/*
    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/>.

*/

#ifndef _book_h_
#define _book_h_

#include "protector.h"
#include "position.h"
#include <stdio.h>

#define BOOKINDEX_SIZE 10007
#define getBookpositionIndex(hashvalue) \
        ((hashvalue) % BOOKINDEX_SIZE)
#define getBookpositionIndexOffset(hashvalue) \
        (getBookpositionIndex(hashvalue) * sizeof(BookPosition))

typedef struct
{
   UINT64 hashValue;
   UINT32 nextPosition;
   UINT32 firstMove;
}
BookPosition;

typedef struct
{
   UINT16 move;
   UINT16 numberOfGames;
   INT16 score;
   UINT16 numberOfPersonalGames;
   INT16 personalScore;
   UINT32 nextAlternative;
}
BookMove;

typedef struct
{
   FILE *indexFile, *moveFile;
   bool readonly;
   UINT32 numberOfPositions, numberOfMoves;
}
Book;

extern Book globalBook;

/**
 * Open the book specified by 'name'.
 *
 * @return 0 if no errors occurred.
 */
int openBook(Book * book, const char *name);

/**
 * Create an empty book.
 */
void createEmptyBook(Book * book);

/**
 * Close the specified book.
 */
void closeBook(Book * book);

/**
 * Get all bookmoves for the position specified by 'hashValue'.
 */
void getBookmoves(const Book * book, const UINT64 hashValue,
                  const Movelist * legalMoves, Movelist * bookMoves);

/**
 * Get a move suggestion for the position specified by 'hashValue'.
 *
 * @return an illegal move if the book doesn't contain the position
 */
Move getBookmove(const Book * book, const UINT64 hashValue,
                 const Movelist * legalMoves);

/**
 * Add the specified move to the opening book.
 */
void addBookmove(Book * book, const Position * position,
                 const Move move, const GameResult result,
                 const bool personalResult);

/**
 * Append the database specified by 'filename' to the book specified by 'book'.
 *
 * @param maximumNumberOfPlies the maximum distance between a book position
 *        and the start position
 */
void appendBookDatabase(Book * book, const char *filename,
                        int maximumNumberOfPlies);

/**
 * Initialize this module.
 *
 * @return 0 if no errors occurred.
 */
int initializeModuleBook(void);

/**
 * Test this module.
 *
 * @return 0 if all tests succeed.
 */
int testModuleBook(void);

#endif
