/*
 
    Protector -- a UCI chess engine
 
 
 
    Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com)
 
 
 
    This program is free software: you can redistribute it and/or modify
 
    it under the terms of the GNU General Public License as published by
 
    the Free Software Foundation, either version 3 of the License, or
 
    (at your option) any later version.
 
 
 
    This program is distributed in the hope that it will be useful,
 
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
    GNU General Public License for more details.
 
 
 
    You should have received a copy of the GNU General Public License
 
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 
 
*/
 
 
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <string.h>
 
#include <stdarg.h>
 
#include <assert.h>
 
#include "io.h"
 
#include "pgn.h"
 
#include "position.h"
 
 
 
char pieceSymbol[16];
 
char pieceName[16];
 
 
 
static char *logfileName = "protector.log";
 
 
 
int getKeyStroke()
 
{
 
   logDebug("\nProgram halted. Hit RETURN to continue.");
 
 
 
}
 
 
 
void getSquareName(Square square, char name[3])
 
{
 
   name[0] = (char) fileName(file(square));
 
   name[1] = (char) rankName(rank(square));
 
   name[2] = '\0';
 
}
 
 
 
void getMoveDump(const Move move, char *buffer)
 
{
 
   char from[3], to[3];
 
 
 
   getSquareName(getFromSquare(move), from);
 
   getSquareName(getToSquare(move), to);
 
 
 
   if (getNewPiece(move) == NO_PIECE)
 
   {
 
      sprintf(buffer
, "%s-%s", from
, to
);  
   }
 
   else
 
   {
 
      sprintf(buffer
, "%s-%s=%c", from
, to
, pieceSymbol
[getNewPiece
(move
)]);  
   }
 
}
 
 
 
static void getMovelistDump(const Movelist * movelist, char *buffer)
 
{
 
   int i;
 
   char movebuffer[128];
 
 
 
   buffer[0] = '\0';
 
 
 
 
 
   for (i = 0; i < movelist->numberOfMoves; i++)
 
   {
 
      getMoveDump(movelist->moves[i], movebuffer);
 
      sprintf(buffer 
+ strlen(buffer
), "%d. %s (%d)\n", i 
+ 1, movebuffer
,  
              getMoveValue(movelist->moves[i]));
 
   }
 
 
 
 
 
   for (i = 0; i < movelist->numberOfBadCaptures; i++)
 
   {
 
      getMoveDump(movelist->badCaptures[i], movebuffer);
 
      sprintf(buffer 
+ strlen(buffer
), "%d. %s (%d)\n", i 
+ 1, movebuffer
,  
              getMoveValue(movelist->badCaptures[i]));
 
   }
 
}
 
 
 
static void formatTime(long sec, char *buffer)
 
{
 
   long seconds = sec % 60;
 
   long minutes = (sec / 60) % 60;
 
   long hours = (sec / 3600) % 60;
 
 
 
   sprintf(buffer
, "%02ld:%02ld:%02ld", hours
, minutes
, seconds
);  
}
 
 
 
void formatLongInteger(UINT64 n, char *buffer)
 
{
 
   char tmp[32], *pBuffer, *fmt = "%llu";
 
   int i, j = 1, ol;
 
 
 
   pBuffer = buffer + ol + (ol - 1) / 3;
 
   *pBuffer-- = '\0';
 
 
 
   for (i = ol - 1; i >= 0; i--)
 
   {
 
 
 
      *pBuffer-- = tmp[i];
 
 
 
      if (j++ % 3 == 0 && i > 0)
 
      {
 
         *pBuffer-- = ',';
 
      }
 
   }
 
}
 
 
 
static void formatCentipawnValue(int centipawnValue, char *buffer)
 
{
 
   float value = (float) centipawnValue;
 
 
 
   if (abs(centipawnValue
) <= -(VALUE_MATED 
+ 500))  
   {
 
      sprintf(buffer
, "%.2f", value 
/ 100.0);  
   }
 
   else
 
   {
 
      if (centipawnValue > 0)
 
      {
 
         sprintf(buffer
, "#%d", (1 - VALUE_MATED 
- centipawnValue
) / 2);  
      }
 
      else
 
      {
 
         sprintf(buffer
, "-#%d", (centipawnValue 
- VALUE_MATED
) / 2);  
      }
 
   }
 
}
 
 
 
void formatUciValue(const int centipawnValue, char *buffer)
 
{
 
   if (abs(centipawnValue
) <= -(VALUE_MATED 
+ 500))  
   {
 
      sprintf(buffer
, "cp %d", centipawnValue
);  
   }
 
   else
 
   {
 
      if (centipawnValue > 0)
 
      {
 
         sprintf(buffer
, "mate %d", (1 - VALUE_MATED 
- centipawnValue
) / 2);  
      }
 
      else
 
      {
 
         sprintf(buffer
, "mate -%d", (centipawnValue 
- VALUE_MATED
) / 2);  
      }
 
   }
 
}
 
 
 
static void getBoardDump(const Position * position, char *buffer)
 
{
 
   int file, rank;
 
   Square square;
 
   Piece piece;
 
 
 
   for (rank = RANK_8; rank >= RANK_1; rank--)
 
   {
 
      for (file = FILE_A; file <= FILE_H; file++)
 
      {
 
         square = getSquare(file, rank);
 
         piece = position->piece[square];
 
         *buffer++ = pieceName[piece];
 
      }
 
 
 
      *buffer++ = '\n';
 
   }
 
 
 
   *buffer = '\0';
 
 
 
   if (position->activeColor == WHITE)
 
   {
 
      strcat(buffer
, "White to move");  
   }
 
   else
 
   {
 
      strcat(buffer
, "Black to move");  
   }
 
}
 
 
 
void dumpSquare(const Square square)
 
{
 
   char buffer[3];
 
 
 
   getSquareName(square, buffer);
 
 
 
   logDebug("%s\n", buffer);
 
}
 
 
 
void dumpMove(const Move move)
 
{
 
   char buffer[128];
 
 
 
   getMoveDump(move, buffer);
 
 
 
   logDebug("%s (%d)\n", buffer, getMoveValue(move));
 
}
 
 
 
void logMove(const Move move)
 
{
 
   char buffer[128];
 
 
 
   getMoveDump(move, buffer);
 
 
 
   logReport("%s (%d)\n", buffer, getMoveValue(move));
 
}
 
 
 
void dumpMovelist(const Movelist * movelist)
 
{
 
   char buffer[4096];
 
 
 
   getMovelistDump(movelist, buffer);
 
 
 
   logDebug("%s\n", buffer);
 
}
 
 
 
void dumpPv(int depth, long timestamp,
 
            const char *moves, int value, UINT64 nodes,
 
            const Color activeColor)
 
{
 
   char ts[32], ns[32], vs[32];
 
 
 
   formatTime(timestamp / 1000, ts);
 
   formatLongInteger(nodes, ns);
 
 
 
   if (activeColor == BLACK && value > 20000)
 
   {
 
      value--;
 
   }
 
 
 
   formatCentipawnValue((activeColor == WHITE ? value : -value), vs);
 
   logReport("%d: %s %s (%s) %s\n", depth, ts, moves, vs, ns);
 
}
 
 
 
void logPosition(const Position * position)
 
{
 
   char buffer[1024];
 
 
 
   getBoardDump(position, buffer);
 
 
 
   logReport("%s\n", buffer);
 
}
 
 
 
void dumpPosition(const Position * position)
 
{
 
   logPosition(position);
 
   getKeyStroke();
 
}
 
 
 
void dumpVariation(const Variation * variation)
 
{
 
   char buffer[1024], moveBuffer[16];
 
   int ply;
 
 
 
   getBoardDump(&variation->singlePosition, buffer);
 
 
 
   for (ply = 0; ply < variation->ply; ply++)
 
   {
 
      getMoveDump(variation->plyInfo[ply].currentMove, moveBuffer);
 
   }
 
 
 
   logReport("%s\nnodeCount: %llu hashKey: %llu", buffer, variation->nodes,
 
             variation->singlePosition.hashKey);
 
   getKeyStroke();
 
}
 
 
 
void reportVariation(const Variation * variation)
 
{
 
   char buffer[1024], moveBuffer[16];
 
   int ply;
 
 
 
   getBoardDump(&variation->startPosition, buffer);
 
 
 
   for (ply = 0; ply < variation->ply; ply++)
 
   {
 
      getMoveDump(variation->plyInfo[ply].currentMove, moveBuffer);
 
   }
 
 
 
   logReport("%s\nnodeCount: %llu hashKey: %llu\nbest move=", buffer,
 
             variation->nodes, variation->singlePosition.hashKey);
 
   logMove(variation->bestBaseMove);
 
}
 
 
 
static void bitboard2String(Bitboard bitboard, char *title, char *buffer)
 
{
 
   int file, rank;
 
 
 
   for (rank = RANK_8; rank >= RANK_1; rank = (Rank) (rank - 1))
 
   {
 
      for (file = FILE_A; file <= FILE_H; file = (File) (file + 1))
 
      {
 
         Square square = getSquare(file, rank);
 
 
 
         *buffer++ = (testSquare(bitboard, square) ? '*' : '0');
 
      }
 
 
 
      *buffer++ = '\n';
 
   }
 
 
 
}
 
 
 
void dumpBitboard(Bitboard bitboard, char *title)
 
{
 
   char buffer[128];
 
 
 
   bitboard2String(bitboard, title, buffer);
 
 
 
   logDebug("\n%s\n\n", buffer);
 
}
 
 
 
void dumpBalance(const INT32 balance)
 
{
 
   int opValue = getOpeningValue(balance);
 
   int egValue = getEndgameValue(balance);
 
 
 
   logDebug("op=%d eg=%d\n", opValue, egValue);
 
}
 
 
 
static void boardValues2String(const int value[64], char *buffer)
 
{
 
   int file, rank;
 
   char valueBuffer[64];
 
 
 
   for (rank = RANK_8; rank >= RANK_1; rank = (Rank) (rank - 1))
 
   {
 
      for (file = FILE_A; file <= FILE_H; file = (File) (file + 1))
 
      {
 
         Square square = getSquare(file, rank);
 
 
 
         sprintf(valueBuffer
, "%i ", value
[square
]);  
         sprintf(buffer
, "%s", valueBuffer
);  
         buffer 
+= strlen(valueBuffer
); 
      }
 
 
 
      *buffer++ = '\n';
 
   }
 
 
 
   *buffer++ = '\0';
 
}
 
 
 
void dumpBoardValues(const int value[64])
 
{
 
   char buffer[1024];
 
 
 
   boardValues2String(value, buffer);
 
 
 
   logDebug("\n%s\n\n", buffer);
 
}
 
 
 
void logDebug(const char *fmt, ...)
 
{
 
   va_list args;
 
 
 
 
 
   if (commandlineOptions.xboardMode == FALSE)
 
   {
 
   }
 
   else
 
   {
 
      FILE 
*logfile 
= fopen(logfileName
, "a"); 
 
 
      fprintf(logfile
, "%lu: ", getTimestamp
());  
 
 
      {
 
         printf("Could not close file '%s'.", logfileName
);  
      }
 
   }
 
 
 
}
 
 
 
void logReport(const char *fmt, ...)
 
{
 
   char buffer[1024];
 
   FILE 
*logfile 
= fopen(logfileName
, "a"); 
   va_list args;
 
 
 
 
 
   if (commandlineOptions.xboardMode == FALSE)
 
   {
 
   }
 
 
 
   if (logfile != NULL)
 
   {
 
 
 
      {
 
         printf("Could not close file '%s'.", logfileName
);  
      }
 
   }
 
   else
 
   {
 
      printf("Could not open file '%s'.", logfileName
);  
   }
 
}
 
 
 
void writeTableToFile(UINT64 * table, const int tablesize,
 
                      const char *fileName, const char *tableName)
 
{
 
   FILE 
*file 
= fopen(fileName
, "w"); 
   int i;
 
   const char *format = "%llullu, ";
 
 
 
   fprintf(file
, "#include \"protector.h\"\n\n");  
   fprintf(file
, "UINT64 %s[%d] = {\n", tableName
, tablesize
);  
 
 
   for (i = 0; i < tablesize; i++)
 
   {
 
 
 
      if ((i % 4) == 3)
 
      {
 
      }
 
   }
 
 
 
}
 
 
 
int initializeModuleIo()
 
{
 
   pieceSymbol[KING] = 'K';
 
   pieceSymbol[QUEEN] = 'Q';
 
   pieceSymbol[ROOK] = 'R';
 
   pieceSymbol[BISHOP] = 'B';
 
   pieceSymbol[KNIGHT] = 'N';
 
   pieceSymbol[PAWN] = 'P';
 
 
 
   pieceName[NO_PIECE] = '*';
 
   pieceName[WHITE_KING] = 'K';
 
   pieceName[WHITE_QUEEN] = 'Q';
 
   pieceName[WHITE_ROOK] = 'R';
 
   pieceName[WHITE_BISHOP] = 'B';
 
   pieceName[WHITE_KNIGHT] = 'N';
 
   pieceName[WHITE_PAWN] = 'P';
 
   pieceName[BLACK_KING] = 'k';
 
   pieceName[BLACK_QUEEN] = 'q';
 
   pieceName[BLACK_ROOK] = 'r';
 
   pieceName[BLACK_BISHOP] = 'b';
 
   pieceName[BLACK_KNIGHT] = 'n';
 
   pieceName[BLACK_PAWN] = 'p';
 
 
 
   return 0;
 
}
 
 
 
int testModuleIo()
 
{
 
   char buffer[32];
 
 
 
   formatLongInteger(123, buffer);
 
   formatLongInteger(1234, buffer);
 
   formatLongInteger(1234567, buffer);
 
 
 
   return 0;
 
}