
#include "RobboLito.h"
#include "RobboBaseLibUsage.h"

#define dROTT 0x00
#define dVITT 0x01
#define dPATT 0x02
#define dPERD0 (dPATT + 1)
#define DISCO_PATT_PERD(x) ((x) >= dPATT)
#define DISCO_VITTORIA(x) ((x) == dVITT)
#define DISCO_PATTA(x) ((x) == dPATT)
#define DISCO_PERDITA(x) ((x) >= dPERD0)

#define IsCheck \
 ( POSITION->wtm ? \
   (wBitboardK & POSITION->DYN->bAtt) :   (bBitboardK & POSITION->DYN->wAtt) )

#define IS_ILLEGAL \
 ( !POSITION->wtm ? \
   (wBitboardK & POSITION->DYN->bAtt) :   (bBitboardK & POSITION->DYN->wAtt) )

boolean Squeeze (typePOS *, Type_PiSq *, boolean);

boolean Robbo_mossa (typePOS* POSITION, uint32* am, int* v, int* cap)
{
  int va, v2, av = 0xff, zv = 0x00, cp;
  uint8 v8;
  typeMoveList mossa_lista[256];
  typeMoveList* q;
  uint32 m;
  Type_PiSq PiSq[1];
  if (POSITION->DYN->oo)
    return FALSE;
  *am = 0;
  if (!Squeeze (POSITION, PiSq, 1))
    return FALSE;
  if (!FUNC_CALL (RobboTotalLibScore) (PiSq, &v8, 1))
    return FALSE;
  va = v8;
  Mobility (POSITION);
  if (IsCheck)
    EvasionMoves (POSITION, mossa_lista, 0xffffffffffffffff);
  else
    {
      q = CaptureMoves (POSITION, mossa_lista, 0xffffffffffffffff);
      OrdinaryMoves (POSITION, q);
    }
  for (q = mossa_lista; q->move; q++)
    {
      m = q->move & 0x7fff;
      POSITION->StackHeight = 0; /* HACK */
      Make (POSITION, m);
      POSITION->StackHeight = 1; /* HACK */
      Mobility (POSITION);
      if (IS_ILLEGAL)
	{
	  Undo (POSITION, m);
	  POSITION->StackHeight = 1; /* HACK */
	  continue;
	}
      if (!Squeeze (POSITION, PiSq, 1))
	{	  
	  Undo (POSITION, m);
	  POSITION->StackHeight = 1; /* HACK */
	  return FALSE;
	}
      if (!FUNC_CALL (RobboTotalLibScore) (PiSq, &v8, 1))
	{	  
	  Undo (POSITION, m);
	  POSITION->StackHeight = 1; /* HACK */
	  return FALSE;
	}
      v2 = v8;
      if (DISCO_PERDITA (va))
	{
	  uint32 m3;
	  int v3;
	  if (!Robbo_mossa (POSITION, &m3, &v3, &cp))
	    {
	      Undo (POSITION, m);
	      POSITION->StackHeight = 1; /* HACK */
	      return FALSE;
	    }
	  if (v3 > zv &&
	      ((!POSITION->DYN->cp && !(m & FLAG_MASK) &&
		((!cp && (!(m3 & FLAG_MASK)))))
	       || va <= dPERD0 + 1))
	    {
	      *am = m;
	      *v = zv = v3;
	      *cap = POSITION->DYN->cp;
	    }
	}
      Undo (POSITION, m);
      POSITION->StackHeight = 1; /* HACK */
      if (DISCO_PATTA (va) && DISCO_PATTA (v2))
	{
	  *am = m;
	  *v = dPATT;
	  *cap = FALSE; /* HACK */
	  return TRUE;
	}
      if (DISCO_VITTORIA (va) && DISCO_PERDITA (v2))
	{
	  if (POSITION->sq[TO (m)] || (m & FLAG_MASK))
	    {
	      *am = m;
	      *v = v2;
	      *cap = TRUE; /* HACK */
	      return TRUE;
	    }
	  if (v2 < av)
	    {
	      *am = m;
	      *v = av = v2;
	      *cap = FALSE; /* HACK */
	    }
	}
    }
  return TRUE;
}

static void main_line_iterate (typePOS* POSITION)
{
  int va, v2, cp;
  uint32 m;
  Type_PiSq PiSq[1];
  uint8 v8;
  (POSITION->DYN + 1)->move = MOVE_NONE;
  Mobility (POSITION);
  if (!Squeeze (POSITION, PiSq, 1))
    {
      SEND ("info string Failure in main_line_iterate (squeeze)\n");
      (POSITION->DYN + 1)->move = MOVE_NONE;
      POSITION->StackHeight = 0; /* HACK */
      return;
    }
  if (!FUNC_CALL (RobboTotalLibScore) (PiSq, &v8, 1))
    {
      SEND ("info string Failure in main_line_iterate\n");
      (POSITION->DYN + 1)->move = MOVE_NONE;
      POSITION->StackHeight = 0; /* HACK */
      return;
    }
  va = v8;
  if (!Robbo_mossa (POSITION, &m, &v2, &cp))
    {
      (POSITION->DYN + 1)->move = MOVE_NONE;
      POSITION->StackHeight = 0; /* HACK */
      return;
    }
  if (va == dPATT)
    {
      POSITION->StackHeight = 0; /* HACK */
      Make (POSITION, m);
      POSITION->DYN->move = m;
      POSITION->StackHeight = 1; /* HACK */
      Undo (POSITION, m);
      return;
    }
  m &= 0x7fff;
  if (m == MOVE_NONE)
    return;
  POSITION->StackHeight = 0; /* HACK */
  Make (POSITION, m);
  POSITION->DYN->move = m;
  POSITION->StackHeight = 1; /* HACK */
  main_line_iterate (POSITION);
  Undo (POSITION, m);
  POSITION->StackHeight = 1; /* HACK */
}

void main_line (typePOS* POSITION)
{
  typeDYNAMIC* p;
  char STRING[16];
  int va;
  Type_PiSq PiSq[1];
  uint8 v8;
  main_line_iterate (POSITION);
  if (!Squeeze (POSITION, PiSq, 1))
    {
      SEND ("info string Failure in main_line (squeeze)\n");
      return;      
    }
  if (!FUNC_CALL (RobboTotalLibScore) (PiSq, &v8, 1) || v8 == dROTT)
    {
      SEND ("info string Failure in main_line\n");
      return;
    }
  va = v8;
  sprintf (STRING, "%d", va - dPERD0);
  printf ("mainline (%c%s): ", (va == dVITT) ? 'W' : ((va == dPATT) ? 'D' : 'L'),
	  (va < dPERD0) ? "" : STRING);
  for (p = POSITION->DYN + 1; p->move; p++)
    printf ("%s ", Notate (p->move & 0x7fff, STRING));
  SEND ("\n");
}
