#include "RobboLito.h"
#include <string.h>

char* Notate (uint32 move, char* M)
{
  int fr, to, pr;
  char c[16] = "0123nbrq";
  fr = FROM (move);
  to = TO (move);
  if (move == MOVE_NONE)
    {
      M[0] = 'N';
      M[1] = 'U';
      M[2] = M[3] = 'L';
      M[4] = 0;
      return M;
    }
  sprintf (M, "%c%c%c%c", 'a' + (fr & 7), '1' + ((fr >> 3) & 7),
	   'a' + (to & 7), '1' + ((to >> 3) & 7));
  if (MoveIsProm (move))
    {
      pr = (move & FLAG_MASK) >> 12;
      sprintf (M + 4, "%c", c[pr]);
    }
  return M;
}

uint32 FullMove (typePOS* POSITION, uint32 x)
{
  int pi, to = TO (x), fr = FROM (x);
  if (!x)
    return x;
  pi = POSITION->sq[fr];
  if (pi == wEnumK || pi == bEnumK)
    {
      if (to - fr == 2 || fr - to == 2)
        x |= FlagOO;
    }
  if (TO (x) != 0 && TO (x) == POSITION->DYN->ep
      && (pi == wEnumP || pi == bEnumP))
    x |= FlagEP;
  return x;
}

static void DoBad (char* x)
{
  SEND ("info string errore posizionale: %s\n", x);
}

#define BAD(x) { DoBad (x); return; }

void InitBitboards (typePOS* POSITION)
{
  int i, b, pi;
  uint64 O;
  BOARD_IS_OK = FALSE;
  for (i = 0; i < 16; i++)
    POSITION->bitboard[i] = 0;
  for (i = A1; i <= H8; i++)
    {
      if ((pi = POSITION->sq[i]))
	BitSet (i, POSITION->bitboard[POSITION->sq[i]]);
    }
  wBitboardOcc = wBitboardK | wBitboardQ | wBitboardR |
    wBitboardB | wBitboardN | wBitboardP;
  bBitboardOcc = bBitboardK | bBitboardQ | bBitboardR |
    bBitboardB | bBitboardN | bBitboardP;
  POSITION->OccupiedBW = wBitboardOcc | bBitboardOcc;
  O = POSITION->OccupiedBW;
  if (POPCNT (wBitboardK) != 1)
    BAD ("re bianco != 1");
  if (POPCNT (bBitboardK) != 1)
    BAD ("re nero != 1");
  if (POPCNT (wBitboardQ) > 9)
    BAD ("donna bianca > 9");
  if (POPCNT (bBitboardQ) > 9)
    BAD ("donna nera > 9");
  if (POPCNT (wBitboardR) > 10)
    BAD ("torre bianco > 10");
  if (POPCNT (bBitboardR) > 10)
    BAD ("torre nero > 10");
  if (POPCNT (wBitboardBL) > 9)
    BAD ("chiaro bianco > 9");
  if (POPCNT (bBitboardBL) > 9)
    BAD ("chiaro nero > 9");
  if (POPCNT (wBitboardBD) > 9)
    BAD ("scuro bianco > 9");
  if (POPCNT (bBitboardBD) > 9)
    BAD ("scuro nero > 9");
  if (POPCNT (wBitboardBL | wBitboardBD) > 10)
    BAD ("alfiere bianco > 10");
  if (POPCNT (bBitboardBL | bBitboardBD) > 10)
    BAD ("alfiere nero > 10");
  if (POPCNT (wBitboardN) > 10)
    BAD ("cavallo bianco > 10");
  if (POPCNT (bBitboardN) > 10)
    BAD ("cavallo nero > 10");
  if (POPCNT (wBitboardP) > 8)
    BAD ("pedone bianco > 8");
  if (POPCNT (bBitboardP) > 8)
    BAD ("pedone nero > 8");
  if (POPCNT (wBitboardOcc) > 16)
    BAD ("pezzo bianco > 16");
  if (POPCNT (bBitboardOcc) > 16)
    BAD ("pezzo nero > 16");
  if ((wBitboardP | bBitboardP) & (RANK1 | RANK8))
    BAD ("pedone traversa prima o ottava");
  POSITION->wKsq = BSF (wBitboardK);
  POSITION->bKsq = BSF (bBitboardK);
  if ((WhiteOO && (POSITION->wKsq != E1 || !(wBitboardR & SqSet[H1])))
      || (WhiteOOO && (POSITION->wKsq != E1 || !(wBitboardR & SqSet[A1])))
      || (BlackOO && (POSITION->bKsq != E8 || !(bBitboardR & SqSet[H8])))
      || (BlackOOO && (POSITION->bKsq != E8 || !(bBitboardR & SqSet[A8]))))
    BAD ("arrocco illegale");
  Mobility (POSITION);
  if (POSITION->wtm && POSITION->DYN->wAtt & bBitboardK)
    BAD ("bianco cattura re");
  if (!POSITION->wtm && POSITION->DYN->bAtt & wBitboardK)
    BAD ("nero catture re");
  if (POPCNT (POSITION->DYN->bKcheck) >= 3 || POPCNT (POSITION->DYN->wKcheck) >= 3)
    BAD ("InCheck from 3 pieces");
  BOARD_IS_OK = TRUE;
}

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

#include <stdarg.h>

void SEND (char* fmt, ...)
{
  va_list Value;
  va_start (Value, fmt);
  vfprintf (stdout, fmt, Value);
  va_end (Value);
  fflush (stdout);
}

void ERROR_END (char* fmt, ...)
{
  va_list Value;
  va_start (Value, fmt);
  va_end (Value);
  /*  stdout = stderr; // WINDOWS */
  fprintf (stdout, "*** ERRORE ***\n");
  vfprintf (stdout, fmt, Value);
  exit (-4);
}

void FEN_ERROR (char* fmt, ...)
{
  va_list Value;
  va_start (Value, fmt);
  va_end (Value);
  /*  stdout = stderr; // WINDOWS */
  fprintf (stdout, "*** FEN ERR ***\n");
  vfprintf (stdout, fmt, Value);
  exit (-8);
}
