
#include "RobboLito.h"
#include "RobboTripleBase.h"
#include <string.h>
#include "RobboTotalBase.h"
#include <pthread.h>
#include "Robbo_gen_mossa.h"

void un_windows_triple (char *A)
{
  int s = strlen (A);
  if (A[1] == 'w')
    A[0] = A[2] - 32;
  if (A[1] == 'b')
    A[0] = A[2];
  if (s > 3 && A[3] == 'w')
    A[1] = A[4] - 32;
  if (s > 3 && A[3] == 'b')
    A[1] = A[4];
  if (s > 5 && A[5] == 'w')
    A[2] = A[6] - 32;
  if (s > 5 && A[5] == 'b')
    A[2] = A[6];
  if (s > 7 && A[7] == 'w')
    A[3] = A[7] - 32;
  if (s > 7 && A[7] == 'b')
    A[3] = A[7];
  A[s >> 1] = 0;
}

static char ENUMn[65] =
  { A1, A2, B1, B2, A3, A4, B3, B4, C1, C2, D1, D2, C3, C4, D3, D4,
    A8, A7, B8, B7, A6, A5, B6, B5, C8, C7, D8, D7, C6, C5, D6, D5,
    H1, H2, G1, G2, H3, H4, G3, G4, F1, F2, E1, E2, F3, F4, E3, E4,
    H8, H7, G8, G7, H6, H5, G6, G5, F8, F7, E8, E7, F6, F5, E6, E5, -1 };
static char ENUM0[2] = { -2, -1 };

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

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

static char ENUM_ALF[65] =
  { A1, A3, B2, C1, A5, B4, C3, D2, E1, A7, B6, C5, D4, E3, F2, G1,
    B8, C7, D6, E5, F4, G3, H2, D8, E7, F6, G5, H4, F8, G7, H6, H8,
    H1, H3, G2, F1, H5, G4, F3, E2, D1, H7, G6, F5, E4, D3, C2, B1,
    G8, F7, E6, D5, C4, B3, A2, E8, D7, C6, B5, A4, C8, B7, A6, A8, -1 };

static char ENUM_BLOCKED[41] =
  { A2, B2, C2, D2, E2, F2, G2, H2, A3, B3, C3, D3, E3, F3, G3, H3,
    A4, B4, C4, D4, E4, F4, G4, H4, A5, B5, C5, D5, E5, F5, G5, H5,
    A6, B6, C6, D6, E6, F6, G6, H6, -1 };

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

static char ENUM_UVWX[4][11] =
  { { A2, H2, A3, H3, A4, H4, A5, H5, A6, H6, -1 },
    { B2, G2, B3, G3, B4, G4, B5, G5, B6, G6, -1 },
    { C2, F2, C3, F3, C4, F4, C5, F5, C6, F6, -1 },
    { D2, E2, D3, E3, D4, E4, D5, E5, D6, E6, -1 } };

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

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

#define fputI(u, a, F) \
  { int _j; for (_j = 0; _j < u; _j++) fputc ( ((a) >> (8 * _j)) & 255, F); }

#define MEMORIA_CONTROL(A, pro, c, N) \
  { if (c > pro - 10) { pro += pro / 4; A = realloc (A, pro * N); } }
#define PROSSIMO(u) E[w++] = u; if ( (w % PROP) == 0) ok = FALSE;
#define BYTEw(r, ff, tr) \
  { uint8 by = r % 32; ok = TRUE; \
    if (r >= 32) by += 128; if (tr) by += 64; if (ff) by += 32; PROSSIMO(by); \
    r -= (r % 32); r >>= 5; \
    while (r && ok) { by = ( r >= 128 ) * 128 + ( r % 128 ); \
                      r -= ( r % 128 ); r >>= 7; PROSSIMO(by); } }

#define SetVal(ARR, loc, v) \
  { ARR[(loc) >> 2] |= ((v) << (2 * ((loc) & 3)) ); (loc)++; }
#define GetVal(ARR, i) (((ARR[(i) >> 2]) >> (2 * ((i) & 3))) & 3)

int HopTable (uint32* TABLE, TypeSymbols* SYM);
int GetHuffmannData (uint8* DATA, int nb, TypeSymbols* SYMBOLS);

static void ReDoHuffman (uint32* L, int l, TypeSymbols* SYMBOLS, int* AB,
			 uint32* rw, uint32* rIi, uint8* E, uint32 *I)
{
  int last = 0, first = 0;
  int i = 0, run, k;
  uint8 val;
  uint32 index = 0, w = 0, Ii = 1;
  boolean tr, flip;
  int BYTE = 0, BIT = 0, sz, B[8], a, b;
  uint32 rr;
  while (i < l) /* l as size of RLE encoded array */
    {
      run = L[i] >> 2; /* length of run */
      val = L[i] & 3; /* value */
      index += run;
      if (!last) /* first */
	{
	  if (val != AB[1])
	    first = last = AB[1];
	  else
	    first = last = AB[2]; /* HACK no AB[3] */
	}
      if (last == AB[1])
	{
	  if (val == AB[2])
	    tr = FALSE;
	  else
	    tr = TRUE;
	}
      else
	{
	  if (val == AB[1])
	    tr = FALSE;
	  else
	    tr = TRUE;
	}
      flip = FALSE;
      if (run == 1 && i > 0 && i < l - 1 && (L[i - 1] & 3) == (L[i + 1] & 3))
	{
	  flip = TRUE;
	  run = L[i + 1] >> 2;
	  val = L[i + 1] & 3;
	}
    CHOP_OFF:
      k = (run & 0x1f) | (flip ? 0x20 : 0) | (tr ? 0x40 : 0);
      b = 0;
      B[b++] = k;
      if (run >= 0x20)
	{
	  b--;
	  B[b++] = k | 0x80;
	  sz = SYMBOLS[k | 0x80].len;
	  rr = run >> 5; /* net */
	  while (rr >= 0x80)
	    {
	      B[b++] = (rr & 0x7f) | 0x80;
	      sz += SYMBOLS[(rr & 0x7f) | 0x80].len;
	      rr = rr >> 7;
	    }
	  sz += SYMBOLS[rr].len;
	  B[b++] = rr;
	}
      else
	sz = SYMBOLS[k].len;
      if (sz + 8 * (BYTE & 0x3f) + BIT > 0x40 * 8)
	{
	  if (flip) /* UnDo */
	    {
	      flip = FALSE;
	      run = L[i] >> 2; /* 1 */ /* owns alphabet symbol ? */ /* plus !! */
	      val = L[i] & 3;
	      goto CHOP_OFF;
	    }
	  BIT = 0;
	  BYTE++;
	  if (BYTE & 0x3f)
	    for (w = BYTE & 0x3f; w < 0x40; w++)
	      E[BYTE++] = 0;
	  I[Ii++] = (index << 2) | val;

	}
      for (a = 0; a < b; a++)
	{
	  int t = SYMBOLS[B[a]].len + BIT;
	  int v = SYMBOLS[B[a]].bits;
	  int z = BIT;
	  while (t >= 8)
	    {
	      E[BYTE++] |= (v << z) & 0xff;
	      v >>= (8 - z);
	      z = 0;
	      t -= 8;
	    }
	  E[BYTE] |= (v << z);
	  BIT = t;
	}
      if (flip)
	i++;
      else
	last = val;
      i++;
    }
  if (BIT)
    BYTE++;
  if (BYTE & 0x3f)
    for (i = BYTE & 0x3f; i < 0x40; i++) /* fill */
      E[BYTE++] = 0;
  *rw = BYTE;
  *rIi = Ii;
}

static int BuildArray (uint32* L, int l, uint32 c, int* AB, int PROP,
		       uint32 *rw, uint32 *rIi, uint8* *rE, uint32* *rI)
{
  int Epr = 32 + c / 1024, Ipr = 32 + c / 1024, last = 0, first = 0;
  int i = 0, run;
  uint8 val;
  uint32 index = 0, w = 0, Ii = 1;
  uint8* E;
  uint32* I;
  boolean tr, flip, ok = FALSE;
  E = *rE;
  I = *rI;
  while (i < l) /* l as size of RLE encoded array */
    {
      run = L[i] >> 2; /* length of run */
      val = L[i] & 3; /* value */
      index += run;
      if (!last) /* first */
	{
	  if (val != AB[1])
	    first = last = AB[1];
	  else
	    first = last = AB[2]; /* HACK no AB[3] */
	}
      if (last == AB[1])
	{
	  if (val == AB[2])
	    tr = FALSE;
	  else
	    tr = TRUE;
	}
      else
	{
	  if (val == AB[1])
	    tr = FALSE;
	  else
	    tr = TRUE;
	}
      flip = FALSE;
      if (run == 1 && i > 0 && i < l - 1 && (L[i - 1] & 3) == (L[i + 1] & 3)
	  && (w % PROP)) /* flip for run length 1 */ /* Huffman compatible? */
	{
	  flip = TRUE;
	  run = L[++i] >> 2;
	  val = L[i] & 3;
	  index += run;
	}
      else
	last = val;
      BYTEw (run, flip, tr); /* encode byte into E array as E[w++] */
      i++;
      MEMORIA_CONTROL (E, Epr, w, 1);
      if ((w % PROP) == 0) /* demonstrate index on 64-byte boundary */
	{
	  I[Ii++] = (index << 2) | val; /* index and value as 2 bits */
	  MEMORIA_CONTROL (I, Ipr, Ii, 4);
	}
    }
  for (i = w % PROP; i < PROP; i++) /* fill as zeroes */
    {
      E[w++] = 0;
      MEMORIA_CONTROL (E, Epr, w, 1);
    }
  *rE = E; /* reform */
  *rI = I;
  *rw = w;
  *rIi = Ii;
  return first;
}

typedef struct {uint8* DATA[1806]; int ctl, ctf; int fettas, limit;} typeDO;

#define NextVal(DO, reg) \
  { reg = GetVal (DO->DATA[DO->ctf], DO->ctl); \
    DO->ctl++; if (DO->ctl == DO->limit) { DO->ctl = 0; DO->ctf++; } }

void Internal_RLE (typeDO* DATA_ORGANIZER, int* AB, int PROP, uint32 c,
		   uint8* *rE, uint32* *rI, uint32 *rw, uint32 *rIi,
		   uint32* *HUFFMANN_HOP)
{
  uint32* L;
  uint32* I;
  uint8* E;
  uint32 Ii;
  int prev, va;
  int last, first;
  int l = 0, run = 0;
  uint32 w = 0;
  int i;
  int Lpr = 32 + c / 1024;
  int Epr = 32 + c / 1024, Ipr = 32 + c / 1024;

  E = malloc (Epr);
  I = malloc (Ipr * sizeof (uint32));
  L = malloc (Lpr * sizeof (uint32));
  Ii = 1;
  NextVal (DATA_ORGANIZER, prev);
  for (i = 1; i < c; i++)
    {
      NextVal (DATA_ORGANIZER, va);
      if (prev == va)
	{
	  run++;
	  continue;
	}
      run++;
      L[l++] = (run << 2) + prev;
      MEMORIA_CONTROL (L, Lpr, l, 4);
      prev = va;
      run = 0;
    }
  run++;
  L[l++] = (run << 2) + prev; /* HACK overflow last index */
  i = 0;
  last = 0;
  first = 0;
  first = BuildArray (L, l, c, AB, PROP, &w, &Ii, &E, &I);
  if ((*HUFFMANN_HOP) && (w <= 0x40000))
    {
      free (*HUFFMANN_HOP);
      *HUFFMANN_HOP = NULL;
    }
  if (*HUFFMANN_HOP) /* anti */
    {
      TypeSymbols SYMBOLS[256];
      GetHuffmannData (E, w, SYMBOLS);
      for (i = 0; i < w; i++)
	E[i] = 0; /* HACK */
      HopTable (*HUFFMANN_HOP, SYMBOLS);
      ReDoHuffman (L, l, SYMBOLS, AB, &w, &Ii, E, I); /* HACK */
    }
  free (L);
  I[0] = (0 << 2) | first; /* bugfix */
  if (c == (1 << 30))
    I[Ii] = (0x3fffffffULL << 2) | 0; /* BUG: overflow giga */
  else
    I[Ii] = (c << 2) | 0; /* consistent */
  *rE = E; /* reform */
  *rI = I;
  *rw = w;
  *rIi = Ii; /* plus one? */
}


#define END_NOTE  (0x3fffffffULL << 2) | 0
static int ReIndex (uint32* INDEX, uint32 n, uint32* RE_INDEX)
{
  int u, u2, v, c = 0, lim1, lim2;
  lim1 = (n + 255) / 0x100;
  for (u = 0; u < lim1; u++)
    RE_INDEX[c++] = INDEX[0x100 * u];
  for (u = lim1; u < 0x10; u++)
    RE_INDEX[c++] = END_NOTE;
  for (u = 0; u < 0x10; u++)
    RE_INDEX[c++] = 32 + 32 * u; /* jump */ /* HACK */
  lim2 = (n + 15) / 0x10;
  for (v = 0; v < lim1; v++)
    {
      for (u = 0; u < 0x10 && u2 < lim2; u++, u2++)
	RE_INDEX[c++] = INDEX[0x10 * u2];
      for (; u < 0x10; u++)
	RE_INDEX[c++] = END_NOTE;
      for (u = 0; u < 0x10; u++)
	RE_INDEX[c++] = 0x10 * (u + v * 0x10) + 32 * (lim1 - v);
    }
  for (u = 0; u < n; u++)
    RE_INDEX[c++] = INDEX[u];
  for (u = n; u < 0x10 * lim2; u++)
    RE_INDEX[c++] = END_NOTE;
  return c;
}

typedef struct
{
  uint32 level_count;
  uint32* LEVEL_INDEX;
  uint32* PACKET_OFFSET;
  uint32* PACKET_INDEX_SIZE;
  uint32* PACKET_DATA_SIZE;
  uint32** PACKET_INDEX;
  uint8** PACKET_DATA;
} type_Handler;

static void RePacket
(uint8* DATA, uint32* INDEX, uint32 data_size, type_Handler* H)
{
  int u, j, ic;
  u = H->level_count = 1 + data_size / 0x40000;
  H->LEVEL_INDEX = malloc (u * sizeof (uint32));
  for (j = 0; j < u; j++)
    H->LEVEL_INDEX[j] = INDEX[j * 0x1000];
  H->PACKET_INDEX_SIZE = malloc (u * sizeof (uint32));
  H->PACKET_DATA_SIZE = malloc (u * sizeof (uint32));
  H->PACKET_OFFSET = malloc (u * sizeof (uint32));
  H->PACKET_DATA = malloc (u * sizeof (uint8*));
  H->PACKET_INDEX = malloc (u * sizeof (uint32*));
  for (j = 0; j < u; j++)
    {
      H->PACKET_DATA_SIZE[j] = MIN (0x40000, data_size - j * 0x40000);
      H->PACKET_DATA[j] = DATA + (j * 0x40000);
      ic = (H->PACKET_DATA_SIZE[j] + 0x3f) / 0x40;
      H->PACKET_INDEX[j] = malloc (0x1220 * sizeof (uint32));
      H->PACKET_INDEX_SIZE[j] =
	ReIndex (INDEX + (j * 0x1000), ic, H->PACKET_INDEX[j]);
    }
}

static void DynamicRLE
(typeDO* DATA_ORGANIZER, int* AB, int PROP, uint64 c, FILE* F, uint8 OPTIONINGS)
{
  int heaps, i, j, k;
  uint8* E[8];
  uint32* I[8];
  uint32* HOPS[8];
  uint32 w[8], Ii[8], hop_size[8];
  uint64 sz, offset;
  type_Handler H[8];

  if (PROP != 0x40)
    SEND ("PROP demands 0x40 in DynamicRLE\n");
  heaps = 1 + (c >> 30);
  for (i = 0; i < heaps; i++)
    {
      if (i == heaps - 1)
	sz = c & 0x3fffffff;
      else
	sz = (1ULL << 30);
      printf ("heap %i size %lld\n", i, sz);
#if 0
      HOPS[i] = malloc (0x10000 * sizeof (uint32));
#else
      HOPS[i] = NULL; /* unhappy */
#endif
      Internal_RLE (DATA_ORGANIZER, AB, PROP, sz, &E[i], &I[i], &w[i], &Ii[i], &HOPS[i]);
      if (HOPS[i])
	for (j = 0; HOPS[i][j] != 0x87654321; j++);
      else
	j = 0;
      hop_size[i] = j;
      RePacket (E[i], I[i], w[i], &H[i]);
    }
  fputc (AB[1], F);
  fputc (AB[2], F);
  fputc (AB[3], F);
  fputc (ROBBO_SCACCO_KNOW_BIT | OPTIONINGS, F); /* DYNAMIC_LOAD */
  fputc (0x53, F);
  fputc (0xa1, F);
  fputc (0x78, F);
  fputc (0x0e, F);
  fputc (0x40, F);
  fputc (0x00, F);
  fputc (18, F);
  fputc (heaps, F);
  fputI (4, 0, F); /* NULL bytes 0xc:0xf */
  offset = 16; /* first */
  for (i = 0; i < heaps; i++)
    offset += 4 + H[i].level_count * (4 + 4); /* giga split */
  for (i = 0; i < heaps; i++) /* Huffman */
    offset += (HOPS[i] ? 8 : 0) + hop_size[i] * 4;
  for (i = 0; i < heaps; i++)
    for (j = 0; j < H[i].level_count; j++)
      {
	H[i].PACKET_OFFSET[j] = offset;
	offset += 12 + 4 * H[i].PACKET_INDEX_SIZE[j] + H[i].PACKET_DATA_SIZE[j];
      }
  for (i = 0; i < heaps; i++)
    {
      fputI (4, H[i].level_count | (HOPS[i] ? 0x10000000 : 0), F);
      for (j = 0; j < H[i].level_count; j++)
	fputI (4, H[i].LEVEL_INDEX[j], F);
      free (H[i].LEVEL_INDEX);
      for (j = 0; j < H[i].level_count; j++)
	fputI (4, H[i].PACKET_OFFSET[j], F);      
      free (H[i].PACKET_OFFSET);
      if (HOPS[i])
	{
	  fputc (0x93, F);
	  fputc (0x06, F);
	  fputc (0xe1, F);
	  fputc (0x88, F);
	  fputI (4, hop_size[i], F); /* Filling! */
	  for (j = 0; j < hop_size[i]; j++)
	    fputI (4, HOPS[i][j], F);
	  free (HOPS[i]);
	}
    }
  for (i = 0; i < heaps; i++)
    {
      for (j = 0; j < H[i].level_count; j++)
	{
	  fputc (0xf2, F);
	  fputc (0x77, F);
	  fputc (0x83, F);
	  fputc (0x83, F);
	  fputI (4, H[i].PACKET_INDEX_SIZE[j], F);
	  fputI (4, H[i].PACKET_DATA_SIZE[j], F);
	  for (k = 0; k < H[i].PACKET_INDEX_SIZE[j]; k++)
	    fputI (4, H[i].PACKET_INDEX[j][k], F);
	  free (H[i].PACKET_INDEX[j]);
	  for (k = 0; k < H[i].PACKET_DATA_SIZE[j]; k++)
	    fputc (H[i].PACKET_DATA[j][k], F); /* fwrite buys the macro? */
	}
      free (H[i].PACKET_INDEX_SIZE);
      free (H[i].PACKET_DATA_SIZE);
      free (H[i].PACKET_INDEX);
      free (H[i].PACKET_DATA);
      free (E[i]);
      free (I[i]);
    }
  fclose (F);
}

static void rle (typeDO* DATA_ORGANIZER, uint64 c, char* NOME, uint64* C, uint8 OPTIONINGS)
{
  uint8* E;
  uint32* I;
  int i;
  uint32 w = 0;
  char FN[256];
  int A[4], AB[4];
  uint32 Ii = 0, PROP;
  FILE* F;
  char TEMP[32];
  uint32* NULL_POINTER[1];

  PROP = (OPTIONINGS & ROBBO_DYNAMIC_LOAD) ? 64 : 16; /* HACK */
  if (C[1] > C[2])
    {
      if (C[3] > C[1])
	{
	  A[3] = 1;
	  A[1] = 2;
	  A[2] = 3;
	}
      else if (C[3] > C[2])
	{
	  A[1] = 1;
	  A[3] = 2;
	  A[2] = 3;
	}
      else
	{
	  A[1] = 1;
	  A[2] = 2;
	  A[3] = 3;
	}
    }
  else
    {
      if (C[3] > C[2])
	{
	  A[3] = 1;
	  A[2] = 2;
	  A[1] = 3;
	}
      else if (C[3] > C[1])
	{
	  A[2] = 1;
	  A[3] = 2;
	  A[1] = 3;
	}
      else
	{
	  A[2] = 1;
	  A[1] = 2;
	  A[3] = 3;
	}
    }
  for (i = 1; i <= 3; i++)
    AB[A[i]] = i;
  if (C[AB[2]] == 0)
    {
      printf ("Sole result %d\n", AB[1]);
      strcpy(TEMP, NOME);
      if (TEMP[0] == 'K' || TEMP[0] =='k')
	un_windows_triple (TEMP);
      sprintf (FN, "%s/%d/%s0.%s", TRIPLE_DIR, (int) strlen (TEMP) + 2,
	       TRIPLE_PREFISSO, NOME);
      F = fopen (FN, "w");
      fputc (AB[1], F);
      fputc (0, F);
      fclose (F);
      F = NULL;
      return;
    }
  strcpy (TEMP, NOME);
  if (TEMP[0] == 'K' || TEMP[0]=='k')
    un_windows_triple (TEMP);
  sprintf (FN, "%s/%d/%s%d.%s", TRIPLE_DIR,
	   ((int) strlen (TEMP)) + 2, TRIPLE_PREFISSO, OPTIONINGS, NOME);
  F = fopen (FN, "w");
  if (OPTIONINGS & ROBBO_DYNAMIC_LOAD)
    {
      DynamicRLE (DATA_ORGANIZER, AB, PROP, c, F, OPTIONINGS);
      return;
    }
  NULL_POINTER[0] = NULL;
  Internal_RLE (DATA_ORGANIZER, AB, PROP, c, &E, &I, &w, &Ii, NULL_POINTER);
  fputc (AB[1], F);
  fputc (AB[2], F);
  fputc (AB[3], F);
  fputc (ROBBO_SCACCO_KNOW_BIT | OPTIONINGS, F); /* DYNAMIC_LOAD */
  fputI (4, w, F); /* ENDIAN ok */
  fputI (4, c, F); /* ENDIAN ok */ /* ignored */
  fputI (2, PROP, F); /* ENDIAN ok */
  fputc (0, F);
  fputc (0, F);
  for (i = 0; i < Ii; i++)
    fputI (4, I[i], F); /* ENDIAN ok */
  free (I);
  for (i = 0; i < w; i++)
    fputc (E[i], F);
  fflush (F);
  fclose (F);
  free (E);
  F = NULL;
}

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

#define wEnumB wEnumBL
#define bEnumB bEnumBL

const short int *WORLD_PILA;
char *E[4];
char PEZZO[4];
int OPTIONINGS;

void TripleMakeSMP(typePOS* POSITION, int rf, uint8* TH)
{
  int bK, wK, move, to, fr, pr, pi, cp;
  int L[4], v[4];
  int i, s, u, vc;
  int MODO = vNON;
  uint64 O;
  typeMoveList LIST[256], *list;
  uint64 w = 0;

  if (WORLD_PILA == RE_normale)
    {
      wK = inverso_normale_re[rf] >> 6;
      bK = inverso_normale_re[rf] & 63;
    }
  if (WORLD_PILA == RE_pedone)
    {
      wK = inverso_pedone_re[rf] >> 6;
      bK = inverso_pedone_re[rf] & 63;
    }
  if (PEZZO[2] && (WORLD_PILA[64 * wK + bK] & 15) == 0)
    printf ("%c%c %c%c %lld %d\n", (wK & 7) + 'a', (wK / 8) + '1',
	    (bK & 7) + 'a', (bK / 8) + '1', w, WORLD_PILA[64 * wK + bK]);
  for (L[0] = 0; (v[0] = E[0][L[0]]) != -1; L[0]++)
    for (L[1] = 0; (v[1] = E[1][L[1]]) != -1; L[1]++)
      for (L[2] = 0; (v[2] = E[2][L[2]]) != -1; L[2]++)
	for (L[3] = 0; (v[3] = E[3][L[3]]) != -1; L[3]++)
	  {
	    if (PEZZO[1] && PEZZO[0] == PEZZO[1] && L[1] >= L[0])
	      continue;
	    if (PEZZO[2] && PEZZO[1] == PEZZO[2] && L[2] >= L[1])
	      continue;
	    if (PEZZO[3] && PEZZO[2] == PEZZO[3] && L[3] >= L[2])
	      continue;
	    POSITION->wKsq = wK;
	    POSITION->bKsq = bK;
	    wBitboardK = SqSet[wK];
	    bBitboardK = SqSet[bK];
	    wBitboardQ = wBitboardR = wBitboardN = wBitboardBD =
	      wBitboardBL = wBitboardP = 0;
	    bBitboardQ = bBitboardR = bBitboardN = bBitboardBD =
	      bBitboardBL = bBitboardP = 0;
	    for (i = 0; i < 4; i++)
	      {
		if (PEZZO[i] != BlockedPawn)
		  POSITION->bitboard[PEZZO[i]] |= SqSet[v[i]];
		else
		  {
		    POSITION->bitboard[wEnumP] |= SqSet[v[i]];
		    POSITION->bitboard[bEnumP] |= SqSet[v[i] + 8];
		  }
	      }		
	    wBitboardOcc = wBitboardP | wBitboardN | wBitboardB |
	      wBitboardR | wBitboardQ | wBitboardK;
#ifndef MAGIC_BITBOARDS
	    POSITION->OccupiedL90 = POSITION->OccupiedL45 =
	      POSITION->OccupiedR45 = 0;
#endif
	    bBitboardOcc = bBitboardP | bBitboardN | bBitboardB |
	      bBitboardR | bBitboardQ | bBitboardK;
	    O = wBitboardOcc | bBitboardOcc;
	    POSITION->OccupiedBW = O;
	    for (i = 0; i < 4; i++)
	      {
		if (PEZZO[i] && PEZZO[i] != BlockedPawn)
		  POSITION->sq[v[i]] = PEZZO[i];
		if (PEZZO[i] == BlockedPawn)
		  {
		    POSITION->sq[v[i]] = wEnumP;
		    POSITION->sq[v[i] + 8] = bEnumP;
		  }
		if (PEZZO[i] == wEnumB && SqSet[v[i]] & LIGHT)
		  POSITION->sq[v[i]] = wEnumBL;
		if (PEZZO[i] == wEnumB && SqSet[v[i]] & DARK)
		  POSITION->sq[v[i]] = wEnumBD;
		if (PEZZO[i] == bEnumB && SqSet[v[i]] & LIGHT)
		  POSITION->sq[v[i]] = bEnumBL;
		if (PEZZO[i] == bEnumB && SqSet[v[i]] & DARK)
		  POSITION->sq[v[i]] = bEnumBD;
	      }
	    POSITION->wtm = TRUE;
	    POSITION->sq[POSITION->wKsq] = wEnumK;
	    POSITION->sq[POSITION->bKsq] = bEnumK;
#ifndef MAGIC_BITBOARDS
	    while (O)
	      {
		b = BSF (O);
		POSITION->OccupiedL90 |= SqSet[Left90[b]];
		POSITION->OccupiedL45 |= SqSet[Left45[b]];
		POSITION->OccupiedR45 |= SqSet[Right45[b]];
		BitClear (b, O);
	      }
#endif
	    POSITION->wtm = TRUE;
	    Mobility (POSITION);
#define IN_CHECK (wBitboardK & POSITION->DYN->bAtt)
	    if ((OPTIONINGS & ROBBO_SCACCO_BIT) && IN_CHECK)
	      {
		SetVal (TH, w, MODO);
		goto LOOP;
	      }

#define IS_ILLEGAL \
  (POSITION->wtm ? \
   (bBitboardK & POSITION->DYN->wAtt) : (wBitboardK & POSITION->DYN->bAtt) )
#define BAD \
  ( (PEZZO[1] && v[0] == v[1]) || (PEZZO[2] && v[0] == v[2]) || \
    (PEZZO[3] && v[0] == v[3]) || (PEZZO[2] && v[1] == v[2]) || \
    (PEZZO[3] && v[1] == v[3]) || (PEZZO[3] && v[2] == v[3]) || \
    (v[0] == POSITION->wKsq) || (v[1] == POSITION->wKsq) || \
    (v[2] == POSITION->wKsq) || (v[3] == POSITION->wKsq) || \
    (v[0] == POSITION->bKsq) || (v[1] == POSITION->bKsq) || \
    (v[2] == POSITION->bKsq) || (v[3] == POSITION->bKsq) || \
    (PEZZO[0] == BlockedPawn && PEZZO[1] == BlockedPawn \
     && (v[0] == v[1] + 1) && FILE (v[1]) != FH)  || \
    (PEZZO[1] == BlockedPawn && PEZZO[2] == BlockedPawn \
     && (v[1] == v[2] + 1) && FILE (v[2]) != FH)  || \
    (PEZZO[2] == BlockedPawn && PEZZO[3] == BlockedPawn \
     && (v[2] == v[3] + 1) && FILE (v[3]) != FH)  || \
    (PEZZO[0] == BlockedPawn && \
     ((v[0] + 8) == v[1] || (v[0] + 8 == v[2]) || (v[0] + 8 == v[3]) \
      || (v[0] + 8) == POSITION->wKsq || (v[0] + 8) == POSITION->bKsq)) || \
    (PEZZO[1] == BlockedPawn && \
     ((v[1] + 8) == v[0] || (v[1] + 8 == v[2]) || (v[1] + 8 == v[3]) \
      || (v[1] + 8) == POSITION->wKsq || (v[1] + 8) == POSITION->bKsq)) || \
    (PEZZO[2] == BlockedPawn && \
     ((v[2] + 8) == v[0] || (v[2] + 8 == v[1]) || (v[2] + 8 == v[3]) \
      || (v[2] + 8) == POSITION->wKsq || (v[2] + 8) == POSITION->bKsq)) || \
    (PEZZO[3] == BlockedPawn && \
     ((v[3] + 8) == v[0] || (v[3] + 8 == v[1]) || (v[3] + 8 == v[2]) \
      || (v[3] + 8) == POSITION->wKsq || (v[3] + 8) == POSITION->bKsq)) \
    || IS_ILLEGAL)
	    if (BAD || !RobboTotalBaseScore (POSITION, &s) || s == dROTT)
	      {
		SetVal (TH, w, MODO);
		goto LOOP;
	      }
	    if (DISCO_PATTA (s) && MODO == ePAT)
	      {
		SetVal (TH, w, MODO);
		goto LOOP;
	      }
	    if (DISCO_VITTORIA (s) && MODO == eVIT)
	      {
		SetVal (TH, w, MODO);
		goto LOOP;
	      }
	    if (DISCO_PERDITA (s) && MODO == ePER)
	      {
		SetVal (TH, w, MODO);
		goto LOOP;
	      }
	    list = GenCapturesTotal (POSITION, LIST);
	    for (u = 0; u < list - LIST; u++)
	      {
		move = LIST[u].move;
		to = TO (move);
		fr = FROM (move);
		cp = POSITION->sq[to];
		pr = MoveIsProm (move);
		pi = POSITION->sq[fr];
		if (cp)
		  POSITION->bitboard[cp] ^= SqSet[to];
		POSITION->bitboard[pi] ^= SqSet[to] ^ SqSet[fr];
		if (pi == wEnumK)
		  POSITION->wKsq = to;
		wBitboardOcc ^= SqSet[to] ^ SqSet[fr];
		if (cp)
		  bBitboardOcc ^= SqSet[to];
		POSITION->OccupiedBW =  wBitboardOcc | bBitboardOcc;
#ifndef MAGIC_BITBOARDS
		POSITION->OccupiedL90 ^=  SqSet[Left90[fr]];
		POSITION->OccupiedL45 ^= SqSet[Left45[fr]];
		POSITION->OccupiedR45 ^= SqSet[Right45[fr]];
		if (!cp)
		  {
		    POSITION->OccupiedL90 ^= SqSet[Left90[to]];
		    POSITION->OccupiedL45 ^= SqSet[Left45[to]];
		    POSITION->OccupiedR45 ^= SqSet[Right45[to]];
		  }
#endif
		if (pr && ((move >> 12) & 7) == 7)
		  {
		    wBitboardP ^= SqSet[to];
		    wBitboardQ ^= SqSet[to];
		  }
		POSITION->sq[fr] = 0;
		POSITION->sq[to] = pi;
		if (pr)
		  POSITION->sq[to] = wEnumQ;
		POSITION->wtm = FALSE;
		Mobility (POSITION);
		if (!IS_ILLEGAL && RobboTotalBaseScore (POSITION, &vc))
		  {} /* HACK */
		else
		  vc = 1000;
		POSITION->wtm = TRUE;
		if (cp)
		  POSITION->bitboard[cp] ^= SqSet[to];
		POSITION->bitboard[pi] ^= SqSet[fr] ^ SqSet[to];
		if (pi == wEnumK)
		  POSITION->wKsq = fr;
		POSITION->sq[fr] = pi;
		POSITION->sq[to] = cp;
		wBitboardOcc ^= SqSet[to] ^ SqSet[fr];
		if (cp)
		  bBitboardOcc ^= SqSet[to];
		POSITION->OccupiedBW = wBitboardOcc | bBitboardOcc;
#ifndef MAGIC_BITBOARDS
		POSITION->OccupiedL90 ^= SqSet[Left90[fr]];
		POSITION->OccupiedL45 ^= SqSet[Left45[fr]];
		POSITION->OccupiedR45 ^= SqSet[Right45[fr]];
		if (!cp)
		  {
		    POSITION->OccupiedL90 ^= SqSet[Left90[to]];
		    POSITION->OccupiedL45 ^= SqSet[Left45[to]];
		    POSITION->OccupiedR45 ^= SqSet[Right45[to]];
		  }
#endif
		if (pr && ((move >> 12) & 7) == 7)
		  {
		    wBitboardP ^= SqSet[to];
		    wBitboardQ ^= SqSet[to];
		  }
		if (vc != 1000 && DISCO_PERDITA (vc))
		  {
		    SetVal (TH, w, MODO);
		    goto LOOP;
		  }
		if (vc != 1000 && DISCO_PATTA (vc) && DISCO_PATTA (s) && w
		    && GetVal (TH, w - 1) != eVIT && GetVal (TH, w - 1) != vNON)
		  {
		    SetVal (TH, w, MODO);
		    goto LOOP;
		  }
	      }
	    POSITION->wtm = TRUE;
	    if (DISCO_PATTA (s))
	      MODO = ePAT;
	    if (DISCO_VITTORIA (s))
	      MODO = eVIT;
	    if (DISCO_PERDITA (s))
	      MODO = ePER;
	    SetVal (TH, w, MODO);
	  LOOP:
	    for (i = 0; i < 4; i++)
	      {
		if (PEZZO[i])
		  POSITION->sq[v[i]] = 0;
		if (PEZZO[i] == BlockedPawn)
		  POSITION->sq[v[i] + 8] = 0;
	      }
	    POSITION->sq[POSITION->wKsq] = 0;
	    POSITION->sq[POSITION->bKsq] = 0;
	  }
}

typeDO DATA_ORGANIZER[1];
int WORLD_RF;
MUTEX_TYPE TRIPLE_SMP_BUILD[1];

void* triple_SMP_thread (void *Null)
{
  int rf, u;
  typePOS POSITION[1];
  POSITION->DYN_ROOT = malloc (MAXIMUM_PLY * sizeof(typeDYNAMIC));
  POSITION->DYN = POSITION->DYN_ROOT + 1;
  POSITION->wtm = TRUE;
  POSITION->DYN->reversible = 0;
  POSITION->DYN->ep = POSITION->DYN->oo = 0;
  for (u = A1; u <= H8; u++)
    POSITION->sq[u] = 0;
  while (TRUE)
    {
      LOCK (TRIPLE_SMP_BUILD);
      rf = WORLD_RF++;
      UNLOCK (TRIPLE_SMP_BUILD);
      if (rf >= ((WORLD_PILA == RE_normale) ? 462 : 1806))
	break;
      TripleMakeSMP (POSITION, rf, DATA_ORGANIZER->DATA[rf]);
    }
  return NULL;
}

pthread_t TripleMake_thread[64]; /* HACK */

void TripleBaseMake (int* FILE_RESTRICT, char* inome_file)
{
  uint64 w;
  int p;
  uint64 C[4];
  char nome_file[256];
  int s, e, cpu;
  sint64 ALLOC_SIZE;
  sint64 i, j;

#ifdef NOME_WINDOWS
  nome_file[0] = 'K';
  j = 0;
  while (inome_file[j])
    {
      if (inome_file[j] <= 'Z')
	{
	  nome_file[2 * j + 1] = 'w';
	  nome_file[2 * j + 2] = inome_file[j] + 32;
	}
      else
	{
	  nome_file[2 * j + 1] = 'b';
	  nome_file[2 * j + 2] = inome_file[j];
	}
      j++;
    }
  nome_file[2 * j + 1] = 0;
#else
  strcpy(nome_file, inome_file);
#endif

  printf ("TripleBaseMake %s %d %d %d %d [%d%d%d%d]\n",
	  nome_file, PEZZO[0], PEZZO[1], PEZZO[2], PEZZO[3],
	  FILE_RESTRICT[0], FILE_RESTRICT[1], FILE_RESTRICT[2], FILE_RESTRICT[3]);
  p = 0;
  WORLD_PILA = RE_normale;
  for (i = 0; i < 4; i++)
    if (PEZZO[i] == wEnumP || PEZZO[i] == bEnumP || PEZZO[i] == BlockedPawn)
      WORLD_PILA = RE_pedone;
  for (i = 0; i < 4; i++)
    {
      E[i] = ENUMn;
      if (!PEZZO[i])
	E[i] = ENUM0;
      if (PEZZO[i] == wEnumP)
	E[i] = ENUM_BI_PED;
      if (PEZZO[i] == bEnumP)
	E[i] = ENUM_NE_PED;
      if (PEZZO[i] == BlockedPawn)
	E[i] = ENUM_BLOCKED;
      if (PEZZO[i] == wEnumB || PEZZO[i] == bEnumB)
	E[i] = ENUM_ALF;
      if (FILE_RESTRICT[i] > 0) /* PEZZO[i]: wEnumP bEnumP vis BlockedPawn*/
	E[i] = ENUM_EFGH[PEZZO[i] / 9][FILE_RESTRICT[i] - 1];
      if (FILE_RESTRICT[i] < 0) /* 1,8 ----> 0    vis    9 -----> 1 */
	E[i] = ENUM_IJ[PEZZO[i] / 9][-FILE_RESTRICT[i] - 1];
      if (FILE_RESTRICT[i] > 0 && PEZZO[i] == BlockedPawn)
	E[i] = ENUM_UVWX[FILE_RESTRICT[i] - 1];
    }
  DATA_ORGANIZER->fettas = ((WORLD_PILA == RE_normale) ? (462) : (1806));
  ALLOC_SIZE = 64 * 64 * ((WORLD_PILA == RE_normale) ? (64) : (48)) + 256;
  if (PEZZO[3])
    ALLOC_SIZE = ((WORLD_PILA == RE_normale) ?
		  (64 * 64 * 64 * 64) : (64 * 64 * 47 * 24)) + 256;
  for (i = 0; i < DATA_ORGANIZER->fettas; i++)
    {
      DATA_ORGANIZER->DATA[i] = malloc (ALLOC_SIZE >> 2);
      for (j = 0; j < (ALLOC_SIZE >> 2); j++)
	(DATA_ORGANIZER->DATA[i])[j] = 0;
    }
  DATA_ORGANIZER->ctl = 0;
  DATA_ORGANIZER->ctf = 0;
  WORLD_RF = 0;
  if (!PEZZO[2])
    RB_CPUS = 1;
  if (PEZZO[3])
    InitInitTotalBaseCache (1024); /* nominal */
  LOCK_INIT (TRIPLE_SMP_BUILD);
  for (cpu = 0; cpu < RB_CPUS; cpu++)
    PTHREAD_CREATE (&TripleMake_thread[cpu], NULL, triple_SMP_thread, NULL);
  for (cpu = 0; cpu < RB_CPUS; cpu++)
    PTHREAD_JOIN (TripleMake_thread[cpu]);
  printf ("Counting DATA\n");
  C[0] = C[1] = C[2] = C[3] = 0;
  for (i = 0; i < DATA_ORGANIZER->fettas; i++)
    {
      j = 0;
      while (GetVal (DATA_ORGANIZER->DATA[i], j) == vNON)
	j++;
      s = GetVal (DATA_ORGANIZER->DATA[i], j);
      while (j >= 0)
	{
	  SetVal (DATA_ORGANIZER->DATA[i], j, s); /* HACK j++ */
	  j -= 2; /* HACK */
	}
      for (j = 0; ; j++)
	{
	  e = GetVal (DATA_ORGANIZER->DATA[i], j);
	  if (e == vNON)
	    break;
	  C[e]++;
	}
      DATA_ORGANIZER->limit = j; /* HACK */
    }
  w = C[1] + C[2] + C[3];
  printf ("Now RLE: %lld %lld %lld %lld\n", w, C[1], C[2], C[3]);
  rle (DATA_ORGANIZER, w, nome_file, C, OPTIONINGS);
  for (i = 0; i < DATA_ORGANIZER->fettas; i++)
    free (DATA_ORGANIZER->DATA[i]);
}

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

void triple_disposto (char *II)
{
  int i, j, FILE_RESTRICT[4];
  char PI[4];
  char I[32];
  if (II[0] == '.')
    II[0] = 0; /* HACK */
  strcpy(I, II);
  for (j = strlen (I); j < 4; j++)
    I[j] = 0;
  for (i = 0; i < 4; i++)
    {
      FILE_RESTRICT[i] = 0;
      switch (I[i])
	{
          case 'Q':
	    PI[i] = wEnumQ;
	    break;
          case 'q':
	    PI[i] = bEnumQ;
	    break;
          case 'R':
	    PI[i] = wEnumR;
	    break;
          case 'r':
	    PI[i] = bEnumR;
	    break;
          case 'B':
	    PI[i] = wEnumB;
	    break;
          case 'b':
	    PI[i] = bEnumB;
	    break;
          case 'N':
	    PI[i] = wEnumN;
	    break;
          case 'n':
	    PI[i] = bEnumN;
	    break;
	  case 'E': case 'F': case 'G': case 'H': case 'I' : case 'J':
	  case 'P':
	    PI[i] = wEnumP;
	    break;
	  case 'e': case 'f': case 'g': case 'h': case 'i' : case 'j':
	  case 'p':
	    PI[i] = bEnumP;
	    break;
	  case 'U': case 'V': case 'W': case 'X': case 'Z':
	    PI[i] = BlockedPawn;
	    break;
          default:
	    PI[i] = 0;
	}
      switch (I[i])
	{
	  case 'E': case 'e': case 'U':
	    FILE_RESTRICT[i] = 4;
	    break;
	  case 'F': case 'f': case 'V':
	    FILE_RESTRICT[i] = 3;
	    break;
	  case 'G': case 'g': case 'W':
	    FILE_RESTRICT[i] = 2;
	    break;
	  case 'H': case 'h': case 'X':
	    FILE_RESTRICT[i] = 1;
	    break;
  	  case 'I': case 'i':
	    FILE_RESTRICT[i] = -1;
	    break;
	  case 'J': case 'j':
	    FILE_RESTRICT[i] = -2;
	    break;
	}
      }
  OPTIONINGS = (PI[2] ? ROBBO_DYNAMIC_LOAD : 0); /* HACK */ /* 5 piece for the always */
  OPTIONINGS |= (0 & ROBBO_SCACCO_BIT); /* HACK */ /* in the none */
  OPTIONINGS |= (((!PI[2]) || PI[3]) ? 0 : ROBBO_DIRECT_DYNAMIC_BIT);
  SEND ("OPTIONINGS: %s %s %s\n",
	(OPTIONINGS & ROBBO_DIRECT_DYNAMIC_BIT) ? "ROBBO_DIRECT_DYNAMIC" : "",
	(OPTIONINGS & ROBBO_DYNAMIC_LOAD) ? "ROBBO_DYNAMIC_LOAD" : "",
	(OPTIONINGS & ROBBO_SCACCO_BIT) ? "ROBBO_SCACCO" : "");
  for (i = 0; i < 4; i++)
    PEZZO[i] = PI[i];
  TripleBaseMake (FILE_RESTRICT, I);
}

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

void wash_arguments (int n, char **A)
{
  int i, b = 0;
  char STRUT[1024][16], OTT[1024];
  boolean LOAD3 = TRUE, LOAD4 = TRUE, LOAD5 = TRUE, LOAD6 = TRUE, LOAD = TRUE;
  for (i = 1; i < n; i++)
    {
      if (!strcmp (A[i], "--cpus"))
        {
          RB_CPUS = atoi(A[++i]);
          continue;
        }
      if (!strcmp (A[i], "--noload"))
	{
	  LOAD = FALSE;
	  continue;
	}
      if (!strcmp (A[i], "--noload3"))
	{
	  LOAD3 = FALSE;
	  continue;
	}
      if (!strcmp (A[i], "--noload4"))
	{
	  LOAD4 = FALSE;
	  continue;
	}
      if (!strcmp (A[i], "--noload5"))
	{
	  LOAD5 = FALSE;
	  continue;
	}
      if (!strcmp (A[i], "--noload6"))
	{
	  LOAD6 = FALSE;
	  continue;
	}
      strcpy (STRUT[b++], A[i]);
    }
  if (LOAD)
    {
      if (LOAD3)
	{
	  sprintf (OTT, "%s/3", TOTAL_BASE_DIRECTORY);
	  GetTotalBase (OTT);
	}
      if (LOAD4)
	{
	  sprintf (OTT, "%s/4", TOTAL_BASE_DIRECTORY);
	  GetTotalBase (OTT);
	}
      if (LOAD5)
	{
	  sprintf (OTT, "%s/5", TOTAL_BASE_DIRECTORY);
	  GetTotalBase (OTT);
	}
      if (LOAD6)
	{
	  sprintf (OTT, "%s/6", TOTAL_BASE_DIRECTORY);
	  GetTotalBase (OTT);
	  sprintf (OTT, "%s/51", TOTAL_BASE_DIRECTORY);
	  GetTotalBase (OTT);
	  sprintf (OTT, "%s/42", TOTAL_BASE_DIRECTORY);
	  GetTotalBase (OTT);
	  sprintf (OTT, "%s/33", TOTAL_BASE_DIRECTORY);
	  GetTotalBase (OTT);
	  sprintf (OTT, "%s/Z", TOTAL_BASE_DIRECTORY);
	  GetTotalBase (OTT);
	  sprintf (OTT, "%s/6Z", TOTAL_BASE_DIRECTORY);
	  GetTotalBase (OTT);
	}
    }
  for (i = 0; i < b; i++)
    triple_disposto (STRUT[i]);
  return;
}


void TotalBaseInit ()
{
  int pi1, pi2, pi3, pi4;
  int i;
  InitTotalBaseUtility (FALSE);
  NUM_TOTAL_BASES = 0;
  for (pi1 = 0; pi1 < 16; pi1++)
    for (pi2 = 0; pi2 < 16; pi2++)
      for (pi3 = 0; pi3 < 16; pi3++)
        for (pi4 = 0; pi4 < 16; pi4++)
          TotalBaseTable[pi1][pi2][pi3][pi4] = -1;
  TABLE_TOTAL_BASES = malloc (MAX_TABLES * sizeof (RobboTotalBase));
  for (i = 0; i < MAX_TABLES; i++)
    (TABLE_TOTAL_BASES + i)->Fdata = NULL;
  for (i = 0; i < MAX_TABLES; i++)
    (TABLE_TOTAL_BASES + i)->indici = NULL;
  InitInitTotalBaseCache (1);
  TOT_INDICI = 0;
}

void InitRandom32 (uint64 x) {} 
void ResetHistory () {}
void ResetPositionalGain() {}
int InitMaterialValue() { return 0; }
void InitStatic() {} /* HACK */

/* Copyright (c) Roberto Pescatore plus Decembrists (all), PUBLICDOMAIN (workers) */

int main (int argc, char **argv)
{
  RB_CPUS = 4;
  TRY_LARGE_PAGES = FALSE;
  InitSlab (4);
  TotalBaseInit ();
  InitInitTotalBaseCache (256); /* 256mb helper size */ /* proffer in which */
  TOTAL_VERBOSO = 0;
  BULK_BYTES = BULK_IND = 0;
  LOAD_COUNT = BULK_COUNT = DIRECT_COUNT = 0;
  TRIVIALLY_COUNT = 0;
  strcpy (TOTAL_BASE_DIRECTORY, "RobboTotalBase");
  strcpy (TRIPLE_DIR, "RobboTripleBase"); /* HACK */
  wash_arguments (argc, argv);
  exit (0);
  return 0;
}

#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

#include <stdarg.h>
void SEND (char* fmt, ...)
{
  va_list Value;
  va_start (Value, fmt);
  vfprintf (stdout, fmt, Value);
  va_end (Value);
  fflush (stdout);
}

