
#include "RobboLito_def.h"
#include "RobboTripleBase.h"
#include <string.h>
#include "RobboTotalBase.h"

boolean TripleIndex (Type_PiSq*, RobboTripleBase**, uint64*);
boolean RobboTriple_valu(RobboTripleBase*, uint64, int*, boolean, boolean);
void TripleMake (uint32, Type_PiSq*, uint64*, uint8*);
void TripleUndo (uint32, Type_PiSq*, uint64*, uint8*);

boolean RobboTripleInternal /* BeLow */
(Type_PiSq* PiSq, int* Value, uint64* BitBoard, uint8* Board, int type);

uint64 AttK[0100];
boolean robbo_triple_lib_score (Type_PiSq* PiSq, int* Value, int type)
{
  uint8 Board[64];
  uint64 BitBoard[16];
  Type_PiSq Copy[1];
  int i = 0;
  uint64 B = 0;
  boolean b;
  PiSq->nodes = 0;
  if (PiSq->wK == PiSq->bK)
    return FALSE;
  if ((1ULL << PiSq->wK) & AttK[PiSq->bK])
    return FALSE;     
  memcpy (Copy, PiSq, 16);
  Copy->n = 0; /* assure */
  Copy->nodes = 0;
  for (i = 0; i < 0x10; i++) /* All */
    BitBoard[i] = 0;
  /* AssertInPut (); */
  for (i = 0; i < 4; i++)
    {
      int sq = PiSq->sq[i], pi = PiSq->pi[i];
      if (pi == 0)
	continue;
      Copy->n++;
      if (pi == 8)
	{
	  B |= (1ULL << sq);
	  Board[sq] = wEnumP | (i << 4) | 0x40;
	  Board[sq + 8] = bEnumP | (i << 4) | 0x80;
	  BitBoard[wEnumP] |= (1ULL << sq);
	  BitBoard[wEnumOcc] |= (1ULL << sq);
	  BitBoard[bEnumP] |= (1ULL << (sq + 8));
	  BitBoard[bEnumOcc] |= (1ULL << (sq + 8));
	  continue;
	}
      Board[sq] = pi | (i << 4);
      BitBoard[pi] |= (1ULL << sq);
      BitBoard[pi & 010] |= (1ULL << sq); /* occupied */
    }
  if ((B & ~FILEh) & (B << 1)) /* desist (Blocked adjacency) */
    return FALSE;
  Board[PiSq->wK] = wEnumK;
  BitBoard[wEnumK] = (1ULL << PiSq->wK);
  BitBoard[wEnumOcc] |= (1ULL << PiSq->wK);
  Board[PiSq->bK] = bEnumK;
  BitBoard[bEnumK] = (1ULL << PiSq->bK);
  BitBoard[bEnumOcc] |= (1ULL << PiSq->bK);
  Copy->pedone = BitBoard[wEnumP] || BitBoard[bEnumP]; /* assure */
  b = RobboTripleInternal (Copy, Value, BitBoard, Board, type);
  PiSq->nodes = Copy->nodes;
  return b;
}

typedef struct { uint32 move; } typeMoveList;

boolean CapturesByWhite (uint64*, uint8*, typeMoveList*, typeMoveList**, int);
boolean CapturesByBlack (uint64*, uint8*, typeMoveList*, typeMoveList**, int);

boolean RobboTripleValue (Type_PiSq*, int*, int); /* BeLow */

#define FlagEP (1 << 28)
boolean RobboTripleInternal
(Type_PiSq* PiSq, int* Value, uint64* BitBoard, uint8* Board, int type)
{
  typeMoveList LIST[256], *list;
  int val, best = -1;
  boolean b, Bad = FALSE;
  int i;

  if (PiSq->wtm)
    { 
      if (CapturesByWhite (BitBoard, Board, LIST, &list, PiSq->ep)) /* king */
	{
	  *Value = 1;
	  return TRUE;
	}
    }
  else
    {
      if (CapturesByBlack (BitBoard, Board, LIST, &list, PiSq->ep)) /* king */
	{
	  *Value = 1;
	  return TRUE;
	}
    }
    for (i = 0; i < list - LIST; i++)
    {
      if (PiSq->n == 4 && LIST[i].move & FlagEP &&  /* over flow BlockedPawn */
	  LIST[i].move & (0x3 << 18) && LIST[i].move & (0x3 << 26))
	{
	  Bad = TRUE;
	  continue;
	}
      TripleMake (LIST[i].move, PiSq, BitBoard, Board);
      b = RobboTripleInternal (PiSq, &val, BitBoard, Board, type); /* iter */
      TripleUndo (LIST[i].move, PiSq, BitBoard, Board);
      if (!b)
	return FALSE;
      if (val == -1)
	{
	  *Value = +1;
	  return TRUE;
	}
      if (val == 0)
	best = 0;
    }
  b = RobboTripleValue (PiSq, &val, type);
  if (!b)
    return FALSE;
  if (val == dVITT)
    {
      *Value = dVITT;
      return TRUE;
    }
  if (Bad)
    return FALSE;
  if (best > val)
    *Value = best;
  else
    *Value = val;
  return TRUE;
}

boolean RobboTripleValue (Type_PiSq* PiSq, int* Value, int type)
{
  boolean b;
  uint64 ind;
  RobboTripleBase* rtb;

  b = TripleIndex (PiSq, &rtb, &ind);
  if (!b)
    return FALSE;
  if (rtb->w[2] == 0)
    *Value = 2 - rtb->w[1];
  else
    {
      if (!RobboTriple_valu (rtb, ind, Value, type == 0, type == 2))
	return FALSE;
      *Value = 2 - (*Value);
    }
  return TRUE;
}

