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

static void InitKingNormal ()
{
  int a, b, s = 0;
  for (a = A1; a <= H8; a++)
    for (b = A1; b <= H8; b++)
      {
	if (a == b || AttK[a] & SqSet[b])
	  {
	    RE_normale[64 * b + a] = -1;
	    continue;
	  }
	if (!(TRIANGOLO & SqSet[a]))
	  {
	    RE_normale[64 * b + a] = -1;
	    continue;
	  }
	if (MARGINE & SqSet[a] && !(TRI_MAR & SqSet[b]))
	  {
	    RE_normale[64 * b + a] = -1;
	    continue;
	  }
	RE_normale[64 * b + a] = s++;
      }
}

static void InitKingPedone ()
{
  int a, b, s = 0;
  for (a = A1; a <= H8; a++)
    for (b = A1; b <= H8; b++)
      {
	if (a == b || AttK[a] & SqSet[b])
	  {
	    RE_pedone[64 * b + a] = -1;
	    continue;
	  }
	if (FILE (a) >= FE)
	  {
	    RE_pedone[64 * b + a] = -1;
	    continue;
	  }
	RE_pedone[64 * b + a] = s++;
      }
}

static void InitInverse ()
{
  int wK, bK;
  for (wK = A1; wK <= H8; wK++)
    for (bK = A1; bK <= H8; bK++)
      {
	if (RE_normale[64 * wK + bK] != -1)
	  inverso_normale_re[RE_normale[64 * wK + bK]] = (wK << 6) | bK;
	if (RE_pedone[64 * wK + bK] != -1)
	  inverso_pedone_re[RE_pedone[64 * wK + bK]] = (wK << 6) | bK;
      }
}

static void InitDoubleSquare ()
{
  int a, b, s = 0;
  for (a = A1; a <= H8; a++)
    for (b = A1; b < a; b++)
      Sq2Normal[s++] = a | (b << 6);
  s = 0;
  for (a = A2; a <= H7; a++)
    for (b = A2; b < a; b++)
      Sq2Pawn[s++] = a | (b << 6);
  s = 0;
  for (a = A2; a <= H6; a++)
    for (b = A2; b < a; b++)
      Sq2Blocked[s++] = a | (b << 6);
}

static void iniz_triplo3 ()
{
  int a, b, c, s = 0;
  for (a = A1; a <= H8; a++)
    for (b = A1; b < a; b++)
      for (c = A1; c < b; c++)
	Sq3normale[s++] = a | (b << 6) | (c << 12);
  s = 0;
  for (a = A2; a <= H7; a++)
    for (b = A2; b < a; b++)
      for (c = A2; c < b; c++)
	Sq3pedone[s++] = a | (b << 6) | (c << 12);
  s = 0;
  for (a = A2; a <= H6; a++)
    for (b = A2; b < a; b++)
      for (c = A2; c < b; c++)
	Sq3blocked[s++] = a | (b << 6) | (c << 12);
}

static void iniz_quadruplo4 ()
{
  int a, b, c, d, s = 0;
  for (a = A1; a <= H8; a++)
    for (b = A1; b < a; b++)
      for (c = A1; c < b; c++)
	for (d = A1; d < c; d++)
	  Sq4normale[s++] = a | (b << 6) | (c << 12) | (d << 18);
  s = 0;
  for (a = A2; a <= H7; a++)
    for (b = A2; b < a; b++)
      for (c = A2; c < b; c++)
	for (d = A2; d < c; d++)
	  Sq4pedone[s++] = a | (b << 6) | (c << 12) | (d << 18);
  s = 0;
  for (a = A2; a <= H6; a++)
    for (b = A2; b < a; b++)
      for (c = A2; c < b; c++)
	for (d = A2; d < c; d++)
	  Sq4blocked[s++] = a | (b << 6) | (c << 12) | (d << 18);
}

static void iniz_lanc ()
{
  int wK, bK, K1, K2, u, sq;
  for (wK = A1; wK <= H8; wK++)
    for (bK = A1; bK <= H8; bK++)
      {
	K1 = bK;
	K2 = wK;
	u = 0;
	if (FILE (K1) >= FE)
	  {
	    u = 4;
	    LANCnor (4, K1);
	    LANCnor (4, K2);
	  }
	if (RANK (K1) >= R5)
	  {
	    u |= 2;
	    LANCnor (2, K1);
	    LANCnor (2, K2);
	  }
	if (RANK (K1) == FILE (K1) && RANK (K2) > FILE (K2))
	  u |= 1;
	else if (RANK (K1) > FILE (K1))
	  u |= 1;
	oLANC[wK][bK] = u;
      }
  for (sq = A1; sq <= H8; sq++)
    {
      lanc_pedone[0][sq] = sq;
      lanc_pedone[1][sq] = lanc_vert[sq];
      lanc_pedone[2][sq] = lanc_oriz[sq];
      lanc_pedone[3][sq] = (FH - FILE (sq)) + 8 * (R8 - RANK (sq));
    }
}

static void iniz_lanc_normale ()
{
  int i, sq, w;
  for (i = 0; i < 8; i++)
    for (sq = A1; sq <= H8; sq++)
      {
	w = sq;
	if (i & 4)
	  w = lanc_oriz[w];
	if (i & 2)
	  w = lanc_vert[w];
	if (i & 1)
	  w = lanc_diag[w];
	lanc_norm[i][sq] = w;
      }
}

static void InitDoubleSame ()
{
  int i, j;
  for (i = A1; i <= H8; i++)
    for (j = A1; j <= H8; j++)
      {
	STESSO2[i][j] =
	  (i > j) ? (i * (i + 1)) / 2 + j - i : (j * (j + 1)) / 2 + i - j;
      }
}

static void iniz_triplo ()
{
  int i, j, k, mas, mez, min;
  for (i = A1; i <= H8; i++)
    for (j = A1; j <= H8; j++)
      for (k = A1; k <= H8; k++)
	{
	  mas = MAX (MAX (i, j), k);
	  min = MIN (MIN (i, j), k);
	  if (i == mas)
	    mez = MAX (j, k);
	  if (j == mas)
	    mez = MAX (i, k);
	  if (k == mas)
	    mez = MAX (i, j);
	  STESSO3[i][j][k] = (mas * (mas - 1) * (mas - 2)) / 6 +
	                     (mez * (mez + 1)) / 2 - mez + min;
	}
}

static void iniz_quadruplo ()
{
  int i, j, k, l, mas, mez2, mez3, min;
  for (i = A1; i <= H8; i++)
    for (j = A1; j <= H8; j++)
      for (k = A1; k <= H8; k++)
	for (l = A1; l <= H8; l++)
	{
	  mas = MAX (MAX (i, j), MAX (k, l));
	  min = MIN (MIN (i, j), MIN (k, l));
	  if (i == mas)
	    mez2 = MAX (MAX (j, k), l);
	  if (j == mas)
	    mez2 = MAX (MAX (i, k), l);
	  if (k == mas)
	    mez2 = MAX (MAX (i, j), l);
	  if (l == mas)
	    mez2 = MAX (MAX (i, j), k);
	  if (i == min)
	    mez3 = MIN (MIN (j, k), l);
	  if (j == min)
	    mez3 = MIN (MIN (i, k), l);
	  if (k == min)
	    mez3 = MIN (MIN (i, j), l);
	  if (l == min)
	    mez3 = MIN (MIN (i, j), k);
	  STESSO4[i][j][k][l] =
	    (mas * (mas - 1) * (mas - 2) * (mas - 3)) / 24 +
	    (mez2 * (mez2 - 1) * (mez2 - 2)) / 6 +
	    (mez3 * (mez3 - 1)) / 2 + min;
	}
}

static void pila_lanc ()
{
  int pi, sq;
  for (pi = 0; pi < 16; pi++)
    col_scamb[pi] = pi ^ 8;
  col_scamb[0] = 0;
  col_scamb[8] = 8;
  for (sq = A1; sq <= H8; sq++)
    {
      lanc_oriz[sq] = (FH - FILE (sq)) + 8 * RANK (sq);
      lanc_vert[sq] = FILE (sq) + 8 * (R8 - RANK (sq));
      lanc_diag[sq] = 8 * FILE (sq) + RANK (sq);
    }
}

void InitTotalBaseUtility (boolean BUILD)
{
  pila_lanc ();
  strcpy (TOTAL_BASE_DIRECTORY, "RobboTotalBase");
  strcpy (COMPRESSA_PREFISSO, "iCOMP.");
  InitKingNormal ();
  InitKingPedone ();
  InitInverse ();
  InitDoubleSquare ();
  iniz_triplo3 ();
  if (BUILD) iniz_quadruplo4 ();
  iniz_lanc_normale ();
  iniz_lanc ();
  InitDoubleSame ();
  iniz_triplo ();
  if (BUILD) iniz_quadruplo ();
}
