/*----------------------------------------------------------------------
 | INIT.C							940420
 |
 | Contains procedures concerning the initialization of several
 | variables.
 +----------------------------------------------------------------------*/


#include "var.h"
#include "rand48.h"

static void     InitMoveTables(void);
static void     InitKnightTable(void);
static void     InitBishopTable(void);
static void     InitRookTable(void);
static void     InitPawnMoveTables(void);
static void     InitPawnCaptureTables(void);
static void     InitPieceSymbols(void);
static void     InitPieceValues(void);
static void     InitAllocVariables(void);
static void     FillHashTables(void);
static void     InitPackArrays(void);
static void     UpdateCentreTable(void);
static Boolean  Unique(HashType h);
static void     CheckHashTables(void);


/*----------------------------------------------------------------------
 | Init								940421
 |
 | Initializes the move tables, piece symbols, piece values,
 | alloc variables, piece tables, history tables, transposition table.
 | Puts board in starting position.
 +----------------------------------------------------------------------*/
void            Init(void)
{
    FillHashTables();
    CheckHashTables();
    EmptyBoard();               /* Has to be done before InitMoveTables! */
    InitMoveTables();
    InitPieceSymbols();
    InitPieceValues();
    InitAllocVariables();
    StartingPosition();
    InitPackArrays();
    UpdateCentreTable();
}                               /* Init */


/*----------------------------------------------------------------------
 | InitMoveTables						940421
 |
 | Initializes all move tables.
 +----------------------------------------------------------------------*/
void            InitMoveTables(void)
{
    InitKnightTable();
    InitBishopTable();
    InitRookTable();
    InitPawnMoveTables();
    InitPawnCaptureTables();
}                               /* InitMoveTables */


/*----------------------------------------------------------------------
 | InitKnightTable						940422
 |
 | Initializes the knight move table.
 +----------------------------------------------------------------------*/
void            InitKnightTable(void)
{
    Signed2         i,
                    j,
                    d,
                    nr;
    BoardIndexType  from,
                    to;

    for (i = 0; i <= H8; i++) {
        for (j = 0; j < MaxKnightMoves; j++) {
            knightTable[i][j] = 0;
        }
    }
    for (i = A; i <= H; i++) {
        for (j = 1; j <= 8; j++) {
            from = Square(i, j);
            nr = 0;
            for (d = 0; d < 8; d++) {
                to = from + knightDir[d];
                if (IsEmpty(board[to])) {
                    knightTable[from][nr++] = to;
                }
            }                   /* for d */
        }                       /* for j */
    }                           /* for i */
}                               /* InitKnightTable */


/*----------------------------------------------------------------------
 | InitBishopTable						940422
 |
 | Initializes the bishop move table.
 +----------------------------------------------------------------------*/
void            InitBishopTable(void)
{
    Signed2         i,
                    j,
                    d,
                    nr;
    BoardIndexType  from,
                    to;

    for (i = 0; i <= H8; i++) {
        for (j = 0; j < MaxBishopMoves; j++) {
            for (d = 0; d < 4; d++) {
                bishopTable[i][d][j] = 0;
            }
        }
    }
    for (i = A; i <= H; i++) {
        for (j = 1; j <= 8; j++) {
            from = Square(i, j);
            for (d = 0; d < 4; d++) {
                nr = 0;
                for (to = from + bishopDir[d]; IsEmpty(board[to]);
                     to += bishopDir[d]) {
                    bishopTable[from][d][nr++] = to;
                }
            }                   /* for d */
        }                       /* for j */
    }                           /* for i */
}                               /* InitBishopTable */


/*----------------------------------------------------------------------
 | InitRookTable						940422
 |
 | Initializes the rook move table.
 +----------------------------------------------------------------------*/
void            InitRookTable(void)
{
    Signed2         i,
                    j,
                    d,
                    nr;
    BoardIndexType  from,
                    to;

    for (i = 0; i <= H8; i++) {
        for (j = 0; j < MaxRookMoves; j++) {
            for (d = 0; d < 4; d++) {
                rookTable[i][d][j] = 0;
            }
        }
    }
    for (i = A; i <= H; i++) {
        for (j = 1; j <= 8; j++) {
            from = Square(i, j);
            for (d = 0; d < 4; d++) {
                nr = 0;
                for (to = from + rookDir[d]; IsEmpty(board[to]);
                     to += rookDir[d]) {
                    rookTable[from][d][nr++] = to;
                }
            }                   /* for d */
        }                       /* for j */
    }                           /* for i */
}                               /* InitRookTable */


/*----------------------------------------------------------------------
 | InitPawnMoveTables						940422
 |
 | Initializes the pawn movetables.
 +----------------------------------------------------------------------*/
void            InitPawnMoveTables(void)
{
    Signed2         i,
                    j;
    BoardIndexType  from;

    for (i = 0; i <= H8; i++) {
        for (j = 0; j < 2; j++) {
            pawnMoveTable[White][i][j] = 0;
        }
    }
    for (i = A; i <= H; i++) {
        for (j = 1; j <= 7; j++) {
            from = Square(i, j);
            if (j == 2) {
                pawnMoveTable[White][from][1] = from + Up + Up;
            }
            pawnMoveTable[White][from][0] = from + Up;
        }                       /* for j */
    }                           /* for i */

    for (i = 0; i <= H8; i++) {
        for (j = 0; j < 2; j++) {
            pawnMoveTable[Black][i][j] = 0;
        }
    }
    for (i = A; i <= H; i++) {
        for (j = 2; j <= 8; j++) {
            from = Square(i, j);
            if (j == 7) {
                pawnMoveTable[Black][from][1] = from + Down + Down;
            }
            pawnMoveTable[Black][from][0] = from + Down;
        }                       /* for j */
    }                           /* for i */
}                               /* InitPawnMoveTables */


/*----------------------------------------------------------------------
 | InitPawnCaptureTables					940422
 |
 | Initializes the pawn capture tables.
 +----------------------------------------------------------------------*/
void            InitPawnCaptureTables(void)
{
    Signed2         i,
                    j,
                    k;
    BoardIndexType  from,
                    to;

    for (i = 0; i <= H8; i++) {
        for (j = 0; j < 2; j++) {
            pawnCaptureTable[White][i][j] = 0;
        }
    }
    for (i = A; i <= H; i++) {
        for (j = 1; j <= 7; j++) {
            from = Square(i, j);
            for (k = 0; k < 2; k++) {
                to = from + pawnCaptureDir[White][k];
                if (IsEmpty(board[to])) {
                    pawnCaptureTable[White][from][k] = to;
                } else {
                    pawnCaptureTable[White][from][k] = 0;
                }
            }
        }                       /* for j */
    }                           /* for i */

    for (i = 0; i <= H8; i++) {
        for (j = 0; j < 2; j++) {
            pawnCaptureTable[Black][i][j] = 0;
        }
    }
    for (i = A; i <= H; i++) {
        for (j = 2; j <= 8; j++) {
            from = Square(i, j);
            for (k = 0; k < 2; k++) {
                to = from + pawnCaptureDir[Black][k];
                if (IsEmpty(board[to])) {
                    pawnCaptureTable[Black][from][k] = to;
                } else {
                    pawnCaptureTable[Black][from][k] = 0;
                }
            }
        }                       /* for j */
    }                           /* for i */
}                               /* InitPawnCaptureTables */


/*----------------------------------------------------------------------
 | InitPieceSymbols						940421
 |
 | Initializes all piece symbols. White pieces in capitals.
 +----------------------------------------------------------------------*/
static void     InitPieceSymbols(void)
{
    Signed2         i;

    for (i = 0; i < 256; i++) {
        pieceSymbol[i] = '#';
    }
    pieceSymbol[WhitePawn] = 'O';
    pieceSymbol[WhiteKnight] = 'N';
    pieceSymbol[WhiteBishop] = 'B';
    pieceSymbol[WhiteRook] = 'R';
    pieceSymbol[WhiteQueen] = 'Q';
    pieceSymbol[WhiteKing] = 'K';
    pieceSymbol[BlackPawn] = 'o';
    pieceSymbol[BlackKnight] = 'n';
    pieceSymbol[BlackBishop] = 'b';
    pieceSymbol[BlackRook] = 'r';
    pieceSymbol[BlackQueen] = 'q';
    pieceSymbol[BlackKing] = 'k';
}                               /* InitPieceSymbols */


/*----------------------------------------------------------------------
 | InitPieceValues.						940425
 |
 | Initializes all piece values.
 +----------------------------------------------------------------------*/
static void     InitPieceValues(void)
{
    Signed2         i;

    for (i = 0; i < 128; i++) {
        pieceValue[i] = 0;
    }
    pieceValue[WhitePawn] = 100;
    pieceValue[BlackPawn] = 100;
    pieceValue[WhiteKnight] = 325;
    pieceValue[BlackKnight] = 325;
    pieceValue[WhiteBishop] = 325;
    pieceValue[BlackBishop] = 325;
    pieceValue[WhiteRook] = 500;
    pieceValue[BlackRook] = 500;
    pieceValue[WhiteQueen] = 900;
    pieceValue[BlackQueen] = 900;
    pieceValue[WhiteKing] = 3200;
    pieceValue[BlackKing] = 3200;
}                               /* InitPieceValues */


/*----------------------------------------------------------------------
 | InitAllocVariables.						940425
 |
 | Initializes all allocation variables. They are used to check if
 | all allocated memory is being freed.
 +----------------------------------------------------------------------*/
static void     InitAllocVariables(void)
{
    nrAllocMoveLists = nrAllocPathMoves = 0;
}                               /* InitAllocVariables */


/*----------------------------------------------------------------------
 | EmptyBoard							940421
 |
 | Empties the board and resets number of black and white pieces.
 | Furthermnore, the history tables are cleared.
 +----------------------------------------------------------------------*/
void            EmptyBoard(void)
{
    BoardIndexType  i,
                    j;

    for (i = 0; i < NrSquares; i++) {
        board[i] = Edge;
    }
    for (i = A; i <= H; i++) {
        for (j = 1; j <= 8; j++) {
            board[Square(i, j)] = Empty;
        }
    }
    nrPieces[White] = nrPieces[Black] = 0;
    toMove = White;
    for (i = A1; i <= H8; i++) {
        pieceIndex[i] = 0;
    }
    kingSquare[White] = kingSquare[Black] = 0;
    nrGamePlies = maxGamePlies = 0;
    epSquare[nrGamePlies] = NoEp;
    castling[nrGamePlies] = 0;
    material[White] = material[Black] = 0;
    HashMakeZero(hashValue[nrGamePlies]);
    startHashIndex[nrGamePlies] = nrGamePlies;
    InitPositionalValue();

    ClearHistoryTables();
    lastMovedPieceSquare = 0;
}                               /* EmptyBoard */


/*----------------------------------------------------------------------
 | StartingPosition						940421
 |
 | Places all pieces on an empty board in starting position.
 +----------------------------------------------------------------------*/
void            StartingPosition(void)
{
    PlacePiece((SquareType) WhiteKnight, (BoardIndexType) B1);
    PlacePiece((SquareType) WhiteKnight, (BoardIndexType) G1);
    PlacePiece((SquareType) WhiteBishop, (BoardIndexType) C1);
    PlacePiece((SquareType) WhiteBishop, (BoardIndexType) F1);
    PlacePiece((SquareType) WhiteRook, (BoardIndexType) A1);
    PlacePiece((SquareType) WhiteRook, (BoardIndexType) H1);
    PlacePiece((SquareType) WhiteQueen, (BoardIndexType) D1);
    PlacePiece((SquareType) WhiteKing, (BoardIndexType) E1);
    PlacePiece((SquareType) WhitePawn, (BoardIndexType) A2);
    PlacePiece((SquareType) WhitePawn, (BoardIndexType) B2);
    PlacePiece((SquareType) WhitePawn, (BoardIndexType) C2);
    PlacePiece((SquareType) WhitePawn, (BoardIndexType) D2);
    PlacePiece((SquareType) WhitePawn, (BoardIndexType) E2);
    PlacePiece((SquareType) WhitePawn, (BoardIndexType) F2);
    PlacePiece((SquareType) WhitePawn, (BoardIndexType) G2);
    PlacePiece((SquareType) WhitePawn, (BoardIndexType) H2);

    PlacePiece((SquareType) BlackKnight, (BoardIndexType) B8);
    PlacePiece((SquareType) BlackKnight, (BoardIndexType) G8);
    PlacePiece((SquareType) BlackBishop, (BoardIndexType) C8);
    PlacePiece((SquareType) BlackBishop, (BoardIndexType) F8);
    PlacePiece((SquareType) BlackRook, (BoardIndexType) A8);
    PlacePiece((SquareType) BlackRook, (BoardIndexType) H8);
    PlacePiece((SquareType) BlackQueen, (BoardIndexType) D8);
    PlacePiece((SquareType) BlackKing, (BoardIndexType) E8);
    PlacePiece((SquareType) BlackPawn, (BoardIndexType) A7);
    PlacePiece((SquareType) BlackPawn, (BoardIndexType) B7);
    PlacePiece((SquareType) BlackPawn, (BoardIndexType) C7);
    PlacePiece((SquareType) BlackPawn, (BoardIndexType) D7);
    PlacePiece((SquareType) BlackPawn, (BoardIndexType) E7);
    PlacePiece((SquareType) BlackPawn, (BoardIndexType) F7);
    PlacePiece((SquareType) BlackPawn, (BoardIndexType) G7);
    PlacePiece((SquareType) BlackPawn, (BoardIndexType) H7);

    castling[nrGamePlies] = WhiteShort | WhiteLong | BlackShort | BlackLong;
    HashXorIs(hashValue[nrGamePlies], castlingHashTable[White][Short]);
    HashXorIs(hashValue[nrGamePlies], castlingHashTable[White][Long]);
    HashXorIs(hashValue[nrGamePlies], castlingHashTable[Black][Short]);
    HashXorIs(hashValue[nrGamePlies], castlingHashTable[Black][Long]);
}                               /* StartingPosition */


/*----------------------------------------------------------------------
 | PlacePiece							940421
 |
 | Puts a piece on the board. Updates the board and the piece tables.
 +----------------------------------------------------------------------*/
void            PlacePiece(SquareType piece, BoardIndexType square)
{
    SquareType      color;
    HashType       *table;

    board[square] = piece;
    color = Color(piece);
    pieces[color][nrPieces[color]].type = piece;
    pieces[color][nrPieces[color]].square = square;
    pieceIndex[square] = nrPieces[color]++;
    if (IsKing(piece)) {
        kingSquare[color] = square;
    }
    material[color] += pieceValue[piece];
    GetHashTable(table, color, piece);
    HashXorIs(hashValue[nrGamePlies], table[square]);
}                               /* PlacePiece */


/*----------------------------------------------------------------------
 | ClearHistoryTables.						940606
 |
 | Clears the white and black history tables.
 +----------------------------------------------------------------------*/
void            ClearHistoryTables(void)
{
    BoardIndexType  i,
                    j;

    for (i = 0; i <= H8; i++) {
        for (j = 0; j <= H8; j++) {
            historyTable[White][i][j] = historyTable[Black][i][j] = 0;
        }
    }
}                               /* ClearHistoryTables */


/*----------------------------------------------------------------------
 | ClearPieceSquareTables.					940606
 |
 | Clears the white and black piece-square tables.
 +----------------------------------------------------------------------*/
void            ClearPieceSquareTables(void)
{
    BoardIndexType  i;

    for (i = 0; i <= H8; i++) {
        pawnEvalTable[White][i] = pawnEvalTable[Black][i] = 0;
        knightEvalTable[White][i] = knightEvalTable[Black][i] = 0;
        bishopEvalTable[White][i] = bishopEvalTable[Black][i] = 0;
        rookEvalTable[White][i] = rookEvalTable[Black][i] = 0;
        queenEvalTable[White][i] = queenEvalTable[Black][i] = 0;
        kingEvalTable[White][i] = kingEvalTable[Black][i] = 0;
    }
}                               /* ClearPieceSquareTables */


void            InitPositionalValue(void)
{
    Signed2        *table;
    Signed2         i;

    positionalValue[White] = 0;
    for (i = 0; i < nrPieces[White]; i++) {
        GetEvalTable(table, White, pieces[White][i].type);
        positionalValue[White] += table[pieces[White][i].square];
    }
    printf("\n");
    positionalValue[Black] = 0;
    for (i = 0; i < nrPieces[Black]; i++) {
        GetEvalTable(table, Black, pieces[Black][i].type);
        positionalValue[Black] += table[pieces[Black][i].square];
    }
}                               /* InitPositionalValue */

static void     reverse(HashType h)
{
    Unsigned1       b1,
                    b2,
                    b3,
                    b4;

    b1 = h[0] & 255;
    b2 = (h[0] >> 8) & 255;
    b3 = (h[0] >> 16) & 255;
    b4 = (h[0] >> 24) & 255;
    h[0] = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
    b1 = h[1] & 255;
    b2 = (h[1] >> 8) & 255;
    b3 = (h[1] >> 16) & 255;
    b4 = (h[1] >> 24) & 255;
    h[1] = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
}

static void     FillHashTables(void)
{
    Signed2         i,
                    j;
    BoardIndexType  square;
    FILE           *fp;

    if ((fp = fopen("random.tab", "rb")) != NULL) {
        printf("\nReading random values from 'random.tab'\n");
        fread(pawnHashTable[White], sizeof(HashType), H8 + 1, fp);
        fread(pawnHashTable[Black], sizeof(HashType), H8 + 1, fp);
        fread(knightHashTable[White], sizeof(HashType), H8 + 1, fp);
        fread(knightHashTable[Black], sizeof(HashType), H8 + 1, fp);
        fread(bishopHashTable[White], sizeof(HashType), H8 + 1, fp);
        fread(bishopHashTable[Black], sizeof(HashType), H8 + 1, fp);
        fread(rookHashTable[White], sizeof(HashType), H8 + 1, fp);
        fread(rookHashTable[Black], sizeof(HashType), H8 + 1, fp);
        fread(queenHashTable[White], sizeof(HashType), H8 + 1, fp);
        fread(queenHashTable[Black], sizeof(HashType), H8 + 1, fp);
        fread(kingHashTable[White], sizeof(HashType), H8 + 1, fp);
        fread(kingHashTable[Black], sizeof(HashType), H8 + 1, fp);
        fread(enPassantHashTable, sizeof(HashType), H + 1, fp);
        fread(movedHash, sizeof(HashType), 1, fp);
        fread(castlingHashTable[White], sizeof(HashType), 2, fp);
        fread(castlingHashTable[Black], sizeof(HashType), 2, fp);
        fclose(fp);
    } else {
        srand48((unsigned)time(NULL));
        for (i = A; i <= H; i++) {
            for (j = 1; j <= 8; j++) {
                square = Square(i, j);
                SetRandomHash(pawnHashTable[White][square]);
                SetRandomHash(pawnHashTable[Black][square]);
                SetRandomHash(knightHashTable[White][square]);
                SetRandomHash(knightHashTable[Black][square]);
                SetRandomHash(bishopHashTable[White][square]);
                SetRandomHash(bishopHashTable[Black][square]);
                SetRandomHash(rookHashTable[White][square]);
                SetRandomHash(rookHashTable[Black][square]);
                SetRandomHash(queenHashTable[White][square]);
                SetRandomHash(queenHashTable[Black][square]);
                SetRandomHash(kingHashTable[White][square]);
                SetRandomHash(kingHashTable[Black][square]);
            }
            SetRandomHash(enPassantHashTable[i]);
        }
        SetRandomHash(movedHash);
        SetRandomHash(castlingHashTable[White][Short]);
        SetRandomHash(castlingHashTable[White][Long]);
        SetRandomHash(castlingHashTable[Black][Short]);
        SetRandomHash(castlingHashTable[Black][Long]);

        if ((fp = fopen("random.tab", "wb")) != NULL) {
            fwrite(pawnHashTable[White], sizeof(HashType), H8 + 1, fp);
            fwrite(pawnHashTable[Black], sizeof(HashType), H8 + 1, fp);
            fwrite(knightHashTable[White], sizeof(HashType), H8 + 1, fp);
            fwrite(knightHashTable[Black], sizeof(HashType), H8 + 1, fp);
            fwrite(bishopHashTable[White], sizeof(HashType), H8 + 1, fp);
            fwrite(bishopHashTable[Black], sizeof(HashType), H8 + 1, fp);
            fwrite(rookHashTable[White], sizeof(HashType), H8 + 1, fp);
            fwrite(rookHashTable[Black], sizeof(HashType), H8 + 1, fp);
            fwrite(queenHashTable[White], sizeof(HashType), H8 + 1, fp);
            fwrite(queenHashTable[Black], sizeof(HashType), H8 + 1, fp);
            fwrite(kingHashTable[White], sizeof(HashType), H8 + 1, fp);
            fwrite(kingHashTable[Black], sizeof(HashType), H8 + 1, fp);
            fwrite(enPassantHashTable, sizeof(HashType), H + 1, fp);
            fwrite(movedHash, sizeof(HashType), 1, fp);
            fwrite(castlingHashTable[White], sizeof(HashType), 2, fp);
            fwrite(castlingHashTable[Black], sizeof(HashType), 2, fp);
            fclose(fp);
        }
    }                           /* else */
/*
   if ((fp = fopen( "random.tab", "wb" )) != NULL) {
   for (i=0; i<=H8; i++) {
   reverse( pawnHashTable[ White ][ i ] );
   reverse( pawnHashTable[ Black ][ i ] );
   reverse( knightHashTable[ White ][ i ] );
   reverse( knightHashTable[ Black ][ i ] );
   reverse( bishopHashTable[ White ][ i ] );
   reverse( bishopHashTable[ Black ][ i ] );
   reverse( rookHashTable[ White ][ i ] );
   reverse( rookHashTable[ Black ][ i ] );
   reverse( queenHashTable[ White ][ i ] );
   reverse( queenHashTable[ Black ][ i ] );
   reverse( kingHashTable[ White ][ i ] );
   reverse( kingHashTable[ Black ][ i ] );
   }
   for (i=A; i<=H; i++) {
   reverse( enPassantHashTable[ i ] );
   }
   reverse( movedHash );
   for (i=0; i<2; i++) {
   reverse( castlingHashTable[ White ][ i ] );
   reverse( castlingHashTable[ Black ][ i ] );
   }

   fwrite( pawnHashTable[ White ], sizeof( HashType ), H8+1, fp );
   fwrite( pawnHashTable[ Black ], sizeof( HashType ), H8+1, fp );
   fwrite( knightHashTable[ White ], sizeof( HashType ), H8+1, fp );
   fwrite( knightHashTable[ Black ], sizeof( HashType ), H8+1, fp );
   fwrite( bishopHashTable[ White ], sizeof( HashType ), H8+1, fp );
   fwrite( bishopHashTable[ Black ], sizeof( HashType ), H8+1, fp );
   fwrite( rookHashTable[ White ], sizeof( HashType ), H8+1, fp );
   fwrite( rookHashTable[ Black ], sizeof( HashType ), H8+1, fp );
   fwrite( queenHashTable[ White ], sizeof( HashType ), H8+1, fp );
   fwrite( queenHashTable[ Black ], sizeof( HashType ), H8+1, fp );
   fwrite( kingHashTable[ White ], sizeof( HashType ), H8+1, fp );
   fwrite( kingHashTable[ Black ], sizeof( HashType ), H8+1, fp );
   fwrite( enPassantHashTable, sizeof( HashType ), H+1, fp );
   fwrite( movedHash, sizeof( HashType ), 1, fp );
   fwrite( castlingHashTable[ White ], sizeof( HashType ), 2, fp );
   fwrite( castlingHashTable[ Black ], sizeof( HashType ), 2, fp );
   fclose( fp );
   }
 */
}                               /* FillHashTables */


void            InitTransTable(void)
{
    Unsigned4       i;

    Malloc(transTable, TtEntry, 1L << nrTtBits);
    for (i = 0; i < (1L << nrTtBits); i++) {
        ClearEntry(&(transTable[i]));
    }
}                               /* InitTransTable */


static void     InitPackArrays(void)
{
    Signed2         i,
                    file,
                    rank,
                    piece;

    /* Initialize packPiece and unpackPiece */
    for (piece = 0; piece < Edge; piece++) {
        if (IsKnight(piece)) {
            packPiece[piece] = PackKnight;
        } else if (IsBishop(piece)) {
            packPiece[piece] = PackBishop;
        } else if (IsRook(piece)) {
            packPiece[piece] = PackRook;
        } else if (IsQueen(piece)) {
            packPiece[piece] = PackQueen;
        } else {
            packPiece[piece] = 0;
        }
    }
    unpackPiece[PackKnight] = Knight;
    unpackPiece[PackBishop] = Bishop;
    unpackPiece[PackRook] = Rook;
    unpackPiece[PackQueen] = Queen;

    /* Initialize packSquare and unpackSquare */
    for (i = 0; i <= H8; i++) {
        packSquare[i] = 0;
    }
    for (file = A; file <= H; file++) {
        for (rank = 1; rank <= 8; rank++) {
            packSquare[Square(file, rank)] = (file - A) * 8 + rank - 1;
            unpackSquare[(file - A) * 8 + rank - 1] = Square(file, rank);
        }
    }

    /* Initialize packType and unpackType */
    for (i = 0; i <= 63; i++) {
        packType[i] = 0;
    }
    packType[Normal] = PackNormal;
    packType[Double] = PackDouble;
    packType[ShortCastle] = PackShortCastle;
    packType[LongCastle] = PackLongCastle;
    packType[EnPassant | Capture] = PackEnPassant;
    packType[Capture] = PackCapture;
    packType[Promotion] = PackPromotion;
    packType[Promotion | Capture] = PackCapPromotion;
    unpackType[PackNormal] = Normal;
    unpackType[PackDouble] = Double;
    unpackType[PackShortCastle] = ShortCastle;
    unpackType[PackLongCastle] = LongCastle;
    unpackType[PackEnPassant] = EnPassant | Capture;
    unpackType[PackCapture] = Capture;
    unpackType[PackPromotion] = Promotion;
    unpackType[PackCapPromotion] = Promotion | Capture;
}                               /* InitPackArrays */


static void     UpdateCentreTable(void)
{
    Signed2         i;

    for (i = 0; i <= H8; i++) {
        centreTable[i] /= 1000 / pieceValue[WhitePawn];
    }
}                               /* UpdateCentreTable */


static void     CheckHashTables(void)
{
    Signed2         i,
                    j;
    BoardIndexType  square;
    char            s[4];

    for (i = A; i <= H; i++) {
        for (j = 1; j <= 8; j++) {
            square = Square(i, j);
            SPrintSquare(s, square);
            if (!Unique(pawnHashTable[White][square])) {
                printf("ERROR: pawnHashTable[ White ][ %s ] not unique\n", s);
            }
            if (!Unique(pawnHashTable[Black][square])) {
                printf("ERROR: pawnHashTable[ Black ][ %s ] not unique\n", s);
            }
            if (!Unique(knightHashTable[White][square])) {
                printf("ERROR: knightHashTable[ White ][ %s ] not unique\n", s);
            }
            if (!Unique(knightHashTable[Black][square])) {
                printf("ERROR: knightHashTable[ Black ][ %s ] not unique\n", s);
            }
            if (!Unique(bishopHashTable[White][square])) {
                printf("ERROR: bishopHashTable[ White ][ %s ] not unique\n", s);
            }
            if (!Unique(bishopHashTable[Black][square])) {
                printf("ERROR: bishopHashTable[ Black ][ %s ] not unique\n", s);
            }
            if (!Unique(rookHashTable[White][square])) {
                printf("ERROR: rookHashTable[ White ][ %s ] not unique\n", s);
            }
            if (!Unique(rookHashTable[Black][square])) {
                printf("ERROR: rookHashTable[ Black ][ %s ] not unique\n", s);
            }
            if (!Unique(queenHashTable[White][square])) {
                printf("ERROR: queenHashTable[ White ][ %s ] not unique\n", s);
            }
            if (!Unique(queenHashTable[Black][square])) {
                printf("ERROR: queenHashTable[ Black ][ %s ] not unique\n", s);
            }
            if (!Unique(kingHashTable[White][square])) {
                printf("ERROR: kingHashTable[ White ][ %s ] not unique\n", s);
            }
            if (!Unique(kingHashTable[Black][square])) {
                printf("ERROR: kingHashTable[ Black ][ %s ] not unique\n", s);
            }
        }                       /* for j */
        if (!Unique(enPassantHashTable[i])) {
            printf("ERROR: enPassantHashTable[ %c ] not unique\n", i - A + 'A');
        }
    }                           /* for i */
    if (!Unique(movedHash)) {
        printf("ERROR: movedHash not unique\n");
    }
    for (i = 0; i < 2; i++) {
        if (!Unique(castlingHashTable[White][i])) {
            printf("ERROR: castlingHashTable[ White ][ %d ] not unique\n", i);
        }
        if (!Unique(castlingHashTable[Black][i])) {
            printf("ERROR: castlingHashTable[ Black ][ %d ] not unique\n", i);
        }
    }
}                               /* CheckHashTables */


static          Boolean
                Unique(HashType h)
{
    Signed2         i,
                    j;
    BoardIndexType  square;
    Unsigned2       nr;

    if (h[0] == 0 && h[1] == 0) {
        return (False);
    }
    nr = 0;
    for (i = A; i <= H; i++) {
        for (j = 1; j <= 8; j++) {
            square = Square(i, j);
            if (HashEqual(pawnHashTable[White][square], h)) {
                nr++;
            }
            if (HashEqual(pawnHashTable[Black][square], h)) {
                nr++;
            }
            if (HashEqual(knightHashTable[White][square], h)) {
                nr++;
            }
            if (HashEqual(knightHashTable[Black][square], h)) {
                nr++;
            }
            if (HashEqual(bishopHashTable[White][square], h)) {
                nr++;
            }
            if (HashEqual(bishopHashTable[Black][square], h)) {
                nr++;
            }
            if (HashEqual(rookHashTable[White][square], h)) {
                nr++;
            }
            if (HashEqual(rookHashTable[Black][square], h)) {
                nr++;
            }
            if (HashEqual(queenHashTable[White][square], h)) {
                nr++;
            }
            if (HashEqual(queenHashTable[Black][square], h)) {
                nr++;
            }
            if (HashEqual(kingHashTable[White][square], h)) {
                nr++;
            }
            if (HashEqual(kingHashTable[Black][square], h)) {
                nr++;
            }
        }                       /* for j */
        if (HashEqual(enPassantHashTable[i], h)) {
            nr++;
        }
    }                           /* for i */
    if (HashEqual(movedHash, h)) {
        nr++;
    }
    for (i = 0; i < 2; i++) {
        if (HashEqual(castlingHashTable[White][i], h)) {
            nr++;
        }
        if (HashEqual(castlingHashTable[Black][i], h)) {
            nr++;
        }
    }
#ifdef _DEBUG
	if (nr != 1)
	    printf("number = %d\n", nr);
#endif
    return (nr == 1);
}                               /* Unique */
