
#include "RobboLito.h"
#include "RobboTotalBase.h"

#ifdef WINDOWS
uint64 GetClock()
{
  return (GetTickCount () * 1000ULL);
}
#else
#include <sys/time.h>
uint64 GetClock ()
{
  uint64 x;
  struct timeval tv;
  gettimeofday (&tv, NULL);
  x = tv.tv_sec;
  x *= 1000000;
  x += tv.tv_usec;
  return x;
}
#endif

static uint64 RAGGIO_NO[64], RAGGIO_SE[64], RAGGIO_SO[64], RAGGIO_NE[64];
static uint64 RAGGIO_N[64], RAGGIO_S[64], RAGGIO_O[64], RAGGIO_E[64];

static void iniz_raggio ()
{
  int sq, tr, co, TR, CO;
  for (sq = A1; sq <= H8; sq++)
    {
      TR = RANK (sq);
      CO = FILE (sq);
      RAGGIO_NE[sq] = 0;
      for (tr = TR, co = CO; tr <= R8 && co <= FH; tr++, co++)
	RAGGIO_NE[sq] |= SqSet[8 * tr + co];
      RAGGIO_NO[sq] = 0;
      for (tr = TR, co = CO; tr <= R8 && co >= FA; tr++, co--)
	RAGGIO_NO[sq] |= SqSet[8 * tr + co];
      RAGGIO_SO[sq] = 0;
      for (tr = TR, co = CO; tr >= R1 && co >= FA; tr--, co--)
	RAGGIO_SO[sq] |= SqSet[8 * tr + co];
      RAGGIO_SE[sq] = 0;
      for (tr = TR, co = CO; tr >= R1 && co <= FH; tr--, co++)
	RAGGIO_SE[sq] |= SqSet[8 * tr + co];
      RAGGIO_N[sq] = 0;
      for (tr = TR; tr <= R8; tr++)
	RAGGIO_N[sq] |= SqSet[8 * tr + CO];
      RAGGIO_S[sq] = 0;
      for (tr = TR; tr >= R1; tr--)
	RAGGIO_S[sq] |= SqSet[8 * tr + CO];
      RAGGIO_O[sq] = 0;
      for (co = CO; co >= FA; co--)
	RAGGIO_O[sq] |= SqSet[8 * TR + co];
      RAGGIO_E[sq] = 0;
      for (co = CO; co <= FH; co++)
	RAGGIO_E[sq] |= SqSet[8 * TR + co];
      RAGGIO_NE[sq] &= ~SqSet[sq];
      RAGGIO_SO[sq] &= ~SqSet[sq];
      RAGGIO_N[sq] &= ~SqSet[sq];
      RAGGIO_S[sq] &= ~SqSet[sq];
      RAGGIO_SE[sq] &= ~SqSet[sq];
      RAGGIO_NO[sq] &= ~SqSet[sq];
      RAGGIO_E[sq] &= ~SqSet[sq];
      RAGGIO_O[sq] &= ~SqSet[sq];
    }
}

static const uint8 EFGH_UNDO12[4][12] =
  { { A2, H2, A3, H3, A4, H4, A5, H5, A6, H6, A7, H7 },
    { B2, G2, B3, G3, B4, G4, B5, G5, B6, G6, B7, G7 },
    { C2, F2, C3, F3, C4, F4, C5, F5, C6, F6, C7, F7 },
    { D2, E2, D3, E3, D4, E4, D5, E5, D6, E6, D7, E7 } };
static const uint8 EFGH_UNDO24[2][24] =
  { { A2, C2, F2, H2, A3, C3, F3, H3, A4, C4, F4, H4,
      A5, C5, F5, H5, A6, C6, F6, H6, A7, C7, F7, H7 },
    { B2, D2, E2, G2, B3, D3, E3, G3, B4, D4, E4, G4,
      B5, D5, E5, G5, B6, D6, E6, G6, B7, D7, E7, G7 } };

void FORZA_POS (RobboTotalBase * TotalBase, uint64 PositionCount,
		tipo_fPOS * fpos, boolean SELF)
{
  int i, rf, m, wK, bK, v, x;
  uint64 n = PositionCount, q, r, sq;
  boolean PEDONE = FALSE;
  int PI[4] = { 0, 0, 0, 0 }, Squ[4] = { 0, 0, 0, 0};

  for (i = 3; i >= 0; i--)
    {
      if (TotalBase->p[i] == wEnumP || TotalBase->p[i] == bEnumP
	  || TotalBase->p[i] == BlockedPawn)
	PEDONE = TRUE;
      DIV (q, n, TotalBase->m[i]);
      r = n - q * TotalBase->m[i];
      sq = r;
      n = q;
      if (TotalBase->p[i] && i < 1 && (TotalBase->p[i]) == (TotalBase->p[i + 3]))
	{
	  if (TotalBase->p[i] == wEnumP || TotalBase->p[i] == bEnumP)
	    m = quad_quat_pedone[sq];
	  else if (TotalBase->p[i] == BlockedPawn)
	    m = quad_quat_blocked[sq];
	  else
	    m = quad_quat_normale[sq];
	  Squ[i] = m & 63;
	  Squ[i + 1] = (m >> 6) & 63;
	  Squ[i + 2] = (m >> 12) & 63;
	  Squ[i + 3] = m >> 18;
	}
      else if (TotalBase->p[i] && i < 2 && (TotalBase->p[i]) == (TotalBase->p[i + 2]))
	{
	  if (TotalBase->p[i] == wEnumP || TotalBase->p[i] == bEnumP)
	    m = quad_tre_pedone[sq];
	  else if (TotalBase->p[i] == BlockedPawn)
	    m = quad_tre_blocked[sq];
	  else
	    m = quad_tre_normale[sq];
	  Squ[i] = m & 63;
	  Squ[i + 1] = (m >> 6) & 63;
	  Squ[i + 2] = m >> 12;
	}
      else if (TotalBase->p[i] && i < 3
	       && (TotalBase->p[i]) == (TotalBase->p[i + 1])
	       && TotalBase->m[i] != 1)
	{
	  if (TotalBase->p[i] == wEnumP || TotalBase->p[i] == bEnumP)
	    m = Sq2Pawn[sq];
	  else if (TotalBase->p[i] == BlockedPawn)
	    m = Sq2Blocked[sq];
	  else
	    m = Sq2Normal[sq];
	  Squ[i] = m & 63;
	  Squ[i + 1] = m >> 6;
	}
      else if (TotalBase->m[i] != 1)
	{
	  if (TotalBase->m[i] == 48 || TotalBase->m[i] == 40)
	    sq += 8;
	  if (TotalBase->m[i] == 10 || TotalBase->m[i] == 12)
	    sq = EFGH_UNDO12[TotalBase->efgh_file[i]][sq];
	  if (TotalBase->m[i] == 24)
	    sq = EFGH_UNDO24[TotalBase->efgh_file[i]][sq];
	  Squ[i] = sq;
	}
    }
  if (PEDONE)
    rf = inverso_pedone_re[n];
  else
    rf = inverso_normale_re[n];
  wK = rf & 63;
  bK = rf >> 6;
  if (SELF)
    {
      for (i = 0; i < 4; i++)
	{
	  fpos->pi[i] = TotalBase->p[i];
	  fpos->sq[i] = Squ[i];
	}
      fpos->wK = bK;
      fpos->bK = wK; /* HACK */
      return;
    }
  for (i = 0; i < 4; i++)
    PI[i] = col_scamb[TotalBase->p[i]];
  fpos->PEDONE = PEDONE;
  if (PEDONE)
    {
      int w = 2 * (FILE (bK) >= FE) + 1;
      for (i = 0; i < 4; i++)
	{
	  LANCpez (w, Squ[i]);
	  if (PI[i] == BlockedPawn)
	    Squ[i] -= 8;
	}
      LANCpez (w, wK);
      LANCpez (w, bK);
      rf = RE_pedone[64 * wK + bK];
    }
  else
    {
      uint8 w = oLANC[wK][bK];
      for (i = 0; i < 4; i++)
	LANCnor (w, Squ[i]);
      LANCnor (w, bK);
      LANCnor (w, wK);
      rf = RE_normale[64 * wK + bK];
    }
  fpos->re_fetta = rf;
  fpos->wK = wK;
  fpos->bK = bK;
  fpos->Occupied = SqSet[wK] | SqSet[bK];
  v = TotalBaseTable[PI[0]][PI[1]][PI[2]][PI[3]];
  for (i = 0; i < 4; i++)
    {
      x = (v >> (16 + 2 * i)) & 3;
      fpos->sq[i] = Squ[x];
      fpos->pi[i] = PI[x];
      if (PI[x])
	fpos->Occupied |= SqSet[Squ[x]];
      if (PI[x] == BlockedPawn)
	fpos->Occupied |= SqSet[Squ[x] + 8];
    }
  fpos->PawnOnFourth = 0;
  for (i = 0; i < 4; i++)
    if (fpos->pi[i] == bEnumP && RANK (fpos->sq[i]) == R4)
      fpos->PawnOnFourth |= SqSet[fpos->sq[i]];
  for (i = 0; i < 4; i++)
    if ((fpos->pi[i] == BlockedPawn && RANK (fpos->sq[i]) == R3))
      fpos->PawnOnFourth |= SqSet[fpos->sq[i] + 8];
  fpos->m[3] = 1;

  for (i = 0; i < 4; i++)
    fpos->rip[i] = 0;
  if (fpos->pi[0] && fpos->pi[0] == fpos->pi[3])
    {
      fpos->rip[0] = fpos->rip[1] = fpos->rip[2] = fpos->rip[3] = 4;
      fpos->rip_ai[0] = 1;
      fpos->rip_ai[1] = 2;
      fpos->rip_ai[2] = 3;
      fpos->rip_ai[3] = 4;
    }
  else if (fpos->pi[0] && fpos->pi[0] == fpos->pi[2])
    {
      fpos->rip[0] = fpos->rip[1] = fpos->rip[2] = 3;
      fpos->rip_ai[0] = 1;
      fpos->rip_ai[1] = 2;
      fpos->rip_ai[2] = 3;
    }
  else if (fpos->pi[1] && fpos->pi[1] == fpos->pi[3])
    {
      fpos->rip[1] = fpos->rip[2] = fpos->rip[3] = 3;
      fpos->rip_ai[1] = 1;
      fpos->rip_ai[2] = 2;
      fpos->rip_ai[3] = 3;
    }
  else
    {
      if (fpos->pi[0] && fpos->pi[0] == fpos->pi[1])
	{
	  fpos->rip[0] = fpos->rip[1] = 2;
	  fpos->rip_ai[0] = 1;
	  fpos->rip_ai[1] = 2;
	}
      if (fpos->pi[1] && fpos->pi[1] == fpos->pi[2])
	{
	  fpos->rip[1] = fpos->rip[2] = 2;
	  fpos->rip_ai[1] = 1;
	  fpos->rip_ai[2] = 2;
	}
      if (fpos->pi[2] && fpos->pi[2] == fpos->pi[3])
	{
	  fpos->rip[2] = fpos->rip[3] = 2;
	  fpos->rip_ai[2] = 1;
	  fpos->rip_ai[3] = 2;
	}
    }

  for (i = 2; i >= 0; i--)
    fpos->m[i] =
      fpos->m[i + 1] * ((TABLE_TOTAL_BASES + (v & 65535))->m[i + 1]);
  fpos->re_fetta_molt = fpos->m[0] * (TABLE_TOTAL_BASES + (v & 65535))->m[0];
  for (i = 0; i < 4; i++)
    Squ[i] = fpos->sq[i]
      - 8 * (fpos->pi[i] == wEnumP || fpos->pi[i] == bEnumP)
      - 8 * (fpos->pi[i] == BlockedPawn);
  for (i = 0; i < 4; i++)
    fpos->efgh_shift[i] = ((TABLE_TOTAL_BASES) + (v & 65535))->efgh_shift[i];
  for (i = 0; i < 4; i++)
    Squ[i] >>= fpos->efgh_shift[i];
  if (fpos->pi[0] && fpos->pi[0] == fpos->pi[3])
    {
      Squ[0] = STESSO4[Squ[0]][Squ[1]][Squ[2]][Squ[3]];
      Squ[1] = Squ[2] = Squ[3] = 0;
    }
  else if (fpos->pi[0] && fpos->pi[0] == fpos->pi[2])
    {
      Squ[0] = STESSO3[Squ[0]][Squ[1]][Squ[2]];
      Squ[1] = Squ[2] = 0;
    }
  else if (fpos->pi[1] && fpos->pi[1] == fpos->pi[3])
    {
      Squ[1] = STESSO3[Squ[1]][Squ[2]][Squ[3]];
      Squ[2] = Squ[3] = 0;
    }
  else
    {
      if (fpos->pi[0] && fpos->pi[0] == fpos->pi[1])
	{
	  Squ[0] = STESSO2[Squ[0]][Squ[1]];
	  Squ[1] = 0;
	}
      if (fpos->pi[1] && fpos->pi[1] == fpos->pi[2])
	{
	  Squ[1] = STESSO2[Squ[1]][Squ[2]];
	  Squ[2] = 0;
	}
      if (fpos->pi[2] && fpos->pi[2] == fpos->pi[3])
	{
	  Squ[2] = STESSO2[Squ[2]][Squ[3]];
	  Squ[3] = 0;
	}
    }
  fpos->ind = 0;
  for (i = 0; i < 4; i++)
    if (PI[i])
      fpos->ind += fpos->m[i] * Squ[i];
  fpos->Double = -1;
  if ((!PEDONE) && RANK (wK) == FILE (wK) && RANK (bK) == FILE (bK))
    {
      for (i = 0; i < 4; i++)
	Squ[i] = lanc_norm[1][fpos->sq[i]];
      if (fpos->pi[0] && fpos->pi[0] == fpos->pi[3])
	{
	  Squ[0] = STESSO4[Squ[0]][Squ[1]][Squ[2]][Squ[3]];
	  Squ[1] = Squ[2] = Squ[3] = 0;
	}
      else if (fpos->pi[0] && fpos->pi[0] == fpos->pi[2])
	{
	  Squ[0] = STESSO3[Squ[0]][Squ[1]][Squ[2]];
	  Squ[1] = Squ[2] = 0;
	}
      else if (fpos->pi[1] && fpos->pi[1] == fpos->pi[3])
	{
	  Squ[1] = STESSO3[Squ[1]][Squ[2]][Squ[3]];
	  Squ[2] = Squ[3] = 0;
	}
      else
	{
	  if (fpos->pi[0] && fpos->pi[0] == fpos->pi[1])
	    {
	      Squ[0] = STESSO2[Squ[0]][Squ[1]];
	      Squ[1] = 0;
	    }
	  if (fpos->pi[1] && fpos->pi[1] == fpos->pi[2])
	    {
	      Squ[1] = STESSO2[Squ[1]][Squ[2]];
	      Squ[2] = 0;
	    }
	  if (fpos->pi[2] && fpos->pi[2] == fpos->pi[3])
	    {
	      Squ[2] = STESSO2[Squ[2]][Squ[3]];
	      Squ[3] = 0;
	    }
	}
      fpos->Double = 0;
      for (i = 0; i < 4; i++)
	if (PI[i])
	  fpos->Double += fpos->m[i] * Squ[i];
    }
}

static char AMMET[64][64];
static void ammet_iniz ()
{
  int sq, to;
  for (sq = A1; sq <= H8; sq++)
    for (to = A1; to <= H8; to++)
      {
	AMMET[sq][to] = (((RANK (to) > RANK (sq)) || (FILE (to) < FILE (sq)))
			 && (to - sq) != 10 && (to - sq) != -17);
	if ((RANK (to) - RANK (sq)) == (FILE (to) - FILE (sq))
	    && RANK (sq) > FILE (sq))
	  AMMET[sq][to] = 0;
      }
}

/********************************/ /********************************/

typedef struct { uint32 rf, pos; } tipo_LIST;
static tipo_LIST* MARCO_LIST[64];
static tipo_LIST* RIMA_LIST[64];
static boolean USE_MARCO_LIST, USE_RIMA_LIST;
static uint64 LIST_PTR[64][8]; /* Fact: Cache Thrash! for the [0] */

static boolean aMARCO (RobboTotalBase * tb, int fetta, uint64 PositionNumber)
{ return emarco (tb->MAR, fetta * tb->PawnMult8 * 8 + PositionNumber); }

static void nonMARCO (RobboTotalBase * tb, int fetta, uint64 PositionNumber)
{ UnSet (tb->MAR, fetta * tb->PawnMult8 * 8 + PositionNumber); }

static boolean eVIT (RobboTotalBase * tb, int fetta, uint64 PositionNumber)
{ return emarco (tb->VIT, fetta * tb->PawnMult8 * 8 + PositionNumber); }

static void aVIT (RobboTotalBase * tb, int fetta, uint64 PositionNumber)
{ Set (tb->VIT, fetta * tb->PawnMult8 * 8 + PositionNumber); }

static boolean ePERD (RobboTotalBase * tb, int fetta, uint64 PositionNumber)
{ return emarco (tb->PER, fetta * tb->PawnMult8 * 8 + PositionNumber); }

static void aPERD (RobboTotalBase * tb, int fetta, uint64 PositionNumber, int cpu)
{
  if (USE_RIMA_LIST)
    {
      RIMA_LIST[cpu][LIST_PTR[cpu][0]].rf = fetta;
      RIMA_LIST[cpu][LIST_PTR[cpu][0]++].pos = PositionNumber;
      if (LIST_PTR[cpu][0] == LIST_SIZE) /* HACK */
	RIMA_LIST[cpu] = realloc (RIMA_LIST[cpu], 2 * sizeof (tipo_LIST) * LIST_SIZE);
      return;
    }
  Set (tb->PER, fetta * tb->PawnMult8 * 8 + PositionNumber);
}

static void zPERD (RobboTotalBase * tb, int fetta, uint64 PositionNumber)
{ UnSet (tb->PER, fetta * tb->PawnMult8 * 8 + PositionNumber); }

static int NUMERO_DI_ITERAZIONE = 0;

static void sottRIMA
(RobboTotalBase* tb, uint64 ind, uint64 fetta, uint64 PositionNumber, int cpu)
{
  uint8 Value;
  Value = tb->data[ind];
  if (Value >= PRIMERA_PERDITA)
    {
      printf ("MAL z:%d %lld/%lld (sottRIMA)\n", Value, fetta, PositionNumber);
      exit (1);
    }
  if (Value == 1)
    {
      aPERD (tb, fetta, PositionNumber, cpu);
      if (NUMERO_DI_ITERAZIONE >= LARGH)
	{
	  uint64 n = (((uint64) fetta) << 32) | PositionNumber;
	  tb->data[ind] = PERD_FINE;
	  tb->supp++;
	  LOCK (FWRITE_LOCK);
	  fwrite (&n, 8, 1, tb->Fsupp);
	  UNLOCK (FWRITE_LOCK);
	}
      else
	tb->data[ind] = PERD_IN (NUMERO_DI_ITERAZIONE);
    }
  else if (Value <= MASSIMO_RIMA)
    tb->data[ind] = Value - 1;
}

/********************************/ /********************************/

static void indice_sini
(uint64 fetta, uint64 PositionNumber,
 RobboTotalBase * LeftTB, RobboTotalBase * RightTB, int cpu)
{
  uint64 ind = fetta * RightTB->PawnMult + PositionNumber;
  ROBBO_LOCK (RightTB, ind >> RightTB->shift);
  sottRIMA (RightTB, ind, fetta, PositionNumber, cpu);
  ROBBO_UNLOCK (RightTB, ind >> RightTB->shift);
}

static void indice_DES
(uint64 fetta, uint64 PositionNumber,
 RobboTotalBase * LeftTB, RobboTotalBase * RightTB, int cpu)
{
  uint64 ind = fetta * 8 * LeftTB->PawnMult8 + PositionNumber;
  ROBBO_LOCK (LeftTB, ind >> LeftTB->shift);
  if (!emarco (LeftTB->VIT, ind))
    {
      Set (LeftTB->VIT, ind);      
      if (USE_MARCO_LIST)
	{
	  MARCO_LIST[cpu][LIST_PTR[cpu][0]].rf = fetta;
	  MARCO_LIST[cpu][LIST_PTR[cpu][0]++].pos = PositionNumber;
	  if (LIST_PTR[cpu][0] == LIST_SIZE) /* HACK */
	    MARCO_LIST[cpu] = realloc (MARCO_LIST[cpu], 2 * sizeof (tipo_LIST) * LIST_SIZE);
	}
      else
	Set (LeftTB->MAR, ind);	
    }
  ROBBO_UNLOCK (LeftTB, ind >> LeftTB->shift);
}

/********************************/ /********************************/

#define DIAGa1h8SOPRA (0xff7f3f1f0f070301)
#define DIAGa1h8SOTTO (0x80c0e0f0f8fcfeff)
#define DIAGa1h8 (0x8040201008040201)
#define DIAGh1a8 (0x0102040810204080)

static void mossaPROCi
(int sq, int b, int i, tipo_fPOS * fpos, int cpu,
 RobboTotalBase * sinRTB, RobboTotalBase * desRTB, boolean simm,
 void (*INDICE) (uint64, uint64, RobboTotalBase *, RobboTotalBase *, int))
{
  uint64 index, Double;
  int to, a1, a2, a3;
  if (simm && !AMMET[sq][b])
    return;
  if (!fpos->rip[i])
    {
      index = fpos->ind + (b - sq) * fpos->m[i];
      Double = 0;
      INDICE (fpos->re_fetta, index, sinRTB, desRTB, cpu);
      if (!fpos->PEDONE && SqSet[fpos->wK] & DIAGa1h8
	  && SqSet[fpos->bK] & DIAGa1h8)
	{
	  Double =
	    fpos->Double + (lanc_norm[1][b] - lanc_norm[1][sq]) * fpos->m[i];
	  if (Double != index || !simm)
	    INDICE (fpos->re_fetta, Double, sinRTB, desRTB, cpu);
	}
    }
  if (fpos->rip[i] == 2)
    {
      if (fpos->rip_ai[i] == 1)
	to = 1;
      else
	to = -1;
      index = fpos->ind + fpos->m[i] * (STESSO2[b][fpos->sq[i + to]] -
					STESSO2[sq][fpos->sq[i + to]]);
      Double = 0;
      INDICE (fpos->re_fetta, index, sinRTB, desRTB, cpu);
      if (!fpos->PEDONE && SqSet[fpos->wK] & DIAGa1h8
	  && SqSet[fpos->bK] & DIAGa1h8)
	{
	  Double = fpos->Double + fpos->m[i] *
	    (STESSO2[lanc_norm[1][b]][lanc_norm[1][fpos->sq[i + to]]] -
	     STESSO2[lanc_norm[1][sq]][lanc_norm[1][fpos->sq[i + to]]]);
	  if (Double != index || !simm)
	    INDICE (fpos->re_fetta, Double, sinRTB, desRTB, cpu);
	}
    }
  if (fpos->rip[i] == 3)
    {
      if (fpos->rip_ai[i] == 1)
	{
	  a1 = 1;
	  a2 = 2;
	}
      if (fpos->rip_ai[i] == 2)
	{
	  a1 = -1;
	  a2 = 1;
	}
      if (fpos->rip_ai[i] == 3)
	{
	  a1 = -2;
	  a2 = -1;
	}
      index = fpos->ind +
	      fpos->m[i] * (STESSO3[b][fpos->sq[i + a1]][fpos->sq[i + a2]] -
			    STESSO3[sq][fpos->sq[i + a1]][fpos->sq[i + a2]]);
      Double = 0;
      INDICE (fpos->re_fetta, index, sinRTB, desRTB, cpu);
      if (!fpos->PEDONE && SqSet[fpos->wK] & DIAGa1h8
	  && SqSet[fpos->bK] & DIAGa1h8)
	{
	  Double = fpos->Double + fpos->m[i] *
	    (STESSO3[lanc_norm[1][b]][lanc_norm[1][fpos->sq[i + a1]]]
	     [lanc_norm[1][fpos->sq[i + a2]]] -
	     STESSO3[lanc_norm[1][sq]][lanc_norm[1][fpos->sq[i + a1]]]
	     [lanc_norm[1][fpos->sq[i + a2]]]);
	  if (Double != index || !simm)
	    INDICE (fpos->re_fetta, Double, sinRTB, desRTB, cpu);
	}
    }
  if (fpos->rip[i] == 4)
    {
      if (fpos->rip_ai[i] == 1)
	{
	  a1 = 1;
	  a2 = 2;
	  a3 = 3;
	}
      if (fpos->rip_ai[i] == 2)
	{
	  a1 = -1;
	  a2 = 1;
	  a3 = 2;
	}
      if (fpos->rip_ai[i] == 3)
	{
	  a1 = -2;
	  a2 = -1;
	  a3 = 1;
	}
      if (fpos->rip_ai[i] == 4)
	{
	  a1 = -3;
	  a2 = -2;
	  a3 = -1;
	}
      index = fpos->ind +
	fpos->m[i] *
	(STESSO4[b][fpos->sq[i + a1]][fpos->sq[i + a2]][fpos->sq[i + a3]] -
	 STESSO4[sq][fpos->sq[i + a1]][fpos->sq[i + a2]][fpos->sq[i + a3]]);
      Double = 0;
      INDICE (fpos->re_fetta, index, sinRTB, desRTB, cpu);
      if (!fpos->PEDONE && SqSet[fpos->wK] & DIAGa1h8 && SqSet[fpos->bK] & DIAGa1h8)
	{
	  Double = fpos->Double + fpos->m[i] *
	    (STESSO4[lanc_norm[1][b]][lanc_norm[1][fpos->sq[i + a1]]]
	     [lanc_norm[1][fpos->sq[i + a2]]][lanc_norm[1][fpos->sq[i + a3]]] -
	     STESSO4[lanc_norm[1][sq]][lanc_norm[1][fpos->sq[i + a1]]]
	     [lanc_norm[1][fpos->sq[i + a2]]][lanc_norm[1][fpos->sq[i + a3]]]);
	  if (Double != index || !simm)
	    INDICE (fpos->re_fetta, Double, sinRTB, desRTB, cpu);
	}
    }
}

static void iMOSSA_PEDONE
(int sq, int b, int i, tipo_fPOS * fpos, int cpu,
 RobboTotalBase * sinRTB, RobboTotalBase * desRTB,
 void (*INDICE) (uint64, uint64, RobboTotalBase *, RobboTotalBase *, int))
{
  int to, a1, a2, a3;
  uint64 index;
  if (!fpos->rip[i])
    {
      index = fpos->ind + ((b - sq) >> fpos->efgh_shift[i]) * fpos->m[i];
      INDICE (fpos->re_fetta, index, sinRTB, desRTB, cpu);
    }
  if (fpos->rip[i] == 2)
    {
      if (fpos->rip_ai[i] == 1)
	to = 1;
      else
	to = -1;
      index = fpos->ind + fpos->m[i] * (STESSO2[b - 8][fpos->sq[i + to] - 8] -
					STESSO2[sq - 8][fpos->sq[i + to] - 8]);
      INDICE (fpos->re_fetta, index, sinRTB, desRTB, cpu);
    }
  if (fpos->rip[i] == 3)
    {
      if (fpos->rip_ai[i] == 1)
	{
	  a1 = 1;
	  a2 = 2;
	}
      if (fpos->rip_ai[i] == 2)
	{
	  a1 = -1;
	  a2 = 1;
	}
      if (fpos->rip_ai[i] == 3)
	{
	  a1 = -2;
	  a2 = -1;
	}
      index = fpos->ind +
	fpos->m[i] *
	(STESSO3[(b) - 8][fpos->sq[i + a1] - 8][fpos->sq[i + a2] - 8] -
	 STESSO3[(sq) - 8][fpos->sq[i + a1] - 8][fpos->sq[i + a2] - 8]);
      INDICE (fpos->re_fetta, index, sinRTB, desRTB, cpu);
    }
  if (fpos->rip[i] == 4)
    {
      if (fpos->rip_ai[i] == 1)
	{
	  a1 = 1;
	  a2 = 2;
	  a3 = 3;
	}
      if (fpos->rip_ai[i] == 2)
	{
	  a1 = -1;
	  a2 = 1;
	  a3 = 2;
	}
      if (fpos->rip_ai[i] == 3)
	{
	  a1 = -2;
	  a2 = -1;
	  a3 = 1;
	}
      if (fpos->rip_ai[i] == 4)
	{
	  a1 = -3;
	  a2 = -2;
	  a3 = -1;
	}
      index = fpos->ind +
	fpos->m[i] *
	(STESSO4[(b) - 8][fpos->sq[i + a1] - 8]
	 [fpos->sq[i + a2] - 8][fpos->sq[i + a3] - 8] -
	 STESSO4[(sq) - 8][fpos->sq[i + a1] - 8]
	 [fpos->sq[i + a2] - 8][fpos->sq[i + a3] - 8]);
      INDICE (fpos->re_fetta, index, sinRTB, desRTB, cpu);
    }
}

static void iMOSSA_RE
(uint64 TARGA, tipo_fPOS * fpos, int cpu,
 RobboTotalBase * sinRTB, RobboTotalBase * desRTB, boolean simm,
 void (*INDICE) (uint64, uint64, RobboTotalBase *, RobboTotalBase *, int))
{
  int j;
  uint64 Double, index;
  while (TARGA)
    {
      int b = BSF (TARGA);
      BitClear (b, TARGA);
      Double = 0;
      if (fpos->PEDONE)
	INDICE (RE_pedone[64 * b + fpos->bK], fpos->ind, sinRTB, desRTB, cpu);
      else
	{
	  if (simm && !AMMET[fpos->wK][b])
	    continue;
	  if (SqSet[fpos->bK] & DIAGa1h8 && SqSet[b] & DIAGa1h8SOPRA)
	    {
	      if (SqSet[b] & DIAGa1h8)
		{
		  INDICE (RE_normale[64 * b + fpos->bK], fpos->ind, sinRTB, desRTB, cpu);
		  for (j = 0; j < 4; j++)
		    if (fpos->pi[j])
		      {
			if (!fpos->rip[j])
			  Double += fpos->m[j] * lanc_norm[1][fpos->sq[j]];
			if (fpos->rip[j] == 2 && fpos->rip_ai[j] == 2)
			  Double += fpos->m[j] *
			              STESSO2[lanc_norm[1][fpos->sq[j]]]
			                     [lanc_norm[1][fpos->sq[j - 1]]];
			if (fpos->rip[j] == 3 && fpos->rip_ai[j] == 3)
			  Double += fpos->m[j] *
			              STESSO3[lanc_norm[1][fpos->sq[j]]]
			                     [lanc_norm[1][fpos->sq[j - 1]]]
			                     [lanc_norm[1][fpos->sq[j - 2]]];
			if (fpos->rip[j] == 4 && fpos->rip_ai[j] == 4)
			  Double += fpos->m[j] *
			              STESSO4[lanc_norm[1][fpos->sq[j]]]
			                     [lanc_norm[1][fpos->sq[j - 1]]]
			                     [lanc_norm[1][fpos->sq[j - 2]]]
			                     [lanc_norm[1][fpos->sq[j - 3]]];
		      }
		  if (Double != fpos->ind || !simm)
		    INDICE (RE_normale[64 * b + fpos->bK],
			    Double, sinRTB, desRTB, cpu);
		}
	      else
		{
		  index = 0;
		  for (j = 0; j < 4; j++)
		    if (fpos->pi[j])
		      {
			if (!fpos->rip[j])
			  index += fpos->m[j] * lanc_norm[1][fpos->sq[j]];
			if (fpos->rip[j] == 2 && fpos->rip_ai[j] == 2)
			  index += fpos->m[j] *
			    STESSO2[lanc_norm[1][fpos->sq[j]]]
			           [lanc_norm[1][fpos->sq[j - 1]]];
			if (fpos->rip[j] == 3 && fpos->rip_ai[j] == 3)
			  index += fpos->m[j] *
			    STESSO3[lanc_norm[1][fpos->sq[j]]]
			           [lanc_norm[1][fpos->sq[j - 1]]]
			           [lanc_norm[1][fpos->sq[j - 2]]];
			if (fpos->rip[j] == 4 && fpos->rip_ai[j] == 4)
			  index += fpos->m[j] *
			    STESSO4[lanc_norm[1][fpos->sq[j]]]
			           [lanc_norm[1][fpos->sq[j - 1]]]
			           [lanc_norm[1][fpos->sq[j - 2]]]
			           [lanc_norm[1][fpos->sq[j - 3]]];
		      }
		  INDICE (RE_normale
			  [64 * lanc_norm[1][b] + lanc_norm[1][fpos->bK]],
			  index, sinRTB, desRTB, cpu);
		}
	    }
	  else
	    INDICE (RE_normale[64 * b + fpos->bK], fpos->ind, sinRTB, desRTB, cpu);
	}
    }
}

/********************************/ /********************************/

static boolean EP_CHECK (int sq, tipo_fPOS* fpos, int dir, uint8 VALU)
{
  int tb, rf, j, w = 0;
  uint64 ind, Double;
  type_PiSq PiSq[1];
  if (fpos->PawnOnFourth & SqSet[sq - dir])
    {
      PiSq->wK = fpos->wK;
      PiSq->bK = fpos->bK;
      PiSq->wtm = TRUE;
      PiSq->pedone = TRUE;
      for (j = 0; j < 4; j++)
	{
	  if (fpos->sq[j] == (sq - dir))
	    {
	      PiSq->pi[w] = fpos->pi[j];
	      PiSq->sq[w++] = sq - 8;
	    }
	  else if (fpos->sq[j] == (sq - 8 - dir) && fpos->pi[j] == BlockedPawn)
	    {
	      PiSq->pi[w] = bEnumP;
	      PiSq->sq[w++] = sq - 8;
	      PiSq->pi[w] = wEnumP;
	      PiSq->sq[w++] = sq - 8 - dir;
	    }
	  else if (fpos->sq[j] != sq)
	    {
	      PiSq->pi[w] = fpos->pi[j];
	      PiSq->sq[w++] = fpos->sq[j];
	    }
	}
      for (j = w; j < 4; j++)
	PiSq->pi[j] = PiSq->sq[j] = 0;
      tot_ind_ott (PiSq, &tb, &ind, &Double, &rf);
      if (tot_valu (TABLE_TOTAL_BASES + tb,
		    rf * (TABLE_TOTAL_BASES + tb)->PawnMult + ind) >= VALU)
	return TRUE;
    }
  return FALSE;
}

/********************************/ /********************************/

#define mossaPROC(sq, b) \
  (w) ? mossaPROCi(sq, b, i, fpos, cpu, Tot1, Tot2, simm, indice_sini) : \
        mossaPROCi(sq, b, i, fpos, cpu, Tot2, Tot1, simm, indice_DES)
#define MOSSA_PEDONE(sq, b) \
  (w) ? iMOSSA_PEDONE(sq, b, i, fpos, cpu, Tot1, Tot2, indice_sini) : \
        iMOSSA_PEDONE(sq, b, i, fpos, cpu, Tot2, Tot1, indice_DES)
#define MOSSA_RE(TARGA) \
  (w) ? iMOSSA_RE(TARGA, fpos, cpu, Tot1, Tot2, simm, indice_sini) : \
        iMOSSA_RE(TARGA, fpos, cpu, Tot2, Tot1, simm, indice_DES)

#define LOOP(TARGA, pros_bit, O) \
  { uint64 T = TARGA; \
    while (T) \
      { int b = pros_bit(T); \
	if (SqSet[b] & O) \
	  break; \
	T &= ~SqSet[b]; \
	mossaPROC(sq, b); } }

static uint16 RIMAP_NORMALE[462], RIMAP_PEDONE[1806];

static int PROC
 (RobboTotalBase* Tot1, RobboTotalBase* Tot2,
  uint64 rf, uint64 PositionNumber, boolean w, int cpu)
{
  int i, sq, pi;
  boolean simm;
  tipo_fPOS fpos[1];
  uint64 RE_TARGA, Occupied;
  FORZA_POS (Tot1, rf * Tot1->PawnMult + PositionNumber, fpos, FALSE);
  Occupied = fpos->Occupied;
  simm = FALSE;
  if (fpos->Double != -1)
    {
      if (fpos->ind < fpos->Double)
	return 0;
      if (fpos->ind == fpos->Double)
	simm = TRUE;
    }
  for (i = 0; i < 4 && fpos->pi[i]; i++)
    {
      if (fpos->pi[i] >= 8)
	continue;
      sq = fpos->sq[i];
      pi = fpos->pi[i];
      if (pi == wEnumP)
	{
	  if (sq >= A3 && !(Occupied & SqSet[sq - 8]))
	    {
	      MOSSA_PEDONE (sq, sq - 8);
	      if (RANK (sq) == R4 && !(Occupied & SqSet[sq - 16]))
		{
		  if (FILE (sq) != FA
		      && EP_CHECK (sq, fpos, 1, w ? dPERD0 : dPATT))
		    continue;
		  if (FILE (sq) != FH
		      && EP_CHECK (sq, fpos, -1, w ? dPERD0 : dPATT))
		    continue;
		  MOSSA_PEDONE (sq, sq - 16);
		}
	    }
	}
      if (pi == wEnumN)
	LOOP (AttN[sq] & ~fpos->Occupied, BSF, 0);
      if (pi == wEnumB || pi == wEnumQ)
	{
	  LOOP (RAGGIO_NO[sq], BSF, Occupied);
	  if (!simm)
	    LOOP (RAGGIO_SE[sq], BSR, Occupied);
	  if (!simm || SqSet[sq] & DIAGa1h8SOTTO)
	    {
	      LOOP (RAGGIO_SO[sq], BSR, Occupied);
	      LOOP (RAGGIO_NE[sq], BSF, Occupied);
	    }
	}
      if (pi == wEnumR || pi == wEnumQ)
	{
	  LOOP (RAGGIO_N[sq], BSF, Occupied);
	  LOOP (RAGGIO_O[sq], BSR, Occupied);
	  if (!simm)
	    {
	      LOOP (RAGGIO_S[sq], BSR, Occupied);
	      LOOP (RAGGIO_E[sq], BSF, Occupied);
	    }
	}
    }
  RE_TARGA = AttK[fpos->wK] & ~AttK[fpos->bK] & ~Occupied;
  MOSSA_RE (RE_TARGA);
  return 1;
}

static sint64 processo_MARCO(RobboTotalBase * Tot1, RobboTotalBase * Tot2,
			     uint64 rf, uint64 NUM, int cpu)
{
  sint64 count = 0;
  uint64 PositionNumber, u;
  if (rf == -1)
    LIST_PTR[cpu][0] = 0;
  if (0 && rf == -1 && NUM)
    printf ("pM: cpu %d NUM %lld\n", cpu, NUM);
  if (rf != -1)
    for (PositionNumber = 0; PositionNumber < Tot1->PawnMult; PositionNumber++)
      {
	if (!aMARCO (Tot1, rf, PositionNumber))
	  continue;
	nonMARCO (Tot1, rf, PositionNumber);
	count += PROC (Tot1, Tot2, rf, PositionNumber, TRUE, cpu);
      }
  else
    {
      for (u = 0; u < NUM; u++)
	{
	  rf = MARCO_LIST[cpu][u].rf;
	  PositionNumber = MARCO_LIST[cpu][u].pos;
	  count += PROC (Tot1, Tot2, rf, PositionNumber, TRUE, cpu);
	}
    }
  return count;
}

static sint64 procRIMA (RobboTotalBase * Tot1, RobboTotalBase * Tot2,
			uint64 rf, uint64 NUM, int cpu)
{
  sint64 count = 0;
  uint64 PositionNumber, u;
  if (rf == -1)
    LIST_PTR[cpu][0] = 0;
  if (0 && rf == -1 && NUM)
    printf ("pR: cpu %d NUM %lld\n", cpu, NUM);
  if (rf != -1)
    for (PositionNumber = 0; PositionNumber < Tot1->PawnMult; PositionNumber++)
      {
	if (!ePERD (Tot1, rf, PositionNumber))
	  continue;
	zPERD (Tot1, rf, PositionNumber);
	count += PROC (Tot1, Tot2, rf, PositionNumber, FALSE, cpu);
      }
  else
    {
      for (u = 0; u < NUM; u++)
	{
	  rf = RIMA_LIST[cpu][u].rf;
	  PositionNumber = RIMA_LIST[cpu][u].pos;
	  count += PROC (Tot1, Tot2, rf, PositionNumber, FALSE, cpu);
	}
    }
  return count;
}

/********************************/ /********************************/

static uint16* RIMAP;
static RobboTotalBase* TOT1;
static RobboTotalBase* TOT2;
static volatile uint64 COUNT = 0;
static MUTEX_TYPE ROBBO_GEN_LOCK[1];
static volatile int CURR_RF;
static int MAX_RF;

void* MARCO_thread (void* A)
{
  int u;
  uint64 v;
  int cpu = *((int*) A);
  if (USE_MARCO_LIST)
    {
      v = processo_MARCO (TOT1, TOT2, -1, LIST_PTR[cpu][0], cpu);
      LOCK (ROBBO_GEN_LOCK);
      COUNT += v;
      UNLOCK (ROBBO_GEN_LOCK);
      return NULL;
    }
  while (TRUE)
    {
      LOCK (ROBBO_GEN_LOCK);
      u = CURR_RF++;
      UNLOCK (ROBBO_GEN_LOCK);
      if (u >= MAX_RF)
	break;      
      v = processo_MARCO (TOT1, TOT2, RIMAP[u], 0, cpu);
      LOCK (ROBBO_GEN_LOCK);
      COUNT += v;
      UNLOCK (ROBBO_GEN_LOCK);
    }
  return NULL;
}

void* RIMA_thread (void* A)
{
  int u;
  uint64 v;
  int cpu = *((int*) A);
  if (USE_RIMA_LIST)
    {
      v = procRIMA (TOT1, TOT2, -1, LIST_PTR[cpu][0], cpu);
      LOCK (ROBBO_GEN_LOCK);
      COUNT += v;
      UNLOCK (ROBBO_GEN_LOCK);
      return NULL;
    }
  while (TRUE)
    {
      LOCK (ROBBO_GEN_LOCK);
      u = CURR_RF++;
      UNLOCK (ROBBO_GEN_LOCK);
      if (u >= MAX_RF)
	break;      
      v = procRIMA (TOT1, TOT2, RIMAP[u], 0, cpu);
      LOCK (ROBBO_GEN_LOCK);
      COUNT += v;
      UNLOCK (ROBBO_GEN_LOCK);
    }
  return NULL;
}

#define LNUM 2
static uint64 LAST_RIMA[64], LAST_MARCO[64];
uint64 fareMARCO (RobboTotalBase * Tot1, int iter, RobboTotalBase * Tot2)
{
  uint64 marco = 0;
  uint64 Clock = GetClock ();
  boolean SMALL, LARGE;
  int cpu;
  int CPU[64];
  for (cpu = 0; cpu < 64; cpu++)
    CPU[cpu] = cpu;
  NUMERO_DI_ITERAZIONE = iter + 1;
  if (NUMERO_DI_ITERAZIONE == LARGH)
    {
      char FN[1024];
      sprintf (FN, "%sSUPP.%s", Tot2->DIR_NOME, Tot2->string);
      Tot2->Fsupp = fopen (FN, "w");
      printf ("LARGH iterazione %d\n", NUMERO_DI_ITERAZIONE);
    }
  if (NUMERO_DI_ITERAZIONE >= LARGH)
    {
      fputc (0xff, Tot2->Fsupp);
      fputc (0xff, Tot2->Fsupp);
      fputc (0xff, Tot2->Fsupp);
      fputc (0xff, Tot2->Fsupp);
      fputc (NUMERO_DI_ITERAZIONE & 255, Tot2->Fsupp);
      fputc ((NUMERO_DI_ITERAZIONE >> 8) & 255, Tot2->Fsupp);
      fputc (0xff, Tot2->Fsupp);
      fputc (0xff, Tot2->Fsupp);
    }
  printf ("Mossa %d\n", iter);
  if (iter == 0)
    USE_MARCO_LIST = FALSE;
  USE_RIMA_LIST = (iter > 0 && Tot1->p[LNUM]);
  for (cpu = 0; cpu < RB_CPUS; cpu++)
    if (LAST_RIMA[cpu] > LIST_SIZE / 2)
      USE_RIMA_LIST = FALSE;
#if 1
  SMALL = LARGE = FALSE;
  for (cpu = 0; cpu < RB_CPUS; cpu++) /* balancia */
    if (LAST_RIMA[cpu] > LIST_SIZE / 4)
      LARGE = TRUE;
  for (cpu = 0; cpu < RB_CPUS; cpu++)
    if (LAST_RIMA[cpu] < LIST_SIZE / 32)
      SMALL = TRUE;
  if (SMALL && LARGE)
    USE_RIMA_LIST = FALSE;
#endif
  CURR_RF = 0;
  MAX_RF = Tot1->PEDONE ? 1806 : 462;
  COUNT = 0;
  TOT1 = Tot1;
  TOT2 = Tot2;
  RIMAP = Tot1->PEDONE ? RIMAP_PEDONE : RIMAP_NORMALE;
  LOCK_INIT (ROBBO_GEN_LOCK);
  for (cpu = 0; cpu < RB_CPUS; cpu++)
    PTHREAD_CREATE (&PTHREAD[cpu], NULL, MARCO_thread, (void*) (CPU + cpu));
  for (cpu = 0; cpu < RB_CPUS; cpu++)
    PTHREAD_JOIN (PTHREAD[cpu]);
  LOCK_DESTROY (ROBBO_GEN_LOCK);
  marco = COUNT;
  printf ("MARCO %lld [%.2fs]%s (iter:%d)\n", marco,
          ((double) (GetClock () - Clock)) / 1000000.0,
	  USE_MARCO_LIST ? "*" : "", iter);
  if (!marco && Tot1->p[LNUM])
    {
      for (cpu = 0; cpu < RB_CPUS; cpu++)
	{
	  free (MARCO_LIST[cpu]);
	  free (RIMA_LIST[cpu]);
	}
    }
  if (USE_RIMA_LIST)
    for (cpu = 0; cpu < RB_CPUS; cpu++)
      LAST_RIMA[cpu] = LIST_PTR[cpu][0];
  else
    for (cpu = 0; cpu < RB_CPUS; cpu++)
      LAST_RIMA[cpu] = (3 * COUNT) / (2 * RB_CPUS);
  return marco;
}

uint64 fareRIMA (RobboTotalBase * Tot1, int iter, RobboTotalBase * Tot2)
{
  int cpu;
  uint64 Clock = GetClock ();
  uint64 rima = 0;
  int CPU[64];
  boolean SMALL, LARGE;
  for (cpu = 0; cpu < 64; cpu++)
    CPU[cpu] = cpu;
  if (iter == 0)
    USE_RIMA_LIST = FALSE;
  if (iter == 0 && Tot1->p[LNUM])
    {
      for (cpu = 0; cpu < RB_CPUS; cpu++)
	{
	  MARCO_LIST[cpu] = malloc (LIST_SIZE * sizeof (tipo_LIST));
	  RIMA_LIST[cpu] = malloc (LIST_SIZE * sizeof (tipo_LIST));
	}
    }
  USE_MARCO_LIST = (iter > 1 && Tot1->p[LNUM]);
  for (cpu = 0; cpu < RB_CPUS; cpu++)
    if (LAST_MARCO[cpu] > LIST_SIZE / 2)
      USE_MARCO_LIST = FALSE;
#if 1
  SMALL = LARGE = FALSE;
  for (cpu = 0; cpu < RB_CPUS; cpu++) /* balancia */
    if (LAST_MARCO[cpu] > LIST_SIZE / 4)
      LARGE = TRUE;
  for (cpu = 0; cpu < RB_CPUS; cpu++)
    if (LAST_MARCO[cpu] < LIST_SIZE / 32)
      SMALL = TRUE;
  if (SMALL && LARGE)
    USE_MARCO_LIST = FALSE;
#endif
  CURR_RF = 0;
  MAX_RF = Tot1->PEDONE ? 1806 : 462;
  COUNT = 0;
  TOT1 = Tot1;
  TOT2 = Tot2;
  RIMAP = Tot1->PEDONE ? RIMAP_PEDONE : RIMAP_NORMALE;
  LOCK_INIT (ROBBO_GEN_LOCK);
  for (cpu = 0; cpu < RB_CPUS; cpu++)
    PTHREAD_CREATE (&PTHREAD[cpu], NULL, RIMA_thread, (void*) (CPU + cpu));
  for (cpu = 0; cpu < RB_CPUS; cpu++)
    PTHREAD_JOIN (PTHREAD[cpu]);
  LOCK_DESTROY (ROBBO_GEN_LOCK);
  rima = COUNT;
  printf ("NON RIMA %lld [%.2fs]%s\n", rima,
          ((double) (GetClock () - Clock)) / 1000000.0, USE_RIMA_LIST ? "*" : "");
  if (USE_MARCO_LIST)
    for (cpu = 0; cpu < RB_CPUS; cpu++)
      LAST_MARCO[cpu] = LIST_PTR[cpu][0];
  else
    for (cpu = 0; cpu < RB_CPUS; cpu++)
      LAST_MARCO[cpu] = (3 * COUNT) / (2 * RB_CPUS);
  return rima;
}

typedef struct
{
  int w, max, min;
  sint16 data[10];
} typeKingPawn;

static int qsort_RE_PEDONE (const void * x, const void * y)
{
  typeKingPawn *a, *b;
  a = (typeKingPawn *) x;
  b = (typeKingPawn *) y;
  if (a->min < b->min)
    return -1;
  if (a->min > b->min)
    return 1;
  if (a->w < b->w)
    return -1;
  if (a->w > b->w)
    return 1;
  return 0;
}

static void iniz_fine_des ()
{
  int c, wK, bK, b, rf, i, t, w, max, min;
  typeKingPawn RE_PEDONE[1806], RE_NORMALE[462];
  for (wK = A1; wK <= H8; wK++)
    for (bK = A1; bK <= H8; bK++)
      {
        rf = RE_pedone[64 * wK + bK];
        if (rf == -1)
          continue;
        uint64 U = (AttK[bK] & ~AttK[wK]) | SqSet[bK];
        c = 0;
        max = 0;
        min = 2000;
        while (U)
          {
            b = BSF (U);
            BitClear (b, U);
            w = 1 + 2 * (FILE (wK) >= FE);
            t = RE_pedone[lanc_pedone[w][b] * 64 + lanc_pedone[w][wK]];
            if (t < min)
              min = t;
            if (t > max)
              max = t;
            RE_PEDONE[rf].data[c++] = t;
          }
        RE_PEDONE[rf].max = max;
        RE_PEDONE[rf].min = min;
        RE_PEDONE[rf].w = rf;
        RE_PEDONE[rf].data[c] = -1;
      }
  qsort (RE_PEDONE, 1806, sizeof (typeKingPawn), qsort_RE_PEDONE);
  for (i = 0; i < 1806; i++)
    RIMAP_PEDONE[i] = RE_PEDONE[i].w;
  for (wK = A1; wK <= H8; wK++)
    for (bK = A1; bK <= H8; bK++)
      {
        uint64 U = (AttK[bK] & ~AttK[wK]) | SqSet[bK];
        rf = RE_normale[64 * wK + bK];
        if (rf == -1)
          continue;
        c = 0;
        max = 0;
        min = 500;
        while (U)
          {
            b = BSF (U);
            BitClear (b, U);
            w = oLANC[b][wK];
            t = RE_normale[lanc_norm[w][b] * 64 + lanc_norm[w][wK]];
            if (t < min)
              min = t;
            if (t > max)
              max = t;
            RE_NORMALE[rf].data[c++] = t;
          }
        RE_NORMALE[rf].max = max;
        RE_NORMALE[rf].min = min;
        RE_NORMALE[rf].w = rf;
        RE_NORMALE[rf].data[c] = -1;
      }
  qsort (RE_NORMALE, 462, sizeof (typeKingPawn), qsort_RE_PEDONE);
  for (i = 0; i < 462; i++)
    RIMAP_NORMALE[i] = RE_NORMALE[i].w;
}

void iniz_vario ()
{
  iniz_raggio ();
  ammet_iniz ();
  iniz_fine_des ();
}
