Subversion Repositories Games.Chess Giants

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.     Protector -- a UCI chess engine
  3.  
  4.     Copyright (C) 2009-2010 Raimund Heid (Raimund_Heid@yahoo.com)
  5.  
  6.     This program is free software: you can redistribute it and/or modify
  7.     it under the terms of the GNU General Public License as published by
  8.     the Free Software Foundation, either version 3 of the License, or
  9.     (at your option) any later version.
  10.  
  11.     This program is distributed in the hope that it will be useful,
  12.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.     GNU General Public License for more details.
  15.  
  16.     You should have received a copy of the GNU General Public License
  17.     along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  
  19. */
  20.  
  21. #include <stdio.h>
  22. #include <stdlib.h>
  23. #include <string.h>
  24. #include <stdarg.h>
  25. #include <assert.h>
  26. #include "io.h"
  27. #include "pgn.h"
  28. #include "position.h"
  29.  
  30. char pieceSymbol[16];
  31. char pieceName[16];
  32.  
  33. static char *logfileName = "protector.log";
  34.  
  35. int getKeyStroke()
  36. {
  37.    logDebug("\nProgram halted. Hit RETURN to continue.");
  38.  
  39.    return getchar();
  40. }
  41.  
  42. void getSquareName(Square square, char name[3])
  43. {
  44.    name[0] = (char) fileName(file(square));
  45.    name[1] = (char) rankName(rank(square));
  46.    name[2] = '\0';
  47. }
  48.  
  49. void getMoveDump(const Move move, char *buffer)
  50. {
  51.    char from[3], to[3];
  52.  
  53.    getSquareName(getFromSquare(move), from);
  54.    getSquareName(getToSquare(move), to);
  55.  
  56.    if (getNewPiece(move) == NO_PIECE)
  57.    {
  58.       sprintf(buffer, "%s-%s", from, to);
  59.    }
  60.    else
  61.    {
  62.       sprintf(buffer, "%s-%s=%c", from, to, pieceSymbol[getNewPiece(move)]);
  63.    }
  64. }
  65.  
  66. static void getMovelistDump(const Movelist * movelist, char *buffer)
  67. {
  68.    int i;
  69.    char movebuffer[128];
  70.  
  71.    buffer[0] = '\0';
  72.  
  73.    sprintf(buffer + strlen(buffer), "\nmoves:\n");
  74.  
  75.    for (i = 0; i < movelist->numberOfMoves; i++)
  76.    {
  77.       getMoveDump(movelist->moves[i], movebuffer);
  78.       sprintf(buffer + strlen(buffer), "%d. %s (%d)\n", i + 1, movebuffer,
  79.               getMoveValue(movelist->moves[i]));
  80.    }
  81.  
  82.    sprintf(buffer + strlen(buffer), "bad captures\n");
  83.  
  84.    for (i = 0; i < movelist->numberOfBadCaptures; i++)
  85.    {
  86.       getMoveDump(movelist->badCaptures[i], movebuffer);
  87.       sprintf(buffer + strlen(buffer), "%d. %s (%d)\n", i + 1, movebuffer,
  88.               getMoveValue(movelist->badCaptures[i]));
  89.    }
  90. }
  91.  
  92. static void formatTime(long sec, char *buffer)
  93. {
  94.    long seconds = sec % 60;
  95.    long minutes = (sec / 60) % 60;
  96.    long hours = (sec / 3600) % 60;
  97.  
  98.    sprintf(buffer, "%02ld:%02ld:%02ld", hours, minutes, seconds);
  99. }
  100.  
  101. void formatLongInteger(UINT64 n, char *buffer)
  102. {
  103.    char tmp[32], *pBuffer, *fmt = "%llu";
  104.    int i, j = 1, ol;
  105.  
  106.    sprintf(tmp, fmt, n);
  107.    ol = (int) strlen(tmp);
  108.    pBuffer = buffer + ol + (ol - 1) / 3;
  109.    *pBuffer-- = '\0';
  110.  
  111.    for (i = ol - 1; i >= 0; i--)
  112.    {
  113.       assert(pBuffer >= buffer);
  114.  
  115.       *pBuffer-- = tmp[i];
  116.  
  117.       if (j++ % 3 == 0 && i > 0)
  118.       {
  119.          assert(pBuffer >= buffer);
  120.          *pBuffer-- = ',';
  121.       }
  122.    }
  123. }
  124.  
  125. static void formatCentipawnValue(int centipawnValue, char *buffer)
  126. {
  127.    float value = (float) centipawnValue;
  128.  
  129.    if (abs(centipawnValue) <= -(VALUE_MATED + 500))
  130.    {
  131.       sprintf(buffer, "%.2f", value / 100.0);
  132.    }
  133.    else
  134.    {
  135.       if (centipawnValue > 0)
  136.       {
  137.          sprintf(buffer, "#%d", (1 - VALUE_MATED - centipawnValue) / 2);
  138.       }
  139.       else
  140.       {
  141.          sprintf(buffer, "-#%d", (centipawnValue - VALUE_MATED) / 2);
  142.       }
  143.    }
  144. }
  145.  
  146. void formatUciValue(const int centipawnValue, char *buffer)
  147. {
  148.    if (abs(centipawnValue) <= -(VALUE_MATED + 500))
  149.    {
  150.       sprintf(buffer, "cp %d", centipawnValue);
  151.    }
  152.    else
  153.    {
  154.       if (centipawnValue > 0)
  155.       {
  156.          sprintf(buffer, "mate %d", (1 - VALUE_MATED - centipawnValue) / 2);
  157.       }
  158.       else
  159.       {
  160.          sprintf(buffer, "mate -%d", (centipawnValue - VALUE_MATED) / 2);
  161.       }
  162.    }
  163. }
  164.  
  165. static void getBoardDump(const Position * position, char *buffer)
  166. {
  167.    int file, rank;
  168.    Square square;
  169.    Piece piece;
  170.  
  171.    for (rank = RANK_8; rank >= RANK_1; rank--)
  172.    {
  173.       for (file = FILE_A; file <= FILE_H; file++)
  174.       {
  175.          square = getSquare(file, rank);
  176.          piece = position->piece[square];
  177.          *buffer++ = pieceName[piece];
  178.       }
  179.  
  180.       *buffer++ = '\n';
  181.    }
  182.  
  183.    *buffer = '\0';
  184.  
  185.    if (position->activeColor == WHITE)
  186.    {
  187.       strcat(buffer, "White to move");
  188.    }
  189.    else
  190.    {
  191.       strcat(buffer, "Black to move");
  192.    }
  193. }
  194.  
  195. void dumpSquare(const Square square)
  196. {
  197.    char buffer[3];
  198.  
  199.    getSquareName(square, buffer);
  200.  
  201.    logDebug("%s\n", buffer);
  202. }
  203.  
  204. void dumpMove(const Move move)
  205. {
  206.    char buffer[128];
  207.  
  208.    getMoveDump(move, buffer);
  209.  
  210.    logDebug("%s (%d)\n", buffer, getMoveValue(move));
  211. }
  212.  
  213. void logMove(const Move move)
  214. {
  215.    char buffer[128];
  216.  
  217.    getMoveDump(move, buffer);
  218.  
  219.    logReport("%s (%d)\n", buffer, getMoveValue(move));
  220. }
  221.  
  222. void dumpMovelist(const Movelist * movelist)
  223. {
  224.    char buffer[4096];
  225.  
  226.    getMovelistDump(movelist, buffer);
  227.  
  228.    logDebug("%s\n", buffer);
  229. }
  230.  
  231. void dumpPv(int depth, long timestamp,
  232.             const char *moves, int value, UINT64 nodes,
  233.             const Color activeColor)
  234. {
  235.    char ts[32], ns[32], vs[32];
  236.  
  237.    formatTime(timestamp / 1000, ts);
  238.    formatLongInteger(nodes, ns);
  239.  
  240.    if (activeColor == BLACK && value > 20000)
  241.    {
  242.       value--;
  243.    }
  244.  
  245.    formatCentipawnValue((activeColor == WHITE ? value : -value), vs);
  246.    logReport("%d: %s %s (%s) %s\n", depth, ts, moves, vs, ns);
  247. }
  248.  
  249. void logPosition(const Position * position)
  250. {
  251.    char buffer[1024];
  252.  
  253.    getBoardDump(position, buffer);
  254.  
  255.    logReport("%s\n", buffer);
  256. }
  257.  
  258. void dumpPosition(const Position * position)
  259. {
  260.    logPosition(position);
  261.    getKeyStroke();
  262. }
  263.  
  264. void dumpVariation(const Variation * variation)
  265. {
  266.    char buffer[1024], moveBuffer[16];
  267.    int ply;
  268.  
  269.    getBoardDump(&variation->singlePosition, buffer);
  270.    strcat(buffer, "\n");
  271.  
  272.    for (ply = 0; ply < variation->ply; ply++)
  273.    {
  274.       getMoveDump(variation->plyInfo[ply].currentMove, moveBuffer);
  275.       strcat(buffer, moveBuffer);
  276.       strcat(buffer, " ");
  277.    }
  278.  
  279.    logReport("%s\nnodeCount: %llu hashKey: %llu", buffer, variation->nodes,
  280.              variation->singlePosition.hashKey);
  281.    getKeyStroke();
  282. }
  283.  
  284. void reportVariation(const Variation * variation)
  285. {
  286.    char buffer[1024], moveBuffer[16];
  287.    int ply;
  288.  
  289.    getBoardDump(&variation->startPosition, buffer);
  290.    strcat(buffer, "\n");
  291.  
  292.    for (ply = 0; ply < variation->ply; ply++)
  293.    {
  294.       getMoveDump(variation->plyInfo[ply].currentMove, moveBuffer);
  295.       strcat(buffer, moveBuffer);
  296.       strcat(buffer, " ");
  297.    }
  298.  
  299.    logReport("%s\nnodeCount: %llu hashKey: %llu\nbest move=", buffer,
  300.              variation->nodes, variation->singlePosition.hashKey);
  301.    logMove(variation->bestBaseMove);
  302. }
  303.  
  304. static void bitboard2String(Bitboard bitboard, char *title, char *buffer)
  305. {
  306.    int file, rank;
  307.  
  308.    for (rank = RANK_8; rank >= RANK_1; rank = (Rank) (rank - 1))
  309.    {
  310.       for (file = FILE_A; file <= FILE_H; file = (File) (file + 1))
  311.       {
  312.          Square square = getSquare(file, rank);
  313.  
  314.          *buffer++ = (testSquare(bitboard, square) ? '*' : '0');
  315.       }
  316.  
  317.       *buffer++ = '\n';
  318.    }
  319.  
  320.    sprintf(buffer, "%s", title);
  321. }
  322.  
  323. void dumpBitboard(Bitboard bitboard, char *title)
  324. {
  325.    char buffer[128];
  326.  
  327.    bitboard2String(bitboard, title, buffer);
  328.  
  329.    logDebug("\n%s\n\n", buffer);
  330. }
  331.  
  332. void dumpBalance(const INT32 balance)
  333. {
  334.    int opValue = getOpeningValue(balance);
  335.    int egValue = getEndgameValue(balance);
  336.  
  337.    logDebug("op=%d eg=%d\n", opValue, egValue);
  338. }
  339.  
  340. static void boardValues2String(const int value[64], char *buffer)
  341. {
  342.    int file, rank;
  343.    char valueBuffer[64];
  344.  
  345.    for (rank = RANK_8; rank >= RANK_1; rank = (Rank) (rank - 1))
  346.    {
  347.       for (file = FILE_A; file <= FILE_H; file = (File) (file + 1))
  348.       {
  349.          Square square = getSquare(file, rank);
  350.  
  351.          sprintf(valueBuffer, "%i ", value[square]);
  352.          sprintf(buffer, "%s", valueBuffer);
  353.          buffer += strlen(valueBuffer);
  354.       }
  355.  
  356.       *buffer++ = '\n';
  357.    }
  358.  
  359.    *buffer++ = '\0';
  360. }
  361.  
  362. void dumpBoardValues(const int value[64])
  363. {
  364.    char buffer[1024];
  365.  
  366.    boardValues2String(value, buffer);
  367.  
  368.    logDebug("\n%s\n\n", buffer);
  369. }
  370.  
  371. void logDebug(const char *fmt, ...)
  372. {
  373.    va_list args;
  374.  
  375.    va_start(args, fmt);
  376.  
  377.    if (commandlineOptions.xboardMode == FALSE)
  378.    {
  379.       vprintf(fmt, args);
  380.    }
  381.    else
  382.    {
  383.       FILE *logfile = fopen(logfileName, "a");
  384.  
  385.       fprintf(logfile, "%lu: ", getTimestamp());
  386.       vfprintf(logfile, fmt, args);
  387.       fflush(logfile);
  388.  
  389.       if (fclose(logfile) != 0)
  390.       {
  391.          printf("Could not close file '%s'.", logfileName);
  392.       }
  393.    }
  394.  
  395.    va_end(args);
  396. }
  397.  
  398. void logReport(const char *fmt, ...)
  399. {
  400.    char buffer[1024];
  401.    FILE *logfile = fopen(logfileName, "a");
  402.    va_list args;
  403.  
  404.    va_start(args, fmt);
  405.    vsprintf(buffer, fmt, args);
  406.    va_end(args);
  407.  
  408.    if (commandlineOptions.xboardMode == FALSE)
  409.    {
  410.       printf("%s", buffer);
  411.    }
  412.  
  413.    if (logfile != NULL)
  414.    {
  415.       fprintf(logfile, "%s", buffer);
  416.  
  417.       if (fclose(logfile) != 0)
  418.       {
  419.          printf("Could not close file '%s'.", logfileName);
  420.       }
  421.    }
  422.    else
  423.    {
  424.       printf("Could not open file '%s'.", logfileName);
  425.    }
  426. }
  427.  
  428. void writeTableToFile(UINT64 * table, const int tablesize,
  429.                       const char *fileName, const char *tableName)
  430. {
  431.    FILE *file = fopen(fileName, "w");
  432.    int i;
  433.    const char *format = "%llullu, ";
  434.  
  435.    fprintf(file, "#include \"protector.h\"\n\n");
  436.    fprintf(file, "UINT64 %s[%d] = {\n", tableName, tablesize);
  437.  
  438.    for (i = 0; i < tablesize; i++)
  439.    {
  440.       fprintf(file, format, table[i]);
  441.  
  442.       if ((i % 4) == 3)
  443.       {
  444.          fprintf(file, "\n");
  445.       }
  446.    }
  447.  
  448.    fclose(file);
  449. }
  450.  
  451. int initializeModuleIo()
  452. {
  453.    pieceSymbol[KING] = 'K';
  454.    pieceSymbol[QUEEN] = 'Q';
  455.    pieceSymbol[ROOK] = 'R';
  456.    pieceSymbol[BISHOP] = 'B';
  457.    pieceSymbol[KNIGHT] = 'N';
  458.    pieceSymbol[PAWN] = 'P';
  459.  
  460.    pieceName[NO_PIECE] = '*';
  461.    pieceName[WHITE_KING] = 'K';
  462.    pieceName[WHITE_QUEEN] = 'Q';
  463.    pieceName[WHITE_ROOK] = 'R';
  464.    pieceName[WHITE_BISHOP] = 'B';
  465.    pieceName[WHITE_KNIGHT] = 'N';
  466.    pieceName[WHITE_PAWN] = 'P';
  467.    pieceName[BLACK_KING] = 'k';
  468.    pieceName[BLACK_QUEEN] = 'q';
  469.    pieceName[BLACK_ROOK] = 'r';
  470.    pieceName[BLACK_BISHOP] = 'b';
  471.    pieceName[BLACK_KNIGHT] = 'n';
  472.    pieceName[BLACK_PAWN] = 'p';
  473.  
  474.    return 0;
  475. }
  476.  
  477. int testModuleIo()
  478. {
  479.    char buffer[32];
  480.  
  481.    formatLongInteger(123, buffer);
  482.    assert(strcmp(buffer, "123") == 0);
  483.    formatLongInteger(1234, buffer);
  484.    assert(strcmp(buffer, "1,234") == 0);
  485.    formatLongInteger(1234567, buffer);
  486.    assert(strcmp(buffer, "1,234,567") == 0);
  487.  
  488.    return 0;
  489. }
  490.