
#ifdef GAVIOTA_COMPLIANCE
#include "GaviotaCompliance.h"
#include <stdio.h>

#ifdef IMPEL_GAVIOTA_DEBUG
#include "GaviotaDebug.h"
#endif

#define NOSQUARE 64 /* Gaviota */

#define bool unsigned char
#define boolean unsigned char
#define Bitboard unsigned long long int
#define uint8 unsigned char
#define SOFT 0
#define HARD 1
#define dROTT 0x00
#define dVITT 0x01
#define dPATT 0x02
#define dPERD0 (dPATT + 1)

typedef struct
{
  unsigned char pi[4], sq[4], wK, bK;
  bool wtm, pedone;
  unsigned char ep, n, _2, _3; /* 0x10 bytes */ /* plus ep, no Blocked */
} Type_PiSq;

boolean fare_PQ_with_ep_with_type (Type_PiSq *, uint8 *, int);

int tb_probe_soft /* GAVIOTA */
(unsigned int s, SQUARE ep, unsigned oo,
 const SQUARE * wsq, const SQUARE * bsq,
 const SQ_CONTENT * wpi, const SQ_CONTENT * bpi,
 unsigned * r, unsigned * ply)
{
  int a = tb_probe (s, ep, oo, wsq, bsq, wpi, bpi, r, ply, SOFT); /* dolt */
#ifdef IMPEL_GAVIOTA_DEBUG
  int u = *r;
  int b = (*GaviotaDebug_TB_ProbeSoft)(s, ep, oo, wsq, bsq, wpi, bpi, r, ply);
  if (a && b && u != *r) /* BUG */
    GaviotaBugTrap (s, ep, wsq, bsq, wpi, bpi, u, *r);
#endif
  return a;
}

int tb_probe_hard /* GAVIOTA */
(unsigned int s, SQUARE ep, unsigned oo,
 const SQUARE * wsq, const SQUARE * bsq,
 const SQ_CONTENT * wpi, const SQ_CONTENT * bpi,
 unsigned * r, unsigned * ply)
{
  int a = tb_probe (s, ep, oo, wsq, bsq, wpi, bpi, r, ply, HARD); /* dolt */
#ifdef IMPEL_GAVIOTA_DEBUG
  unsigned u = *r;
  int b = (*GaviotaDebug_TB_ProbeSoft)(s, ep, oo, wsq, bsq, wpi, bpi, r, ply);
  if (a && b && u != *r) /* BUG */
    GaviotaBugTrap (s, ep, wsq, bsq, wpi, bpi, u, *r);
#endif
  return a;
}

static int WHITE_SWITCH[8] = { 0, 1, 2, 4, 6, 7, 3 };
void GAVIOTA_TRANSLATE
(unsigned int stm, SQUARE ep,
 const SQUARE * wsq, const SQUARE * bsq,
 const SQ_CONTENT * wpi, const SQ_CONTENT * bpi,
 Type_PiSq * PiSq)
{
  int i = 0, j = 0;
  PiSq->pi[0] = PiSq->pi[1] = PiSq->pi[2] = PiSq->pi[3] = 0;
  PiSq->sq[0] = PiSq->sq[1] = PiSq->sq[2] = PiSq->sq[3] = 0; /* fill */
  PiSq->wtm = (stm == 0); /* Gaviota WHITE_TO_MOVE */ /* HACK */
  PiSq->ep = ep;
  PiSq->pedone = 0;
  while (wpi[i] != 0)
    {
      if (wpi[i] == 6) /* KING */
	{
	  PiSq->wK = wsq[i++];
	  continue;
	}
      PiSq->pi[j] = WHITE_SWITCH[wpi[i]];
      PiSq->pedone |= (wpi[i] == 1); /* PAWN */
      PiSq->sq[j++] = wsq[i++];
    }
  i = 0; /* set */
  while (bpi[i] != 0)
    {
      if (bpi[i] == 6) /* KING */
	{
	  PiSq->bK = bsq[i++];
	  continue;
	}
      PiSq->pi[j] = WHITE_SWITCH[bpi[i]] + 8; /* HACK */ /* value */
      PiSq->pedone |= (bpi[i] == 1); /* PAWN */
      PiSq->sq[j++] = bsq[i++];
    }
  PiSq->n = j;
}

int tb_probe /* glue */
(unsigned int stm, SQUARE ep, unsigned oo,
 const SQUARE * wsq, const SQUARE * bsq,
 const SQ_CONTENT * wpi, const SQ_CONTENT * bpi,
 unsigned * res, unsigned * ply, unsigned type)
{
  Type_PiSq PiSq[1];
  uint8 value;
  bool r;
  if (!oo)
    return 0;
  GAVIOTA_TRANSLATE (stm, ep, wsq, bsq, wpi, bpi, PiSq);
  r = fare_PQ_with_ep_with_type (PiSq, &value, type);
  if (!r)
    {
      *res = 7; /* Gaviota UNKNOWN */
      return 0;
    }
  if (value == dROTT) /* BROKEN */
    *res = 3; /* Gaviota FORBID */
  if (value == dPATT) /* DRAWN */
    *res = 0; /* Gaviota DRAW */
  if (value == dVITT) /* WON */
    {
      *res = (stm) ? 1 : 2; /* WMATE, BMATE */
      *ply = 0xf8; /* holder */
    }
  if (value >= dPERD0) /* LOST */
    {
      *res = (stm) ? 2 : 1; /* BMATE, WMATE */
      *ply = (value - dPERD0);
    }
  return 1;
}

int tb_probe_WDL_soft /* GAVIOTA */
(unsigned int s, SQUARE ep, unsigned oo,
 const SQUARE * wsq, const SQUARE * bsq,
 const SQ_CONTENT * wpi, const SQ_CONTENT * bpi,
 unsigned * res)
{
  if (!oo)
    return 0;
  // call RobboTripleBase
  return 0; // temp
}

int tb_probe_WDL_hard /* GAVIOTA */
(unsigned int s, SQUARE ep, unsigned oo,
 const SQUARE * wsq, const SQUARE * bsq,
 const SQ_CONTENT * wpi, const SQ_CONTENT * bpi,
 unsigned * res)
{
  if (!oo)
    return 0;
  // call RobboTripleBase
  return 0; // temp
}
#endif
