

#define _CRT_SECURE_NO_WARNINGS
#define _CRT_NONSTDC_NO_DEPRECATE 
#define _SCL_SECURE_NO_DEPRECATE 
#define _CRT_SECURE_NO_DEPRECATE


#include <stdio.h>
#include <string.h>
#include <time.h>
#include <signal.h>
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <sys/timeb.h>
#include <assert.h>
#include <stdarg.h>
#ifdef _WIN32
#include <windows.h>
#endif
#include "alibaba.h"



/* testing defaults */


static void     SetTestingDefaults(Signed2 * testDepth, Signed2 * testColor,
                                                   Signed4 testNrNodes)
{
    if (*testDepth == -1) {
        if (testNrNodes == -1) {
            *testDepth = DepthDefault;
            printf("\nChoosing default depth %d", DepthDefault);
        } else {
            *testDepth = MaxSearchDepth;
        }
    }
    if (*testColor == -1) {
        *testColor = ColorDefault;
        printf("\nChoosing default color %s", moveColorString[ColorDefault]);
    }
    printf("\n");
}                               /* SetTestingDefaults */


static void     SetDefaults(Boolean * useTransTable, Boolean * useRefTable,
                           Unsigned1 * nrTtBits, Boolean * useTwoLevelTable,
                                            Boolean * useTtValue, Boolean * useTtMove, Boolean * timeStamp,
                                            Boolean * useFlag)
{
     
	printf("Choosing default transpo %d\n", *useTransTable);
    printf("Choosing default ref %d\n", *useRefTable);
    printf("Choosing default nrTtBits %d\n", *nrTtBits);
    printf("Choosing default twoLevelTable %d\n", *useTwoLevelTable);
    printf("Choosing default ttValue %d\n", *useTtValue);
    printf("Choosing default ttMove %d\n", *useTtMove);
    printf("Choosing default timeStamp %d\n", *timeStamp);
    printf("Choosing default useFlag %d\n", *useFlag);
    
}                               /* SetDefaults */


static void     PerformTest(Signed2 startingMove, Signed2 testColor,
                                            Signed2 testDepth)
{
    Signed2         startingPly,
                    i;
    Unsigned2       testMaxGamePlies;
    char            testGameString[MaxGamePlies][MaxMoveLength];
    MoveType        testGame[MaxGamePlies];
    Boolean         blackBegin;
    char            s[MaxMoveLength];
    MoveType        move;
    ValueType       value;

    startingPly = (startingMove - 1) * 2;
    if ((toMove == White && nrGamePlies % 2 == 0) ||
        (toMove == Black && nrGamePlies % 2 == 1)) {
        if (testColor == Black) {
            ++startingPly;
        }
        blackBegin = false;
    } else {
        if (testColor == White) {
            --startingPly;
        }
        blackBegin = true;
    }
    if (startingPly < 0 || startingPly >= nrGamePlies) {
        printf("ERROR: Starting move '%d' not possible\n", startingMove);
        exit(0);
    }
    /* Save variables */
    testMaxGamePlies = maxGamePlies;
    for (i = 0; i < testMaxGamePlies; i++) {
        testGame[i] = game[i];
        strcpy(testGameString[i], gameString[i]);
    }
    /* Take moves back */
    for (i = 0; i < maxGamePlies - startingPly; i++) {
        UndoMove();
    }
    /* Calculate the moves */
    for (i = startingPly; i < testMaxGamePlies; i++) {
        if (material[White] <= EndgameMaterial ||
            material[Black] <= EndgameMaterial) {
            printf("Stop: endgame reached\n");
            break;
        }
        if ((i - startingPly) % 2 == 0) {
            if (testColor != toMove) {
                printf("ERROR: wrong search color\n");
                exit(0);
            }
            printf("\nCalculating move %d\n", blackBegin ? (i + 3) / 2 : (i + 2) / 2);
            Search((Signed1) testDepth, &move, &value);
            if (move.from) {
                SPrintMove(s, move);
                printf("My move: %s\n", s);
            }
        }
        DoMove(&(testGame[i]));
        printf("Forward: %s\n", testGameString[i]);
    }
}                               /* PerformTest */



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



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     UpdatePieceTables(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)
{
    
    ReadINIFile(INI_FILENAME);
    
    FillHashTables();
    CheckHashTables();
    EmptyBoard();               /* Has to be done before InitMoveTables! */
    InitMoveTables();
    InitPieceSymbols();
    InitPieceValues();
    InitAllocVariables();
    StartingPosition();
    InitPackArrays();
    UpdatePieceTables();
    TestArguments();
    
    first_move = true;		
    force_mode = false;
    maxdepth = 80;
    MAX_TIME = 60;
    timeadd = maxtime = move_count = 0;    
    
    
    
}                               /* 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;
            pawnMoveTable[Black][i][j] = 0;
        }
    }
    for (i = A; i <= H; i++) {
        for (j = 1; j <= 8; j++) {
            from = Square(i, j);
            if (j == 2) pawnMoveTable[White][from][1] = from + Up + Up;
            if (j == 7) pawnMoveTable[Black][from][1] = from + Down + Down;
                      
            pawnMoveTable[White][from][0] = from + Up;
            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] = pieceSymbol[WhiteKnight] = pieceSymbol[WhiteBishop] = 
	pieceSymbol[WhiteRook] = pieceSymbol[WhiteQueen]  = pieceSymbol[WhiteKing]   = 
	pieceSymbol[BlackPawn] = pieceSymbol[BlackKnight] = pieceSymbol[BlackBishop] = 
	pieceSymbol[BlackRook] = pieceSymbol[BlackQueen]  = pieceSymbol[BlackKing] = ' ';

    

}                               /* InitPieceSymbols */


/*----------------------------------------------------------------------
 | InitPieceValues.						940425
 |
 | Initializes all piece values.
 +----------------------------------------------------------------------*/
static void     InitPieceValues(void)
{
    Signed2         i;
    
    bp_bonus         = value_pawn/2;
    bp_bonus_extra   = value_pawn/2;
    rp_bonus         = value_pawn/2;
    

    for (i = 0; i < 128; i++) {
        pieceValue[i] = 0;
    }
    if (!ENDGAME_REACHED) {
                         
    pieceValue[WhitePawn]   = pieceValue[BlackPawn]   = value_pawn;
    pieceValue[WhiteKnight] = pieceValue[BlackKnight] = value_knight;
    
    ///////// bishop pair bonuses ///////////////////
    if (bishop_pair_bonus)  {
    pieceValue[WhiteBishop] = pieceValue[BlackBishop] = value_bishop+bp_bonus;
    if (bishop_pair_bonus && bishop_pair_bonus_extra) 
    pieceValue[WhiteBishop] = pieceValue[BlackBishop] = value_bishop+bp_bonus+bp_bonus_extra;
    
}else{
    pieceValue[WhiteBishop] = pieceValue[BlackBishop] = value_bishop;
}  
  ////////////////////////////////////////////////////////
  
  
  //////////////////// rook pair bonuses //////////////////////
   if (rook_pair_bonus) {
    pieceValue[WhiteRook]   = pieceValue[BlackRook]   = endgame_value_rook+rp_bonus;
}else{
    pieceValue[WhiteRook]   = pieceValue[BlackRook]   = endgame_value_rook;  
}
 //////////////////////////////////////////////////////////////   
  
  
   
    pieceValue[WhiteQueen]  = pieceValue[BlackQueen]  = value_queen;
    pieceValue[WhiteKing]  = pieceValue[BlackKing]    = value_king;
   
    
}else{
      
      
    pieceValue[WhitePawn]   = pieceValue[BlackPawn]   = endgame_value_pawn;
    pieceValue[WhiteKnight] = pieceValue[BlackKnight] = endgame_value_knight;
    
    
    ///////////////// bishop pair bonuses ////////////////////
    if (bishop_pair_bonus)  {
    pieceValue[WhiteBishop] = pieceValue[BlackBishop] = value_bishop+bp_bonus;
    if (bishop_pair_bonus && bishop_pair_bonus_extra) 
    pieceValue[WhiteBishop] = pieceValue[BlackBishop] = value_bishop+bp_bonus+bp_bonus_extra;
    
}else{
    pieceValue[WhiteBishop] = pieceValue[BlackBishop] = value_bishop;
}  
   /////////////////////////////////////////////////////////// 
    
    
    ///////////////////////// rook pair bonuses ///////////////////////
    if (rook_pair_bonus) {
    pieceValue[WhiteRook]   = pieceValue[BlackRook]   = endgame_value_rook+rp_bonus;
}else{
    pieceValue[WhiteRook]   = pieceValue[BlackRook]   = endgame_value_rook;  
}
    ////////////////////////////////////////////////////////////////////
    
    
    pieceValue[WhiteQueen]  = pieceValue[BlackQueen]  = endgame_value_queen;
    pieceValue[WhiteKing]   = pieceValue[BlackKing]   = endgame_value_king;
   
    
}     
      
      

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




void            PieceCount(void)  // JA
{
    BoardIndexType  i,
                    j;
                    
                    white_pawns = black_pawns = white_knights = 
                    black_knights = white_bishops = black_bishops = 
                    white_rooks = black_rooks = white_queens = black_queens =  
                    total_piece_count = 0;
                    
                    
                    White_Bishop_Square_White = false;
                    White_Bishop_Square_Black = false;
                    Black_Bishop_Square_White = false;
                    Black_Bishop_Square_Black = false;

    for (i = A; i <= H; i++) {
        for (j = 1; j <= 8; j++) {
            
                       
        if (board[Square(i, j)] == WhitePawn) white_pawns ++;
        else
        if (board[Square(i, j)] == BlackPawn) black_pawns ++;
        else
        if (board[Square(i, j)] == WhiteKnight) white_knights ++;
        else
        if (board[Square(i, j)] == BlackKnight) black_knights ++;
        else    
        if (board[Square(i, j)] == WhiteBishop) {
        white_bishops ++;
        if (board[Square(i, j)] == White) White_Bishop_Square_White = true;
        if (board[Square(i, j)] == Black) White_Bishop_Square_Black = true;  
        }  
        else
        if (board[Square(i, j)] == BlackBishop) {
        black_bishops ++;
        if (board[Square(i, j)] == White) Black_Bishop_Square_White = true;
        if (board[Square(i, j)] == Black) Black_Bishop_Square_Black = true;    
        }
        else
        if (board[Square(i, j)] == WhiteRook) white_rooks ++;
        else
        if (board[Square(i, j)] == BlackRook) black_rooks ++;
        else
        if (board[Square(i, j)] == WhiteQueen) white_queens ++;
        else
        if (board[Square(i, j)] == BlackQueen) black_queens ++;
        
        
        
        
        
        }}  
        
        total_piece_count = (white_pawns   +  black_pawns   + 
                             white_knights +  black_knights +
                             white_bishops +  black_bishops +
                             white_rooks   +  black_rooks   +
                             white_queens  +  black_queens);
         
         
         
                            
        
        ////// last pawn on board - very valuable ////////
        if (!last_pawn) {
        if (white_pawns + black_pawns == 1) {
                        
        value_pawn *=2, endgame_value_pawn *=2;
        last_pawn = true;
        }}                
        /////////////////////////////////////////////////////
        
        
        

 //////////////////// add piece value bonuses/increases ////////////////////
        
        //////// bishop pair/rook pair value increases ///////////
        ////////         if you are a queen down       ///////////
        
        if (computer == White && black_queens > white_queens) {
        if (white_rooks == 2)  rook_pair_bonus = true;
        if (white_bishops == 2) bishop_pair_bonus_extra = true; 
        }
        
        if (computer == Black && white_queens > black_queens) {
        if (black_rooks == 2)  rook_pair_bonus = true;
        if (black_bishops == 2) bishop_pair_bonus_extra = true; 
        }
        //////////////////////////////////////////////////////////
        
        
        
        ////// value of rook pair increases if you are a bishop down ////////

        if (computer == White && white_bishops < black_bishops && white_rooks == 2) {
            rook_pair_bonus = true;
            }
                        
       if (computer == Black && black_bishops < white_bishops && black_rooks == 2) {
            rook_pair_bonus = true;
            }             
        ////////////////////////////////////////////////////////////////////
        
        
        
        
        ////////// bishop pair value increases if you are a rook down  /////////
        ///////////              or a knight down                   ///////////        
        
        if (computer == White && white_rooks < black_rooks && white_bishops == 2) {
            bishop_pair_bonus = true;
            }
            
         if (computer == Black && black_rooks < white_rooks && black_bishops == 2) {
            bishop_pair_bonus = true;
            }            
        
        if (computer == White && white_knights < black_knights && white_bishops == 2) {
            bishop_pair_bonus = true;
            }
        
        if (computer == Black && black_knights < white_knights && black_bishops == 2) {
            bishop_pair_bonus = true;
            }
         //////////////////////////////////////////////////////////////////////
        
 
 
       /////////// if only pawns left on board, search depth is extended ////////////
      
       if (white_pawns + black_pawns > 0) {
       if (white_knights + black_knights == 0) {
       if (white_bishops + black_bishops == 0) {
       if (white_rooks   + black_rooks   == 0) {
       if (white_queens  + black_queens  == 0) {
        
        only_pawns_left = true;
        }}}}}
        //////////////////////////////////////////////////////////////////////           
       
 
 
 
  /////// check if all piece value increases still apply ////////
  
        if (bishop_pair_bonus) {
        if (computer == White && white_bishops < 2 || 
            computer == Black && black_bishops < 2) {
            bishop_pair_bonus = false;
            bishop_pair_bonus_extra = false; 
            }}
 
        
        if (rook_pair_bonus) {
        if (computer == White && white_rooks < 2 ||
            computer == Black && black_rooks < 2) {
            rook_pair_bonus = false;
            }}
            
  ////////////////////////////////////////////////////////////   
            
            
            
            
           
            
            /// if up on material, go for exchanges //////////
            
             if (computer == White && (material[White] >  material[Black]) + 100 ||
           computer == Black && (material[Black] >  material[White]) + 100) {
           
           incentive_capture = 80;
           }else{
           incentive_capture = 1;
            }
                 
           ////////////////////////////////////////////////////////
            
            
            
            
            
            
            if (using_insufficient_draw) {
            
            //////////// checks for insufficiant material to checkmate (draw) ////////////////
            
            
            if (ENDGAME_REACHED) {
            if (total_piece_count == 0) insufficiant_material = true;     // only kings left
            
            if (total_piece_count == 1) {
            if (white_bishops + black_bishops == 1) {          // king vs king + bishop
            insufficiant_material = true;  
            }}
            
            
            if (total_piece_count == 1) {
            if (white_knights + black_knights == 1) {         // king vs king + knight
            insufficiant_material = true;  
            }}
              
              
              
            if (total_piece_count == 2) {
            if (white_bishops + black_bishops == 2) {               // king & bishop vs king & bishop with 
                                                                    // the bishops on the same color
            if (White_Bishop_Square_White == true && Black_Bishop_Square_White == true ||
                White_Bishop_Square_Black == true && Black_Bishop_Square_Black == true) {
                                          
               insufficiant_material = true;  
              }
              }                           
              }}}
            
           //////////////////////////////////////////////////////////////////////////////////// 
            
            
            
            ///////////     in futile positions (almost no chance of mate) - offer a draw   /////////////
          
            if (total_piece_count == 2) {
            if (white_rooks + black_rooks == 2) {             // king & rook vs king & rook
            
            draw_offer = true;
            }}
            
            if (total_piece_count == 2) {
            if (white_rooks + black_bishops == 2) {              // king & rook vs king & bishop
            draw_offer = true;
            }}
            
            
            if (total_piece_count == 2) {
            if (white_knights + black_knights == 2) {             // king & knight vs king & knight
            draw_offer = true;
            }}
            
            
            if (total_piece_count == 2) {
            if (white_knights == 2 || black_knights == 2) {             // king vs king & two knights
            draw_offer = true;
            }}
            
            /////////////////////////////////////////////////////////////////////////////////////////////////
            
 
 
 InitPieceValues();
 UpdatePieceTables();         
}                              





















/*----------------------------------------------------------------------
 | 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];
  
  
    UpdatePieceTables();
    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]   = knightEvalTable[White][i] = 
        knightEvalTable[Black][i] = bishopEvalTable[White][i] = bishopEvalTable[Black][i] = 
        rookEvalTable[White][i]   = rookEvalTable[Black][i]   = queenEvalTable[White][i]  = 
        queenEvalTable[Black][i]  = 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];
    }
    if (computer == White) IScore += positionalValue[White];
    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];
    }
     if (computer == Black) IScore += positionalValue[Black];

}                               /* 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;

    
        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]);

       
    }                          
 }



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     UpdatePieceTables(void)
{
    Signed2         i;

    for (i = 0; i <= H8; i++) {
        
        if (!ENDGAME_REACHED) {
        
        KingTable[i]   /= 1000 / pieceValue[WhitePawn];
        KnightTable[i] /= 1000 / pieceValue[WhitePawn];
        BishopTable[i] /= 1000 / pieceValue[WhitePawn];
        RookTable[i]   /= 1000 / pieceValue[WhitePawn];
        QueenTable[i]  /= 1000 / pieceValue[WhitePawn];
        PawnTable[i]   /= 1000 / pieceValue[WhitePawn];
           
        }else{
        KingTable_Endgame[i]   /= 1000 / pieceValue[WhitePawn];
        KnightTable[i]         /= 1000 / pieceValue[WhitePawn];
        BishopTable_Endgame[i] /= 1000 / pieceValue[WhitePawn];
        RookTable_Endgame[i]   /= 1000 / pieceValue[WhitePawn];
        QueenTable_Endgame[i]  /= 1000 / pieceValue[WhitePawn];
        PawnTable_Endgame[i]   /= 1000 / pieceValue[WhitePawn];
        }  
                        
        
    }
}                               /* UpdatePieceTables */


                   /* UpdatePieceTables */





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



////////////////////////// srand48  /////////////////////////


/*
 * Copyright (c) 1993 Martin Birgmeier
 * All rights reserved.
 *
 * You may redistribute unmodified or modified versions of this source
 * code provided that the above copyright notice and this and the
 * following conditions are retained.
 *
 * This software is provided ``as is'', and comes with no warranties
 * of any kind. I shall in no event be liable for anything that happens
 * to anyone/anything when using this software.
 */


static unsigned short _rand48_seed[3];
static unsigned short _rand48_mult[3];
static unsigned short _rand48_add;

void
srand48(long seed)
{
	_rand48_seed[0] = RAND48_SEED_0;
	_rand48_seed[1] = (unsigned short) seed;
	_rand48_seed[2] = (unsigned short) (seed >> 16);
	_rand48_mult[0] = RAND48_MULT_0;
	_rand48_mult[1] = RAND48_MULT_1;
	_rand48_mult[2] = RAND48_MULT_2;
	_rand48_add = RAND48_ADD;
}


/////////////////////// Drand48 //////////////////////

/*
 * Copyright (c) 1993 Martin Birgmeier
 * All rights reserved.
 *
 * You may redistribute unmodified or modified versions of this source
 * code provided that the above copyright notice and this and the
 * following conditions are retained.
 *
 * This software is provided ``as is'', and comes with no warranties
 * of any kind. I shall in no event be liable for anything that happens
 * to anyone/anything when using this software.
 */


extern unsigned short _rand48_seed[3];

double
drand48(void)
{
	return erand48(_rand48_seed);
}



///////////////////// erand48  ////////////////////////


/*
 * Copyright (c) 1993 Martin Birgmeier
 * All rights reserved.
 *
 * You may redistribute unmodified or modified versions of this source
 * code provided that the above copyright notice and this and the
 * following conditions are retained.
 *
 * This software is provided ``as is'', and comes with no warranties
 * of any kind. I shall in no event be liable for anything that happens
 * to anyone/anything when using this software.
 */


double
erand48(unsigned short xseed[3])
{
	_dorand48(xseed);
	return ldexp((double) xseed[0], -48) +
	       ldexp((double) xseed[1], -32) +
	       ldexp((double) xseed[2], -16);
}



///////////////////////////  _rand48 //////////////


/*
 * Copyright (c) 1993 Martin Birgmeier
 * All rights reserved.
 *
 * You may redistribute unmodified or modified versions of this source
 * code provided that the above copyright notice and this and the
 * following conditions are retained.
 *
 * This software is provided ``as is'', and comes with no warranties
 * of any kind. I shall in no event be liable for anything that happens
 * to anyone/anything when using this software.
 */



static unsigned short _rand48_seed[3] = {
	RAND48_SEED_0,
	RAND48_SEED_1,
	RAND48_SEED_2
};
static unsigned short _rand48_mult[3] = {
	RAND48_MULT_0,
	RAND48_MULT_1,
	RAND48_MULT_2
};
static unsigned short _rand48_add = RAND48_ADD;

extern void
_dorand48(unsigned short xseed[3])
{
	unsigned long accu;
	unsigned short temp[2];

	accu = (unsigned long) _rand48_mult[0] * (unsigned long) xseed[0] +
	 (unsigned long) _rand48_add;
	temp[0] = (unsigned short) accu;	/* lower 16 bits */
	accu >>= sizeof(unsigned short) * 8;
	accu += (unsigned long) _rand48_mult[0] * (unsigned long) xseed[1] +
	 (unsigned long) _rand48_mult[1] * (unsigned long) xseed[0];
	temp[1] = (unsigned short) accu;	/* middle 16 bits */
	accu >>= sizeof(unsigned short) * 8;
	accu += _rand48_mult[0] * xseed[2] + _rand48_mult[1] * xseed[1] + _rand48_mult[2] * xseed[0];
	xseed[0] = temp[0];
	xseed[1] = temp[1];
	xseed[2] = (unsigned short) accu;
}



/*----------------------------------------------------------------------
 | AB 							940426
 |
 | Contains all ab-search functions.
 +----------------------------------------------------------------------*/

static ValueType Ab(Signed1 depth, ValueType alpha, ValueType beta,
                                    PathType ** bestPath);
static void     PutMoveInFront(MoveType * moveList, Unsigned1 nrMoves,
                                               MoveType * ttMove);
static double   PercFilled(void);
static Unsigned4 NrFilled(void);
static Unsigned4 ExpectedCollisions(Unsigned4 nodes);


/*----------------------------------------------------------------------
 | Search							940426
 |
 | Search for the best move at the root of the tree.
 +----------------------------------------------------------------------*/
void            Search(Signed1 searchDepth, MoveType * move, ValueType * bestValue)
{
    Unsigned1       nrMoves;
    MoveType       *moveList,
                    tempMove;
    ValueType       value,
                    alfa,
                    beta;
    Signed2         i,
                    j;
    Unsigned4       count,
                    ttNodes={0},
                    tot;
    Signed1         depth;
    double          timeUsed;
    Boolean         printDepth;
    PathType       *mainLine[MaxMoves],
                  *tempPath;
    Signed1         ttDepth={0};
    Unsigned1       flag;
    MoveType        ttMove;
    ValueType       ttValue;
    char  s[MaxMoveLength + 1];
    
        
    start_time = get_ms();
	stop_time = start_time + maxtime;

    nrGenerates = nrMovesGenerated = 0;
    shortest_mate = false;
    printDebug = false;
    
	if (!Stop_Search) {
	stopSearching = false;
	}else{
    Stop_Search = false;
    stopSearching = true;
	}
	StartTime();
 
    computer = toMove;
    
    for (i = 0; i < MaxMoves; i++) {
        mainLine[i] = NULL;
    }
    nrInternalNodes = nrLeafNodes = nrQuiesNodes = 0;
    nrTotalNodes = nrExtraNodes = 0;
    nrCollisions = nrHits = nrReads = nrWrites = 0;
    nrIllegalMoves = 0;
  
 
  
  
    if (searchDepth == 0) {
        PreProcessing();
    
      
        value = Quiescence(-Infinity, Infinity, &(mainLine[0]), -2, 0, 0, 0);    
                              
        
        if (edit_mode && shortest_mate) {
        PrintSearchInfo_edit( 0, value, timeUsed, mainLine[0], shortmate );
        }else          
        if (icc) {
        PrintSearchInfo_ICS( 0, value, timeUsed, mainLine[0]);
        }else{
        PrintSearchInfo( 0, value, timeUsed, mainLine[0]);
        }
       
        FreePath(mainLine[0]);
        move->from = 0;
        return;
    }
    if (searchDepth > MaxSearchDepth) {
        searchDepth = MaxSearchDepth;
    }
    startPly = nrGamePlies;
    if (startPly > 455) {
        printf("Warning: startPly too big!\n");
        startPly = 455;
    }
    /* Clear transposition tables */
    if (useTransTable && !timeStamp) {
        tot = useTwoLevelTable ? 1L << (nrTtBits + 1) : 1L << nrTtBits;
        for (count = 0; count < tot; count++) {
            if (GetFlag(&(transTable[count])) != NoEntry &&
                GetPly(&(transTable[count])) + keepPly < nrGamePlies) {
                ClearEntry(&(transTable[count]));
            }
        }
    }
    if (useTransTable && hash_stats_show) {
        if (!Stop_Search) {
        printf("[%lu positions remaining in transposition table]\n", NrFilled());
        }
    }
    ClearHistoryTables();
    PreProcessing();
    GenerateMoves(&moveList, &nrMoves);
    if (nrMoves == 0) {
        if (Attacked(kingSquare[toMove], (SquareType) ! toMove)) {
            if (!Stop_Search) {
            printf("[Alibaba] Mate\n");
			printf("computer mates\n");
			Stop_Search = true;
			computer = Empty;
			force_mode = true;
        }
        } else {
            if (!Stop_Search) {
            printf("[Alibaba] Stalemate\n");
			printf("game is a draw\n");
			Stop_Search = true;
            computer = Empty;
            force_mode = true;
            }
        }
        move->from = 0;
        return;
    }
    HeapSort(moveList, nrMoves);
    GetMoveFromTransTable(ttMove, ttDepth, ttValue, flag, ttNodes);
    if (ttDepth != -1 && IsIllegal(ttMove)) {
        SPrintMove(s, ttMove);
        printf("Illegal move: %s\n", s);
        ttDepth = -1;
        nrIllegalMoves++;
    }
    if (useTtMove && ttDepth != -1) {
        PutMoveInFront(moveList, nrMoves, &ttMove);
    }
    for (i = 0; i < nrMoves; i++) {
        AllocatePathMove(mainLine[i]);
        SPrintMove(mainLine[i]->moveString, moveList[i]);
        mainLine[i]->move = moveList[i];
    }
    for (depth = 1; depth <= searchDepth; depth++) {
        ++nrInternalNodes;
        
         
		
		if (++nrTotalNodes - nrExtraNodes >= testNrNodes && testNrNodes != -1 ||
			
			get_ms() >= stop_time) { 
            stopSearching = true;
            break;
        }
        for (i = 0; i < nrMoves; i++) {
           
           
  		

if (analyze_on) {
if (!strcmp(wb_command, ".\n")) {         
           
           printf("stat01: time nodes ply mvleft mvtot mvname\n");
}}          
           DoMove(&(moveList[i]));
            if (i == 0) {       /* first move: aspiration search */
                if (depth == 1) {
                    alfa = -Infinity;
                    beta = Infinity;
                } else {        /* depth > 1 */
                    alfa = *bestValue - pieceValue[WhitePawn];
                    beta = *bestValue + pieceValue[WhitePawn];
                }
                value = -Ab(depth - 1, -beta, -alfa, &(mainLine[i]->next));
                
                             
                if (value >= beta && !stopSearching) {  /* Fail high */
                    
                    if (edit_mode && shortest_mate) {
                    PrintSearchInfo_edit( depth, value, timeUsed, mainLine[0], shortmate );
                    }else          
                    if (icc) {
                    PrintSearchInfo_ICS(depth, value, timeUsed,  mainLine[i]);
                    }else{
                    PrintSearchInfo(depth, value, timeUsed,  mainLine[i]);
                    }
                  
                   *bestValue = -Ab(depth - 1, -Infinity, -value,
                                     &(mainLine[i]->next));
                    printDepth = false;
                } else if (value <= alfa && !stopSearching) {   /* Fail low */
                 
                    if (edit_mode && shortest_mate) {
                    PrintSearchInfo_edit( depth, value, timeUsed, mainLine[0], shortmate );
                    }else          
                    if (icc) {
                    PrintSearchInfo_ICS(depth, value, timeUsed,  mainLine[i]);
                    }else{
                    PrintSearchInfo(depth, value, timeUsed,  mainLine[i]);
                    }
                    
                    *bestValue = -Ab(depth - 1, -value, Infinity, &(mainLine[i]->next));
                    printDepth = false;
                } else {        /* Na fail high or low */
                    if (!stopSearching) {
                        *bestValue = value;
                    } else if (depth == 1) {
                        *bestValue = 0; /* Unknown best value */
                    }
                    printDepth = true;
                }
                
                
                
                
                if (printDepth) {
                    if (edit_mode && shortest_mate) {
                    PrintSearchInfo_edit( depth, *bestValue, timeUsed, mainLine[0], shortmate );
                    }else          
                    if (icc) {
                    PrintSearchInfo_ICS(depth, *bestValue, timeUsed, mainLine[0]);
                    }else{           
                    PrintSearchInfo(depth, *bestValue, timeUsed, mainLine[0]);
                    }
                } else {
                    if (edit_mode && shortest_mate) {
                    PrintSearchInfo_edit( 0, *bestValue, timeUsed, mainLine[0], shortmate );
                    }else          
                    if (icc) {
                    PrintSearchInfo_ICS(0, *bestValue,timeUsed, mainLine[0]);
                    }else{
                    PrintSearchInfo(0, *bestValue,timeUsed, mainLine[0]);
                    }
                }
            } else {            /* rest of the moves: zero window */
                value = -Ab(depth - 1, -*bestValue - 1, -*bestValue,
                            &(mainLine[i]->next));
                if (value > *bestValue && !stopSearching) {     /* Fail high */
                    
                    if (edit_mode && shortest_mate) {
                    PrintSearchInfo_edit( 0, value, timeUsed, mainLine[0], shortmate );
                    }else          
                    if (icc) {
                    PrintSearchInfo_ICS(0, value, timeUsed, mainLine[i]);
                    }else{
                    PrintSearchInfo(0, value, timeUsed, mainLine[i]);
                    }
                    
                    *bestValue = -Ab(depth - 1, -Infinity, -value,
                                     &(mainLine[i]->next));
                    tempMove = moveList[i];
                    tempPath = mainLine[i];
                    for (j = i; j > 0; j--) {
                        moveList[j] = moveList[j - 1];
                        mainLine[j] = mainLine[j - 1];
                    }
                    moveList[0] = tempMove;
                    mainLine[0] = tempPath;
                     
                    if (edit_mode && shortest_mate) {
                    PrintSearchInfo_edit( 0, *bestValue, timeUsed, mainLine[0], shortmate );
                    }else              
                    if (icc) {
                    PrintSearchInfo_ICS(0, *bestValue, timeUsed, mainLine[0]);
                    }else{
                    PrintSearchInfo(0, *bestValue, timeUsed, mainLine[0]);
                    }
                }               /* if fail high */
            }                   /* rest of the moves */
            UndoMove();
            if (stopSearching) {
                break;
            }
            
            if (*bestValue == Mate - depth) {   /* Shortest mate found */
                if (analyze_on) {
                shortest_mate = true;
                }else{              
                printf("--> Shortest mate found, stop searching\n");
                stopSearching = true;
                break;
                }
            }
        }                       /* for move */
        StopTime(timeUsed);
        if (!IsCaptureMove(moveList[0].type)) {
            historyTable[toMove][moveList[0].from][moveList[0].to] +=
                1 << depth;
        }
        if (!analyze_on) {
        if (*bestValue <= -MateValue) { /* Best value loses */
            printf("--> Best value loses, stop searching\n");
            break;
        }}
        if (stopSearching) {
            break;
        }
    }                           /* for depth */
    *move = moveList[0];
    FreeMoveList(moveList);
    for (i = 0; i < MaxMoves; i++) {
        FreePath(mainLine[i]);
    }
    nrTotalNodes -= nrExtraNodes;       /* When using BigAll */
    
    if (hash_stats_show) { 
    printf("%lu nodes (int:%lu, leaf:%lu, quies:%lu), %lu n/s\n",
           nrTotalNodes, nrInternalNodes, nrLeafNodes, nrQuiesNodes,
           (nrTotalNodes == 0 || timeUsed == 0) ? 0 :
           (Unsigned4) (nrTotalNodes / timeUsed));
           }
    if (useTransTable) {
        PutMoveInTransTable(*move, depth - 1, *bestValue, Valid,
                            nrTotalNodes + nrExtraNodes);
        if (hash_stats_show) {
        printf("%lu filled (%5.2f%%), %lu reads, %lu hits (%5.2f%%) %lu writes\n",
        NrFilled(), PercFilled(), nrReads, nrHits, nrHits * 100.0 / nrReads,
               nrWrites);
        }
        
        if (hash_stats_show) {
        printf("%lu collisions, %lu expected\n", nrCollisions,
              ExpectedCollisions(NrFilled() + nrCollisions));
              }
              
        if (nrIllegalMoves != 0) {
            printf("Error (illegal moves): %d\n", nrIllegalMoves);
           
        }
    }
    if (hash_stats_show) {
    printf("%lu moves in %lu times (%5.2f)\n", nrMovesGenerated, nrGenerates,
           nrMovesGenerated * 1.0 / nrGenerates);
                   
}

} 
                              /* Search */


/*----------------------------------------------------------------------
 | Ab								940502
 |
 | This is the recursive alpha-beta search procedure.
 +----------------------------------------------------------------------*/
static          ValueType
                Ab(Signed1 depth, ValueType alpha, ValueType beta,
                                   PathType ** bestPath)
{
    Unsigned1       nrMoves;
    MoveType       *moveList,
                    ttMove={0};
    ValueType       value,
                    bestValue,
                    bestQuies,
                    ttValue={0};
    Signed2         i;
    PathType       *tempPath;
    Boolean         betterMoveFound,
                    firstMove;
    MoveType        bestMove,
                    pathMove;
    Signed1         ttDepth={0};
    Unsigned1       flag={0};
    char            s[MaxMoveLength + 1]={0};
    ValueType       maxAlpha;
    Unsigned4       ttNodes={0},
                    startNodes;
    

    maxAlpha = alpha;
    if (nrGamePlies - startPly <= debugDepth) {
        PrintGame(startPly, nrGamePlies - 1);
        printf("%lu (%ld, %ld), (%x, %x)\n", nrTotalNodes, alpha, beta,
               hashValue[nrGamePlies][0], hashValue[nrGamePlies][1]);
    }
    startNodes = nrTotalNodes;
    /* Repetition of position or 50 move rule? */
    if (ItIsADraw()) {
        ++nrLeafNodes;
        if (++nrTotalNodes - nrExtraNodes >= testNrNodes && testNrNodes != -1 ) {
            stopSearching = true;
        }
        return (Draw);
    }
    GetMoveFromTransTable(ttMove, ttDepth, ttValue, flag, ttNodes);
    if (ttDepth != -1 && nrGamePlies - startPly <= debugDepth) {
        char            sss[10];
        SPrintMove(sss, ttMove);
        printf("From table: %s (val:%d, depth:%d, flag:%d)\n",
               sss, ttValue, ttDepth, flag);
    }
    if (ttDepth != -1 && IsIllegal(ttMove)) {
        SPrintMove(s, ttMove);
        printf("Illegal move: %s\n", s);
        printf("Error (Illegal move): %s\n", s);
        ttDepth = -1;
        nrIllegalMoves++;
    }
    /* Use ttValue */
    if (useTtValue && ttDepth >= depth) {
        if (keepMethod == BigAll) {
            nrTotalNodes += ttNodes;
            nrExtraNodes += ttNodes;
        }
        if (flag == Valid) {
            ++nrLeafNodes;
            if (++nrTotalNodes - nrExtraNodes >= testNrNodes && testNrNodes != -1) {
                stopSearching = true;
            }
            FreePath(*bestPath);
            AllocatePathMove(*bestPath);
            SPrintMove((*bestPath)->moveString, ttMove);
            (*bestPath)->move = ttMove;
            if (nrGamePlies - startPly <= debugDepth) {
                printf("TT (valid) cut-off\n");
            }
            return (ttValue);
        } else if (flag == LowerBound) {
            if (ttValue > maxAlpha) {
                maxAlpha = ttValue;
            }
        } else {                /* flag == UpperBound */
            if (beta > ttValue) {
                beta = ttValue;
            }
        }
        if (maxAlpha >= beta) {
            ++nrLeafNodes;
            if (++nrTotalNodes - nrExtraNodes >= testNrNodes && testNrNodes != -1) {
                stopSearching = true;
            }
            FreePath(*bestPath);
            AllocatePathMove(*bestPath);
            SPrintMove((*bestPath)->moveString, ttMove);
            (*bestPath)->move = ttMove;
            if (nrGamePlies - startPly <= debugDepth) {
                printf("TT cut-off\n");
            }
            return (ttValue);
        }
    }                           /* if ttDepth >= depth */
    /* Leaf node */

    
    if (depth == 0) { 
        
     bestValue = Quiescence(maxAlpha, beta, bestPath, ttDepth, ttValue, flag,
                               ttNodes);
                               
        
        /* Add '.' to show where quiescence starts */
        if (*bestPath != NULL && (*bestPath)->moveString[0] != '.') {
            for (i = MaxMoveLength - 1; i > 0; i--) {
                (*bestPath)->moveString[i] = (*bestPath)->moveString[i - 1];
            }
            (*bestPath)->moveString[0] = '.';
            (*bestPath)->moveString[MaxMoveLength - 1] = '\0';
        }
        return (bestValue);
    }
    firstMove = true;
    nrMoves = 0;
    ++nrInternalNodes;
    if (++nrTotalNodes - nrExtraNodes >= testNrNodes && testNrNodes != -1) {
       
        stopSearching = true;
        return (-Infinity);
    }
    /* Try refutation table move first */
    if (useRefTable && *bestPath != NULL) {
        if ((*bestPath)->moveString[0] == '.') {
            /* Remove '.' for it's no longer quiescence search */
            for (i = 0; i < MaxMoveLength - 2; i++) {
                (*bestPath)->moveString[i] = (*bestPath)->moveString[i + 1];
            }
            (*bestPath)->moveString[MaxMoveLength - 2] = ' ';
            (*bestPath)->moveString[MaxMoveLength - 1] = '\0';
        }
        firstMove = false;
        pathMove = (*bestPath)->move;
        DoMove(&pathMove);
        bestValue = -Ab(depth - 1, -beta, -maxAlpha, &((*bestPath)->next));
        UndoMove();
        bestMove = pathMove;
        if (stopSearching) {
            return (-Infinity);
        }
        if (bestValue >= beta) {
            goto BetaCutOff;
        }
        if (bestValue > maxAlpha) {
            maxAlpha = bestValue;
        }
    } else {
        pathMove.from = 0;      /* no refutation table move */
        FreePath(*bestPath);
        *bestPath = NULL;
    }

    /* Try transposition table move */
    if (useTtMove && ttDepth >= 0 && !EqualMoves(&ttMove, &pathMove)) {
        if (!firstMove) {       /* Refutation move already examined */
            tempPath = NULL;
            DoMove(&ttMove);
            value = -Ab(depth - 1, -maxAlpha - 1, -maxAlpha, &tempPath);
            if (value > bestValue && !stopSearching) {  /* fail high */
                betterMoveFound = true;
                FreePath((*bestPath)->next);
                (*bestPath)->next = tempPath;
                if (value < beta && depth > 0) {        /* re-search */
                    bestValue = -Ab(depth - 1, -Infinity, -value, &((*bestPath)->next));
                } else {
                    bestValue = value;
                }
            } else {
                betterMoveFound = false;
            }
            UndoMove();
            if (betterMoveFound) {
                SPrintMove((*bestPath)->moveString, ttMove);
                (*bestPath)->move = ttMove;
                bestMove = ttMove;
                if (bestValue >= beta) {
                    goto BetaCutOff;
                }
                if (bestValue > maxAlpha) {
                    maxAlpha = bestValue;
                }
            } else {
                FreePath(tempPath);
            }
            if (stopSearching) {
                return (-Infinity);
            }
        } else {                /* No refutation move, so *bestPath equals
                                 * NULL */
            firstMove = false;
            AllocatePathMove(*bestPath);
            DoMove(&ttMove);
            bestValue = -Ab(depth - 1, -beta, -maxAlpha, &((*bestPath)->next));
            UndoMove();
            bestMove = ttMove;
            SPrintMove((*bestPath)->moveString, ttMove);
            (*bestPath)->move = ttMove;
            if (stopSearching) {
                return (-Infinity);
            }
            if (bestValue >= beta) {
                goto BetaCutOff;
            }
            if (bestValue > maxAlpha) {
                maxAlpha = bestValue;
            }
        }
    } else {
        ttMove.from = 0;        /* no transposition table move */
    }

    /* Rest of the moves */
    GenerateMoves(&moveList, &nrMoves);
    if (nrMoves == 0) {
        ++nrLeafNodes;
        --nrInternalNodes;
        if (Attacked(kingSquare[toMove], (SquareType) ! toMove)) {
            return (-Mate + (nrGamePlies - startPly));
        } else {
            return (Draw);      /* Stalemate */
        }
    }
    /* !!! Check evasion: "*/
 
if (nrCheck) { 
    depth++;
    }



    /* Construct heap */
    for (i = nrMoves / 2 - 1; i > 0; i--) {
        SiftDown(moveList, (Unsigned1) i, (Unsigned1) (nrMoves - 1));
    }
    for (i = nrMoves - 1; i >= 0; i--) {
        if (i != 0) {           /* Put best move above in list */
            SiftDown(moveList, (Unsigned1) 0, (Unsigned1) i);
        }
        /* Refutation or transposition table move already examined */
        if (EqualMoves(&(moveList[0]), &pathMove) ||
            EqualMoves(&(moveList[0]), &ttMove)) {
            goto Next;
        }
        betterMoveFound = false;
        DoMove(&(moveList[0]));
        if (firstMove) {
            AllocatePathMove(*bestPath);
            bestValue = -Ab(depth - 1, -beta, -maxAlpha, &((*bestPath)->next));
            betterMoveFound = true;
            firstMove = false;
        } else {                /* Not the first move */
            tempPath = NULL;
            value = -Ab(depth - 1, -maxAlpha - 1, -maxAlpha, &tempPath);
            if (value > bestValue && !stopSearching) {  /* fail high */
                FreePath((*bestPath)->next);
                (*bestPath)->next = tempPath;
                betterMoveFound = true;
                if (value < beta && depth > 0) {        /* re-search */
                    bestValue = -Ab(depth - 1, -Infinity, -value, &((*bestPath)->next));
                } else {
                    bestValue = value;
                }
            }
        }
        UndoMove();

        if (stopSearching) {
            FreeMoveList(moveList);
            FreePath(tempPath);
            return (-Infinity);
        }
        if (betterMoveFound) {
            SPrintMove((*bestPath)->moveString, moveList[0]);
            (*bestPath)->move = moveList[0];
            bestMove = moveList[0];
            if (bestValue >= beta) {
                goto BetaCutOff;
            }
            if (bestValue > maxAlpha) {
                maxAlpha = bestValue;
            }
        } else {
            /* Druk variant af als diep genoeg en zo */
            FreePath(tempPath);
        }
Next:
        if (i != 0) {
            moveList[0] = moveList[i];
        }
    }                           /* for moves */

BetaCutOff:
    if (nrMoves) {
        FreeMoveList(moveList);
    }
    if (!IsCaptureMove(bestMove.type)) {
        historyTable[toMove][bestMove.from][bestMove.to] += 1 << depth;
    }
    if (bestValue <= alpha) {
        flag = UpperBound;
    } else if (bestValue >= beta) {
        flag = LowerBound;
    } else {
        flag = Valid;
    }
    PutMoveInTransTable(bestMove, depth, bestValue, flag,
                        nrTotalNodes - startNodes);
    if (nrGamePlies - startPly <= debugDepth) {
        char            sss[10];
        SPrintMove(sss, bestMove);
        printf("To table: %s (val:%d, depth:%d, flag:%d)\n",
               sss, bestValue, depth, flag);
    }
    return (bestValue);
}                               /* Ab */


/*----------------------------------------------------------------------
 | FreePath							940506
 |
 | Frees a move path.
 +----------------------------------------------------------------------*/
void            FreePath(PathType * path)
{
    if (path == NULL) {
        return;
    }
    FreePath(path->next);
    free(path);
    nrAllocPathMoves--;
}                               /* FreePath */


static void     PutMoveInFront(MoveType * moveList, Unsigned1 nrMoves,
                                               MoveType * ttMove)
{
    Signed2         i,
                    j;

    for (i = 0; i < nrMoves; i++) {
        if (EqualMoves(&(moveList[i]), ttMove)) {
            for (j = i; j > 0; j--) {
                moveList[j] = moveList[j - 1];
            }
            moveList[0] = *ttMove;
            break;
        }
    }
}                               /* PutMoveInFront */


static double   PercFilled(void)
{
    return (NrFilled() * 100.0 / (useTwoLevelTable ? 1L << (nrTtBits + 1)
                                  : 1L << nrTtBits));
}                               /* PercFilled */


static          Unsigned4
                NrFilled(void)
{
    Unsigned4       i,
                    nr,
                    tot;

    nr = 0;
    tot = useTwoLevelTable ? 1L << (nrTtBits + 1) : 1L << nrTtBits;
    for (i = 0; i < tot; i++) {
        if (GetFlag(&(transTable[i])) != NoEntry) {
            ++nr;
        }
    }
    return (nr);
}                               /* PercFilled */


static          Unsigned4
                ExpectedCollisions(Unsigned4 nodes)
{
    Unsigned4       tot;

    tot = useTwoLevelTable ? 1L << (nrTtBits + 1) : 1L << nrTtBits;
    return ((Unsigned4) (nodes - tot * (1 - exp((double) -1 * nodes / tot))));
}                               /* ExpectedCollisions */






/*----------------------------------------------------------------------
 |   Edit Board							
 |
 |   Sets up board position in winboard edit mode.
 |
 |  (this code was taken from Micro-Max chess engine 
 |   by HG Muller (with permission)
 |  (http://home.hccnet.nl/h.g.muller/dwnldpage.html)
 |   and adapted to work with Alibaba - JA
 |
 +----------------------------------------------------------------------*/


static void edit_board(void) {
        int m, i;
        int color = White;
        char string[256];
        edit_mode = true;
        EmptyBoard(); 

        while(fgets(line, 256, stdin)) {
        m = line[0];
        if(m=='.') break;
        if(m=='#') {
        for(i=0; i<128; i++);
        continue;
        }
        if(m=='c') {
        color = White+Black - color;
        continue;
        }
        if((m=='P' || m=='N' || m=='B' ||
        m=='R' || m=='Q' || m=='K')
        && line[1] >= 'a' && line[1] <= 'h'
        && line[2] >= '1' && line[2] <= '8') {
                                
        switch(line[0])
        {
        case 'P':
        if(color==White) {
        string[0] = 'W';
        string[1] = 'P';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);
        }else{
        string[0] = 'B';
        string[1] = 'P';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);
        }
        break;
        case 'N':
        if(color==White) {
        string[0] = 'W';
        string[1] = 'N';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);
        }else{
        string[0] = 'B';
        string[1] = 'N';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);  
        }    
        break;
        case 'B':
        if(color==White){
        string[0] = 'W';
        string[1] = 'B';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);                                        
        }else{
        string[0] = 'B';
        string[1] = 'B';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string); 
        }                              
        break;
        case 'R':
        if(color==White) {
        string[0] = 'W';
        string[1] = 'R';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);                                              
        }else{
        string[0] = 'B';
        string[1] = 'R';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);   
        }
        break;
        case 'Q':
        if(color==White) {
        string[0] = 'W';
        string[1] = 'Q';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);   
        }else{
        string[0] = 'B';
        string[1] = 'Q';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);
        }
        break;
        case 'K':
        if(color==White) {
        string[0] = 'W';
        string[1] = 'K';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);   
        }else{
        string[0] = 'B';
        string[1] = 'K';
        string[2] = line[1];
        string[3] = line[2];
        PerformPlacePiece(string);      
        }
        break;
        }
        continue;
        }
        }
        }



/*----------------------------------------------------------------------
 | COMMAND							940426
 |
 | Contains all command interpreting functions.
 +----------------------------------------------------------------------*/

static void     PerformHelpCommand(void);
static void     PerformForwardCommand(char *numberString);
static void     PerformBackCommand(char *numberString);
static void     PerformRemovePiece(char *squareString);


/*----------------------------------------------------------------------
 | InterpretCommand						940426
 |
 | Interprets the command string and acts accordingly.
 +----------------------------------------------------------------------*/
Signed2
InterpretCommand()
{

     MoveType        move;
     char         msg[356];
     force_mode = true;
    
     

	for (;;) {


		if (computer == toMove && !force_mode) {
                     
                     
                     
        if (!ENDGAME_REACHED) {
          
       if (material[White] <= EndgameMaterial ||
            material[Black] <= EndgameMaterial) {
                            
           
			printf("_______________________________________\n");
            printf("\n[aliBaba] endgame reached\n");
			printf("[alibaba] activating endgame evaluation\n");
			printf("_______________________________________\n");
			ENDGAME_REACHED = true;
        

}}
   
      if (move_count > 0) PieceCount();
      
                  
      
        
        Search((Signed1) maxdepth, &move, &value);
		
        
       
     
		if (move.from) {
            
             ////////////// resign ////////////////
        if (using_resign) {
		if (value < -Resign_value && resign_counter < count_resign) {			
		printf("[alibaba] score is %d | concede score is -%d\n",value,Resign_value);
		if (icc) printf("tellics whisper [alibaba] score is %d | concede score is -%d\n",value,Resign_value);
        resign_counter++;
		}else{
        resign_counter = 0;
		}	
		if (resign_counter == 3) {
			printf("resign\n");
		if (icc) printf("tellics say I resign\n");
        computer  = Empty;
        force_mode = true;
		break;
		}}
		///////////////////////////////////////


        //////// draw (insufficiant_material) /////////////
        
        if (insufficiant_material) {
          printf("[Alibaba] claiming draw (insufficiant material)\n");
          printf("game is a draw\n");
          computer  = Empty;
          force_mode = true;
		  break;
       }
                                  
       
         ////////// draw offer /////////////
       if (using_draw_offer) {
       if (move_count >= 120*2 &&  // offer draw from move 120 onwards, 
                                 // only if score is neutral or in deficit 
	   value <= 0 && !draw_offer || draw_offer) {
       printf("\noffer draw\n");
       if (icc) printf("tellics say offer draw\n");
       draw_offer = true; 
       }else{
       draw_offer = false;
       } 
       if (draw_offer && move_count == 150*2 || move_count == 160*2
	   || move_count == 170*2 || move_count == 180*2 || move_count == 190*2) {
       draw_offer = false;
       }}
       /////////////////////////////////
            
            
            SPrintMove(wb_command, move);
            printf("move %s\n", wb_command);
            if (icc) printf("tellics whisper kibitz %s\n", wb_command);
			move_count++;
		//	printf("[alibaba] move no. %d\n",move_count);
		    
               
            DoMove(&move);
        }
		
		if (print_board) PrintBoard();  
        continue;
	    }	 				

	if (!fgets(line, 256, stdin)) {
        return 1;
		}

		if (line[0] == '\n') {
		continue;
		}
                      

  if (!xboard_mode)  printf("\n> ");
  
       sscanf(line, "%s", wb_command); 
  		

if (!analyze_on) {
if (!strcmp(wb_command, "quit") || !strcmp(wb_command, "exit")) {         
	 printf("\nalibaba terminating!\n");  
	 if (icc) printf("tellics say alibaba terminating!\n");
 
  #ifndef _MSC_VER
   exit(0);
  #else
   ExitProcess(0);  // use this windows call on final windows compile 
  //exit(0);
  #endif           // to make sure process is terminated fully on exit 
}}


 if (analyze_on) {
 if (!strcmp(wb_command,"exit")) {
     analyze_on = false;      
     continue;                   
 }} 


if (!strcmp(wb_command, "go")) { 
	
    if (!new_used) {
    Init();
    computer = Black;
    new_used = true;
    }
    computer = toMove;
	force_mode = false;
	
}       


if (!strcmp(wb_command, "sd")) { 
    int sd;
    sscanf(line,"sd %d",&sd);
    maxdepth = (Signed1) sd;
    maxtime = 1 << 25;
    printf("\ndepth set to %d\n",sd);
    continue;	
}           
       
if (!strcmp(wb_command, "protover")) { 
    printf("feature colors=1\n");
    printf("feature myname=\"AliBaba %s by D.Breuker\"\n",VERSION);
    printf("feature time=1\n");
    printf("feature pause=0\n");
    printf("feature sigint=0\n");
    printf("feature sigterm=0\n");
    printf("feature reuse=0\n");
	printf("feature draw=1\n");
	printf("feature random=0\n");
    printf("feature variants=\"normal\"\n");
	printf("feature setboard=0\n");
	printf("feature ping=1\n");
	printf("feature ics=1\n");
	printf("feature memory=1\n");
	printf("feature name=1\n");
    printf("feature analyze=1\n");
    printf("feature done=1\n");
    continue;
}                
  
  
  
if (!strcmp(wb_command,"variant")) {
	 char variant[100];
     scanf("%s",variant);
     if (strcmp(variant,"normal")) {
     printf("Error (unsupported variant):%s\n",variant);
     }
     continue;
     }    
      

if (!strcmp(wb_command, "memory")) {
      
	 if (memory_on) {
     sscanf(line, "memory %d", &memory);
	 
   /* <hashsize> is an integer, denoting the number of bits of the
      hash index. The size of the hash table is 2^<number of bits> positions.
     . EXAMPLE: memory 16
      uses a transposition table with 65536 (2^16) positions. */

	 /* set hash size */
	 
	 if (memory == 3)   hashsize = 16;           /* 3mb   */
	 else
	 if (memory == 6)   hashsize = 17;           /* 6mb   */
	 else
	 if (memory == 17)  hashsize = 18;           /* 12mb  */ 
	 else
     if (memory == 22)  hashsize = 20;           /* 22mb */
	 else
	 if (memory == 32)  hashsize = 19;           /* 32mb  */ 
	 else
	 if (memory == 84)  hashsize = 22;           /* 82mb */
	 else
	 if (memory == 164) hashsize = 23;           /* 164 mb */
	 else
     
	 /* if hash size chosen is not one of above, set to a
	    suitable hash size that is in range. */
	 
	 if (memory < 5)    hashsize = 16;           /* 3mb  */
	 else
     if (memory < 10)   hashsize = 17;           /* 6mb  */
	 else
     if (memory < 17)   hashsize = 18;           /* 12mb  */ 
     else
     if (memory < 26)   hashsize = 20;           /* 22mb */          
     else
     if (memory < 50)   hashsize = 19;           /* 32mb */                    
	 else
     if (memory < 100)  hashsize = 22;           /* 82mb */
     else
     if (memory < 200)  hashsize = 23;           /* 164mb */
     	 
	 nrTtBits = hashsize; 
     }
     continue;
}


     
     
if (!strcmp(wb_command, "ics")) { // are we on an internet chess server?
			if(line[4] == '-') {
				icc = false;
			} else {
				icc = true;
			}
			continue;
		}
		    
    
if (!strcmp(wb_command, "told")) {
			// told via "tell" msg or left a msg via "message"
			strcpy(msg, (line+5));
			printf("tellics kibitz %s\n",msg);
			printf("tellics draw\n");			
		 continue;
        }
		
	
if (!strcmp(wb_command, "whispered")) {
			// whispered to via "whisper"
        continue;
}
		
 if (!strcmp(wb_command, "heardkibitz")) {
			// picked up a kibitz
        continue;
}
		
if (!strcmp(wb_command, "heardshout")) {
        continue;
}
		
if (!strcmp(wb_command, "heardsshout")) {
        continue;
}    

                        
if (!strcmp(wb_command,"rating")) {
		int my_rating,opp_rating;
		scanf("%d",&my_rating);
		scanf("%d",&opp_rating);
		continue;
	}            
           
           
if (!strcmp(wb_command, "new")) { 
    new_used = true;
    Init();
    force_mode = false;
    computer = Black;
    move_count = 0;
    if (icc) printf("tellics say Thanks for playing me!\n");
	continue;
}                
	
	
if (!strcmp(wb_command, "edit")) {
  
     edit_board();
     continue;
		}	
	
	
if (!strcmp(wb_command, "white")) { 
	 if (using_bookthinker || edit_mode) {
     computer = White; 
     }else{
     computer = Black;
     }  
     continue;		
}    
	
if (!strcmp(wb_command, "black")) { 
	if (using_bookthinker || edit_mode) {
    computer = Black;
    }else{
    computer = White;
    }
     continue;	
}   

if (!move_count) {
if (!strcmp(wb_command, "a2a3")) {   // for switching black to move in analyze mode.
	analyze_black = true;            // this is needed when using 'edit' instead of
    continue;	                     // 'setboard' to set up position. - JA
}} 



if (!strcmp(wb_command, "force")) { 
    computer  = Empty;
	force_mode = true;
	continue;		
}    

if (!strcmp(wb_command, "draw")) {
    if (draw_offer || value <= -300) {    // if alibaba already has a 'draw offer' pending
		   printf("\noffer draw\n"); // or best score is low, accept the draw 
		   if (icc) printf("tellics say offer draw\n");
		   continue;
	}else{
  
           printf("\ndraw offer declined!\n");
           printf("AliBaba is still optimistic about it's chances\n");
           printf ("to win!\n"); 
           
 	      if (icc) {
          printf("tellics say draw offer declined!\n");	
          printf("tellics say still optimistic about my chances\n");
          }
}
continue;
}


if (!strcmp(wb_command, "result")) {
     char result[256];
     sscanf(line,"result %s",result);
     computer = Empty;
     force_mode = true;
     continue;
}

if (!strcmp(wb_command, "st")) {
	 st_time = true;
     sscanf(line, "st %d", &maxtime);
     maxtime *= 1000;
     continue;
}


if (!strcmp(wb_command, "undo")) {
	 char undo[256];
     sscanf(line, "undo %s", undo);
     PerformBackCommand(undo);
	 continue;
}


if (!strcmp(wb_command, "ping")) {
	 int n; 
     sscanf(line,"%*s %d",&n);
     printf("pong %d\n",n); 
	 continue;
}

if (!strcmp(wb_command, "name")) { 
     char name[265];
     sscanf(line,"name %s",name);
     printf("opponent's name is %s\n",name);
     if (icc) printf("tellics say Alibaba is playing %s\n",name);
	 continue;
}


if (!strcmp(wb_command, "analyze")) {
                       maxtime = INFINITE;
                       analyze_on = true;
                       maxdepth = 80;           
                       force_mode = true;  
                       if (analyze_black) toMove = Black;
                       PieceCount();
                       InitPieceValues();
                       UpdatePieceTables();
                       Search((Signed1) maxdepth, &move, &value);                        
                       continue;
                       }    		 
                                     		       

if (!strcmp(wb_command, "time")) {       
     sscanf(line, "time %d", &maxtime); 
     time_left_computer = maxtime;
     time_left_computer *= 10;
     time_left_computer /= 60; 
     if (time_left_computer > time_left_opponent) {
     add_time = (time_left_computer - time_left_opponent);
     add_time /=180;
     }else{
     add_time = 0;
     }
     if (move_count < max_moves)   
     timeadd = (max_moves*2) + (add_time) - move_count;                          
     else
     if (move_count == (max_moves)) MAX_TIME +=10; 
     maxtime *= (MAX_TIME + timeadd +add_time);  
     maxtime /= 600; 
     continue;
     }
  

if (!strcmp(wb_command, "level")) { 
    sscanf(line, "level %d %d", &max_moves,&minutes);
    if (!max_moves) max_moves = 40;
    continue;
}  


if (!strcmp(wb_command, "easy")) { 
    continue;
}  

if (!strcmp(wb_command, "hard")) { 
    continue;
}       

if (!strcmp(wb_command, "accepted")) { 
    continue;
}       

if (!strcmp(wb_command, "?")) { 
    Stop_Search = true;
	continue;
}    

if (!strcmp(wb_command, "computer")) { 
    continue;
}       
 
if (!strcmp(wb_command, "otim")) { 
    scanf("%d",&time_left_opponent);
	time_left_opponent *= 10;
    time_left_opponent /= 60;
	continue;
}       

if (!strcmp(wb_command, "post")) {
	post = true;
	continue;
}

if (!strcmp(wb_command, "nopost")) {
	post = false;		
	continue;
}


if (!strcmp(wb_command, "rejected")) {
	continue;
}


if (!strcmp(wb_command, "accepted")) {
	continue;
}

if (!strcmp(wb_command, "random")) {
	continue;
}

if (!strcmp(wb_command, "xboard")) { 
    xboard_mode=true;
    printf("feature done=0\n");  
    continue;
}                


if(strcspn(line, "ijklmopstuvwxyz90") < strlen(line)){
	if (move_count && strcmp(wb_command,"go") && 
                      strcmp(wb_command,"rejected")) {
     printf("Error (unknown command): %s\n", wb_command);
     }
	continue;
}



/* At this point, the command better be a move  */

   PerformMoveCommand(wb_command);	
   continue;
        
}

return 1;
}


	

/*----------------------------------------------------------------------
 | MAIN							940420
 |
 | Contains the main program.
 +----------------------------------------------------------------------*/



void Start(void)
{
	    printf("\nAliBaba chess engine v%s\n",VERSION);
		printf("------------------------------\n");
        printf("\n%s, (c) D.M. Breuker\n", version);
		printf("Winboard support by Jim Ablett [%s]\n",BUILDDATE);
   
  
}


/*----------------------------------------------------------------------
 | Main program							940420
 +----------------------------------------------------------------------*/

int             CDECL
                main(int argc, char *argv[])
{
    
	int i;
    computer = Black;
    
    setbuf(stdout, NULL);
    setbuf(stdin, NULL);
    setvbuf(stdout, NULL, _IONBF, 0);
    setvbuf(stdin, NULL, _IONBF, 0);   
    

	signal(SIGINT, catch_sigint);
	

         /* set hash with command-line option */
    	 
         for (i = 1; i < argc; i++) {
             
         if (strcmp(argv[i], "-hash-3") == 0) {
            hashsize = 16;   /* 3mb */
            nrTtBits = hashsize;   
            memory_on = false;
            i++;
        }else
         if (strcmp(argv[i], "-hash-6") == 0) {
            hashsize = 17;   /* 6mb */
            nrTtBits = hashsize;   
            memory_on = false;
            i++;
         }else   
         if (strcmp(argv[i], "-hash-12") == 0) {
            hashsize = 18;  /* 12mb */
            nrTtBits = hashsize;   
            memory_on = false;
            i++;   
          }else   
         if (strcmp(argv[i], "-hash-22") == 0) {
            hashsize = 20;  /* 22mb */
            nrTtBits = hashsize;   
            memory_on = false;
            i++;     
           }else   
         if (strcmp(argv[i], "-hash-32") == 0) {
            hashsize = 19;  /* 32mb */
            nrTtBits = hashsize;   
            memory_on = false;
            i++;    
          }else   
         if (strcmp(argv[i], "-hash-82") == 0) {
            hashsize = 22;  /* 82mb */
            nrTtBits = hashsize;   
            memory_on = false;
            i++;     
           }else   
         if (strcmp(argv[i], "-hash-164") == 0) {
            hashsize = 23;  /* 164mb */
            nrTtBits = hashsize;   
            memory_on = false;
            i++;   
           }
           
           }
           
           
    
    Start();
    
    for (;;) {
    
	printf("\n--------\n");
	printf("\nThis version of AliBaba is Winboard only!.\n");
	printf("\nIt must be loaded into a Winboard compatible\n");
	printf("\nchess gui interface.\n\n");
	printf("Type 'quit' or 'exit' to terminate\n\n");
			
	printf("\n> ");
        
           
            InterpretCommand();
                break;
            }
        
 
    PrintAllocVariables();

    

}          /* main */



/*----------------------------------------------------------------------
 | PerformMoveCommand						940426
 |
 | Performs the "move" command.
 +----------------------------------------------------------------------*/
void            PerformMoveCommand(char *moveString)
{
    MoveType       *moveList;
    Unsigned1       nrMoves;
    Signed2         i;
	Signed2          n;
    char            s[MaxCommandLength],
                   *ptr;


    if (moveString[0] == '\0') {
    if (!first_move) {
		printf("Error: (move required)\n");
		}else{
		first_move = false;
		}
        return;
	    }

	
	if (!force_mode) {

	for (n=0; n < MaxCommandLength; n++) {
		if (moveString[n] == '-') goto start;
	}}	

	if (computer == toMove) {
         if (!strcmp(wb_command, "e8g8") || !strcmp(wb_command, "e1g1")) {
                    moveString[0] = '0';
                    moveString[1] = '-';
					moveString[2] = '0';
					moveString[3] = '\0';
	                goto start;
		 }
	
    if (!strcmp(wb_command, "e8c8") || !strcmp(wb_command, "e1c1")) {
                    moveString[0] = '0';
                    moveString[1] = '-';
					moveString[2] = '0';
					moveString[3] = '-';
					moveString[4] = '0';
					moveString[5] = '\0';
                    goto start;
}



// fix underpromotion bug - JA
                  
          if (moveString[4] == 'q' || moveString[4] == 'Q' ||
              moveString[4] == 'r' || moveString[4] == 'R' ||
              moveString[4] == 'n' || moveString[4] == 'N' ||
              moveString[4] == 'b' || moveString[4] == 'B') {                            
              
          moveString[6] = '\0';        
          moveString[5] = moveString[4];
          moveString[4] = moveString[3];
          moveString[3] = moveString[2];
          moveString[2] = '-';              

 goto start;

}}

					
					moveString[5] = '\0';
                    moveString[4] = moveString[3];
					moveString[3] = moveString[2];
					moveString[2] = '-';
				 
	
start:

    GenerateMoves(&moveList, &nrMoves);
    for (i = 0; i < nrMoves; i++) {
        SPrintMove(s, moveList[i]);
        for (ptr = s; *ptr == ' '; ptr++);
        if (strncmp(ptr, moveString, strlen(moveString)) == 0) {
            DoMove(&(moveList[i]));
            move_count++;
            break;
        }
    }
    if (nrMoves) {
        FreeMoveList(moveList);
    }
    if (i == nrMoves) {
		
        // fix castling bug - JA
        if (strcmp(wb_command, "e8c8")  || strcmp(wb_command, "e1c1") ||
             strcmp(wb_command, "e8g8") || strcmp(wb_command, "e1g1")) {
        
        printf("Error (ambiguous move): %s\n", moveString);
        }
   }
}                               /* PerformMoveCommand */


/*----------------------------------------------------------------------
 | PerformForwardCommand					940429
 |
 | Executes several moves.
 +----------------------------------------------------------------------*/
static void     PerformForwardCommand(char *numberString)
{
    Signed2         i,
                    nrForward;
    int             dummy;

    if (nrGamePlies >= maxGamePlies) {
        printf("Error: (no more moves)\n");
    } else {
        if (numberString[0] == '\0') {
            nrForward = 1;
        } else {
            sscanf(numberString, "%d", &dummy);
            nrForward = (Signed2) dummy;
        }
        if (nrForward > maxGamePlies - nrGamePlies) {
            nrForward = maxGamePlies - nrGamePlies;
        }
        for (i = 0; i < nrForward; i++) {
            if ((toMove == White && nrGamePlies % 2 == 0) ||
                (toMove == Black && nrGamePlies % 2 == 1)) {
                printf("Doing move %d.", nrGamePlies / 2 + 1);
                if (nrGamePlies % 2 == 1) {
                    printf("..");
                }
            } else {
                printf("Doing move %d.", (nrGamePlies + 1) / 2 + 1);
                if ((nrGamePlies + 1) % 2 == 1) {
                    printf("..");
                }
            }
            printf("%s\n", gameString[nrGamePlies]);
            DoMove(&(game[nrGamePlies]));
        }
    }
}                               /* PerformForwardCommand */


/*----------------------------------------------------------------------
 | PerformBackCommand						940429
 |
 | Takes several moves back.
 +----------------------------------------------------------------------*/
static void     PerformBackCommand(char *numberString)
{
    Signed2         nrBack,
                    i;
    int             dummy;

    if (nrGamePlies == 0) {
        printf("ERROR: no moves to take back\n");
    } else {
        if (numberString[0] == '\0') {
            nrBack = 1;
        } else {
            sscanf(numberString, "%d", &dummy);
            nrBack = (Signed2) dummy;
        }
        if (nrBack > nrGamePlies) {
            nrBack = nrGamePlies;
        }
        for (i = 0; i < nrBack; i++) {
            if ((toMove == White && nrGamePlies % 2 == 0) ||
                (toMove == Black && nrGamePlies % 2 == 1)) {
                printf("Undoing move %d.", (nrGamePlies - 1) / 2 + 1);
                if ((nrGamePlies - 1) % 2 == 1) {
                    printf("..");
                }
            } else {
                printf("Undoing move %d.", nrGamePlies / 2 + 1);
                if (nrGamePlies % 2 == 1) {
                    printf("..");
                }
            }
            printf("%s\n", gameString[nrGamePlies - 1]);
            UndoMove();
        }
    }
}                               /* PerformBackCommand */


/*----------------------------------------------------------------------
 | PerformPlacePiece						940429
 |
 | Places a piece on the board.
 +----------------------------------------------------------------------*/
void            PerformPlacePiece(char *pieceString)
{
    SquareType      piece;
    BoardIndexType  square;
    char           *ptr;

    if (tolower(pieceString[0]) == 'w') {
        piece = White;
    } else if (tolower(pieceString[0]) == 'b') {
        piece = Black;
    } else {
        printf("ERROR: Unknown color in piece '%s'\n", pieceString);
        return;
    }
    if (strlen(pieceString) == 3) {
        ptr = &(pieceString[1]);
        piece |= Pawn;
    } else {
        ptr = &(pieceString[2]);
        switch (tolower(pieceString[1])) {
        case 'k':
            piece |= King;
            break;
        case 'q':
            piece |= Queen;
            break;
        case 'r':
            piece |= Rook;
            break;
        case 'b':
            piece |= Bishop;
            break;
        case 'n':
            piece |= Knight;
            break;
        case 'p':
            piece |= Pawn;
            break;
        default:
            printf("ERROR: unknown piece in piece '%s'\n", pieceString);
            return;
        }                       /* switch */
    }
    square = Square(tolower(ptr[0]) - 'a' + A, ptr[1] - '0');
    if (Rank(square) < 1 || Rank(square) > 8 ||
        File(square) < A || File(square) > H ||
        !IsEmpty(board[square])) {
        printf("ERROR: wrong square in piece '%s'\n", pieceString);
        return;
    }
    PlacePiece(piece, square);
}                               /* PerformPlacePiece */


/*----------------------------------------------------------------------
 | PerformRemovePiece						940429
 |
 | Removes a piece from a square.
 +----------------------------------------------------------------------*/
static void     PerformRemovePiece(char *squareString)
{
    BoardIndexType  square;
    SquareType      color;
    HashType       *table;

    square = Square(tolower(squareString[0]) - 'a' + A,
                    squareString[1] - '0');
    if (IsEmpty(board[square]) || IsEdge(board[square])) {
        printf("ERROR: wrong square '%s'\n", squareString);
        return;
    }
    color = Color(board[square]);
    material[color] -= pieceValue[board[square]];
    pieces[color][pieceIndex[square]] =
        pieces[color][--nrPieces[color]];
    pieceIndex[pieces[color][pieceIndex[square]].square] =
        pieceIndex[square];
    GetHashTable(table, color, board[square]);
    HashXorIs(hashValue[nrGamePlies], table[square]);
    board[square] = Empty;
}                               /* PerformRemovePiece */



/*----------------------------------------------------------------------
 | EVALUATE 							940502
 |
 | Contains position evaluation functions.
 +----------------------------------------------------------------------*/


static Boolean  NoMoves(void);
static Boolean  PawnCanMove(BoardIndexType square);
static Boolean  KnightCanMove(BoardIndexType square);
static Boolean  BishopCanMove(BoardIndexType square);
static Boolean  RookCanMove(BoardIndexType square);
static Boolean  KingCanMove(BoardIndexType square);
static Boolean  CaptureMovesAvailable(CheckPieceType * piece);
static Boolean  PawnCaptureMovesAvailable(CheckPieceType * piece);
static Boolean  KnightCaptureMovesAvailable(CheckPieceType * piece);
static Boolean  BishopCaptureMovesAvailable(CheckPieceType * piece);
static Boolean  RookCaptureMovesAvailable(CheckPieceType * piece);
static Boolean  InterposingMovesAvailable(CheckPieceType * piece);
static Boolean  ToMovesAvailable(BoardIndexType to);
static Boolean  PawnToMovesAvailable(BoardIndexType to);
static Boolean  KnightToMovesAvailable(BoardIndexType to);
static Boolean  BishopToMovesAvailable(BoardIndexType to);
static Boolean  RookToMovesAvailable(BoardIndexType to);


/*----------------------------------------------------------------------
 | Evaluate							940502
 |
 | Evaluates a position. 'toMove' is the person who is to move.
 +----------------------------------------------------------------------*/
ValueType
Evaluate(Signed1 ttDepth, ValueType ttValue, Unsigned1 flag,
         Unsigned4 ttNodes)
{
    ValueType       value,
                    readValue;
    MoveType        readMove;
    Unsigned1       readFlag;
    Signed1         readDepth;
    Unsigned4       readNodes;

   
    if (ttDepth == -2) {
        GetMoveFromTransTable(readMove, readDepth, readValue, readFlag,
                              readNodes);
    } else {
        readDepth = ttDepth;
        readValue = ttValue;
        readFlag = flag;
        readNodes = ttNodes;
    }
    if (NoMoves()) {
        return (nrCheck ? -Mate + (nrGamePlies - startPly) : Draw);
    }
    if (nrCheck) {
        return (-Infinity);
    }
    value = material[toMove] + positionalValue[toMove] -
        material[!toMove] - positionalValue[!toMove];

	
    if (useTtValue && readDepth != -1) {
        if (keepMethod == BigAll) {
            nrExtraNodes += readNodes;
            nrTotalNodes += readNodes;
        }
        if ((readFlag == UpperBound && value > readValue) ||
            (readFlag == LowerBound && value < readValue) ||
            readFlag == Valid) {
            value = readValue;
        }
    }
    eval_score = value;
    return (value);
}                               /* Evaluate */


/*----------------------------------------------------------------------
 | NoMoves.							940509
 |
 | Returns 'true' if no moves are available for color 'toMove'. Otherwise
 | 'false' is returned;
 +----------------------------------------------------------------------*/


static          Boolean
                NoMoves(void)
{
    PieceType      *pieceTable;
    Unsigned1       nr;
    SquareType      piece;
    Signed2         i;

    pieceTable = pieces[toMove];
    nr = nrPieces[toMove];

    SearchForPinsAndCheck();
    switch (nrCheck) {
    case 0:
        for (i = 0; i < nr; i++) {
            piece = pieceTable[i].type;
            if (IsPawn(piece) && PawnCanMove(pieceTable[i].square)) {
               return (false);
            } else if (IsKnight(piece) && !pinned[pieceTable[i].square] &&
                       KnightCanMove(pieceTable[i].square)) {
                return (false);
            } else if (IsKing(piece) && KingCanMove(pieceTable[i].square)) {
                return (false);
            } else {
                if (MovesDiagonal(piece) &&
                    BishopCanMove(pieceTable[i].square)) {
                    return (false);
                }
                if (MovesStraight(piece) &&
                    RookCanMove(pieceTable[i].square)) {
                    return (false);
                }
            }
        }                       /* for i */
        break;
    case 1:
        /* Capture check-giving piece, NOT with king */
        if (CaptureMovesAvailable(&(checkingPiece[0]))) {
            return (false);
        }
        /* Interpose piece */
        if (checkingPiece[0].dir &&
            kingSquare[toMove] + checkingPiece[0].dir !=
            checkingPiece[0].square &&
            InterposingMovesAvailable(&(checkingPiece[0]))) {
         
            return (false);
        }
    case 2:
        /* Move king away, including trying to capture (one of) the
         * check-giving piece(s) */
        if (KingCanMove(kingSquare[toMove])) {                            
            return (false);
        }
        break;
    default:
        printf("Error (times in check): %d\n", nrCheck);
       // exit(0);
       return (true);
    }                           /* switch */
    
    return (true);
}                               /* NoMoves */




/*----------------------------------------------------------------------
 | GeneratePawnMoves						940420
 |
 | Generates all legal pawn moves.
 +----------------------------------------------------------------------*/
static          Boolean
                PawnCanMove(BoardIndexType from)
{
    BoardIndexType  to;
    SquareType      piece;
    Unsigned1       dir;
    PieceType       attackingPiece;

    /* non-capture moves */
    if (!pinned[from] || pinned[from] == Up || pinned[from] == Down) {
        to = pawnMoveTable[toMove][from][0];
        if (IsEmpty(board[to])) {
            return (true);
        }
    }                           /* if not pinned */
    /* capture moves */
    for (dir = 0; dir < 2; dir++) {
        if (!pinned[from] || pinned[from] == pawnCaptureDir[toMove][dir] ||
            pinned[from] == -pawnCaptureDir[toMove][dir]) {
            to = pawnCaptureTable[toMove][from][dir];
            if (to == epSquare[nrGamePlies]) {
                /* remove pawns temporarily */
                board[from] = Empty;
                board[to + (toMove == White ? Down : Up)] = Empty;
                if (FindFirstPieceInDir((Unsigned1) MaxRookMoves,
                       rookTable[kingSquare[toMove]][2], &attackingPiece)) {
                    if (attackingPiece.type != (Rook | !toMove) &&
                        attackingPiece.type != (Queen | !toMove)) {
                        if (FindFirstPieceInDir((Unsigned1) MaxRookMoves,
                        rookTable[kingSquare[toMove]][3], &attackingPiece)) {
                            if (attackingPiece.type != (Rook | !toMove) &&
                                attackingPiece.type != (Queen | !toMove)) {
                                /* Put pawns back */
                                board[from] = Pawn | toMove;
                                board[to + (toMove == White ? Down : Up)] = Pawn | !toMove;
                                return (true);
                            }
                        }
                    }
                }
                /* Put pawns back */
                board[from] = Pawn | toMove;
                board[to + (toMove == White ? Down : Up)] = Pawn | !toMove;
            } else {
                piece = board[to];
                if (piece && !IsEdge(piece) && !IsColor(piece, toMove)) {
                    return (true);
                }               /* if enemy piece */
            }                   /* else */
        }                       /* if not pinned */
    }                           /* for dir */
    return (false);
}                               /* PawnCanMove */


/*----------------------------------------------------------------------
 | GenerateKnightMoves						940422
 |
 | Generates all legal knight moves.
 +----------------------------------------------------------------------*/
static          Boolean
                KnightCanMove(BoardIndexType from)
{
    Signed2         i;
    BoardIndexType  to;
    SquareType      piece;

    for (i = 0; i < MaxKnightMoves; i++) {
        to = knightTable[from][i];
        if (!to) {
            break;
        }
        piece = board[to];
        if (IsEmpty(piece)) {
            return (true);
        } else if (!IsEdge(piece) && !IsColor(piece, toMove)) {
            return (true);
        }
    }
    return (false);
}                               /* KnightCanMove */


/*----------------------------------------------------------------------
 | GenerateBishopMoves						940422
 |
 | Generates all legal bishop moves.
 +----------------------------------------------------------------------*/
static          Boolean
                BishopCanMove(BoardIndexType from)
{
    Signed2         i,
                    j;
    BoardIndexType  to;
    SquareType      piece;

    for (i = 0; i < 4; i++) {
        if (!pinned[from] || pinned[from] == bishopDir[i] ||
            pinned[from] == -bishopDir[i]) {
            for (j = 0; j < MaxBishopMoves; j++) {
                to = bishopTable[from][i][j];
                if (!to) {
                    break;
                }
                piece = board[to];
                if (IsEmpty(piece)) {
                    return (true);
                } else if (!IsEdge(piece) && !IsColor(piece, toMove)) {
                    return (true);
                } else {
                    break;
                }
            }                   /* for j */
        }                       /* if not pinned */
    }                           /* for i */
    return (false);
}                               /* BishopCanMove */


/*----------------------------------------------------------------------
 | GenerateRookMoves						940422
 |
 | Generates all legal rook moves.
 +----------------------------------------------------------------------*/
static          Boolean
                RookCanMove(BoardIndexType from)
{
    Signed2         i,
                    j;
    BoardIndexType  to;
    SquareType      piece;

    for (i = 0; i < 4; i++) {
        if (!pinned[from] || pinned[from] == rookDir[i] ||
            pinned[from] == -rookDir[i]) {
            for (j = 0; j < MaxRookMoves; j++) {
                to = rookTable[from][i][j];
                if (!to) {
                    break;
                }
                piece = board[to];
                if (IsEmpty(piece)) {
                    return (true);
                } else if (!IsEdge(piece) && !IsColor(piece, toMove)) {
                    return (true);
                } else {
                    break;
                }
            }                   /* for j */
        }                       /* if not pinned */
    }                           /* for i */
    return (false);
}                               /* RookCanMove */


/*----------------------------------------------------------------------
 | GenerateKingMoves						940422
 |
 | Generates all legal king moves.
 +----------------------------------------------------------------------*/
void            GenerateKingMoves(BoardIndexType from, MoveType * list,
                                                  Unsigned1 * nrMoves)
{
    Signed2         i;
    BoardIndexType  to;
    BoardIndexType  square1,
                    square2,
                    square3,
                    square4,
                    square5,
                    square6;
    SquareType      piece;
    

    /* Remove king temporarily in view of Attacked() */
    board[kingSquare[toMove]] = Empty;
    for (i = 0; i < 4; i++) {
        to = rookTable[from][i][0];
        if (!to) {
            continue;
        }
        piece = board[to];
        if (IsEmpty(piece)) {
            if (!IsCheckingDir(rookDir[i]) &&
                !IsCheckingDir(-rookDir[i]) &&
                !Attacked(to, (Unsigned1) ! toMove)) {
                PutMoveInTable(from, to, 0, 0, Normal, list, *nrMoves);
                
            }
        } else if (!IsEdge(piece) && !IsColor(piece, toMove)) {
            if (!IsCheckingDir(-rookDir[i]) &&
                !Attacked(to, (Unsigned1) ! toMove)) {
                PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
                
            }
        }
    }
    for (i = 0; i < 4; i++) {
        to = bishopTable[from][i][0];
        if (!to) {
            continue;
        }
        piece = board[to];
        if (IsEmpty(piece)) {
            if (!IsCheckingDir(bishopDir[i]) &&
                !IsCheckingDir(-bishopDir[i]) &&
                !Attacked(to, (Unsigned1) ! toMove)) {
                PutMoveInTable(from, to, 0, 0, Normal, list, *nrMoves);
                
            }
        } else if (!IsEdge(piece) && !IsColor(piece, toMove)) {
            if (!IsCheckingDir(-bishopDir[i]) &&
                !Attacked(to, (Unsigned1) ! toMove)) {
                PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
               
            }
        }
    }
    
  
    
    /* Castling */
    if (!nrCheck) {
         if (ShortCastlingPossible()) {         
                  
        if (IsWhite(toMove)) {
            square1 = E1;
            square2 = F1;
            square3 = G1;
            square4 = D1;
            square5 = C1;
            square6 = B1;
        } else {
            square1 = E8;
            square2 = F8;
            square3 = G8;
            square4 = D8;
            square5 = C8;
            square6 = B8;
        }
        
            if( IsEmpty(board[square2]) && IsEmpty(board[square3]) &&
            !Attacked(square2, (Unsigned1) ! toMove) &&
            !Attacked(square3, (Unsigned1) ! toMove)) {
            PutMoveInTable(square1, square3, 0, 0, ShortCastle, list, *nrMoves);
        }}}
        
           
        
         if (!nrCheck) {
        
        if (LongCastlingPossible()) {
                                    
         if (IsWhite(toMove)) {
            square1 = E1;
            square2 = F1;
            square3 = G1;
            square4 = D1;
            square5 = C1;
            square6 = B1;
        } else {
            square1 = E8;
            square2 = F8;
            square3 = G8;
            square4 = D8;
            square5 = C8;
            square6 = B8;
        }                       
                                    
            if (IsEmpty(board[square4]) && IsEmpty(board[square5]) &&
            IsEmpty(board[square6]) &&
            !Attacked(square4, (Unsigned1) ! toMove) &&
            !Attacked(square5, (Unsigned1) ! toMove) &&
            !Attacked(square6, (Unsigned1) ! toMove)) {
            PutMoveInTable(square1, square5, 0, 0, LongCastle, list, *nrMoves);
        }}}
                              /* if not in check */
    board[kingSquare[toMove]] = King | toMove;
}                               /* GenerateKingMoves */



/*----------------------------------------------------------------------
 | GenerateKingMoves						940422
 |
 | Generates all legal king moves.
 +----------------------------------------------------------------------*/
static          Boolean
                KingCanMove(BoardIndexType from)
{
    Signed2         i;
    BoardIndexType  to;
    BoardIndexType  square2,
                    square3,
                    square4,
                    square5,
                    square6;
    SquareType      piece;

    
    /* Remove king temporarily in view of Attacked() */
    board[kingSquare[toMove]] = Empty;
    for (i = 0; i < 4; i++) {
        to = rookTable[from][i][0];
        if (!to) {
            continue;
        }
        piece = board[to];
        if (IsEmpty(piece)) {
            if (!IsCheckingDir(rookDir[i]) &&
                !IsCheckingDir(-rookDir[i]) &&
                !Attacked(to, (SquareType) ! toMove)) {
                board[kingSquare[toMove]] = King | toMove;
                return (true);
            }
        } else if (!IsEdge(piece) && !IsColor(piece, toMove)) {
            if (!IsCheckingDir(-rookDir[i]) &&
                !Attacked(to, (SquareType) ! toMove)) {
                board[kingSquare[toMove]] = King | toMove;              
                return (true);
            }
        }
    }
    for (i = 0; i < 4; i++) {
        to = bishopTable[from][i][0];
        if (!to) {
            continue;
        }
        piece = board[to];
        if (IsEmpty(piece)) {
            if (!IsCheckingDir(bishopDir[i]) &&
                !IsCheckingDir(-bishopDir[i]) &&
                !Attacked(to, (SquareType) ! toMove)) {
                board[kingSquare[toMove]] = King | toMove;               
                return (true);
            }
        } else if (!IsEdge(piece) && !IsColor(piece, toMove)) {
            if (!IsCheckingDir(-bishopDir[i]) &&
                !Attacked(to, (SquareType) ! toMove)) {
                board[kingSquare[toMove]] = King | toMove;               
                return (true);
            
            }
        }
    }
    
     
      
     
    
    
    
    /* Castling */
    if (!nrCheck) {
        
    if (ShortCastlingPossible()) {
        
        if (IsWhite(toMove)) {
            square2 = F1;
            square3 = G1;
            square4 = D1;
            square5 = C1;
            square6 = B1;
        } else {
            square2 = F8;
            square3 = G8;
            square4 = D8;
            square5 = C8;            square6 = B8;
        }
            
            if (IsEmpty(board[square2]) && IsEmpty(board[square3]) &&
            !Attacked(square2, (SquareType) ! toMove) &&
            !Attacked(square3, (SquareType) ! toMove)) {
            board[kingSquare[toMove]] = King | toMove;
            return (true);
        }}}
        
        
        
        
         if (!nrCheck) {
        
        if (LongCastlingPossible()) {
                                    
            if (IsWhite(toMove)) {
            square2 = F1;
            square3 = G1;
            square4 = D1;
            square5 = C1;
            square6 = B1;
        } else {
            square2 = F8;
            square3 = G8;
            square4 = D8;
            square5 = C8;            square6 = B8;
        }                         
            
            
            if (IsEmpty(board[square4]) && IsEmpty(board[square5]) &&
            IsEmpty(board[square6]) &&
            !Attacked(square4, (SquareType) ! toMove) &&
            !Attacked(square5, (SquareType) ! toMove) &&
            !Attacked(square6, (SquareType) ! toMove)) {
            board[kingSquare[toMove]] = King | toMove;
            return (true);
        }
    }    }
                           /* if not in check */
    board[kingSquare[toMove]] = King | toMove;
    return (false);
}                               /* GenerateKingMoves */



/*----------------------------------------------------------------------
 | GenerateCaptureMoves						940428
 |
 | Generate moves for color 'toMove', trying to disable check by
 | capturing the check-giving piece.
 | NOTE: no king capture moves are generated because they are generated
 | later in GenerateKingMoves().
 +----------------------------------------------------------------------*/


static          Boolean
                CaptureMovesAvailable(CheckPieceType * piece)
{
    if (PawnCaptureMovesAvailable(piece)) {      
        return (true);
    }
    if (KnightCaptureMovesAvailable(piece)) {      
        return (true);
    }
    if (BishopCaptureMovesAvailable(piece)) {
        return (true);
    }
    return (RookCaptureMovesAvailable(piece));
}                               // CaptureMovesAvailable 


/*
static          Boolean
                CaptureMovesAvailable(CheckPieceType * piece)
{
    if (PawnCaptureMovesAvailable(piece)) {      
        return (true);
    }else
    if (KnightCaptureMovesAvailable(piece)) {      
        return (true);
    }else
    if (BishopCaptureMovesAvailable(piece)) {
        return (true);
    }else
    if (RookCaptureMovesAvailable(piece)) {
    return (true);
}else{
      return (false);
      }
}                               // CaptureMovesAvailable 

*/

/*----------------------------------------------------------------------
 | GeneratePawnCaptureMoves					940428
 |
 | Generate pawn moves for color 'toMove', trying to disable check by
 | capturing the check-giving piece.
 +----------------------------------------------------------------------*/
static          Boolean
                PawnCaptureMovesAvailable(CheckPieceType * piece)
{
    Signed2         dir;
    BoardIndexType  from,
                    to;

    to = piece->square;
    /* Normal capture */
    for (dir = 0; dir < 2; dir++) {
        if (pawnCaptureDir[!toMove][dir] == -piece->dir) {
            continue;
        }
        from = pawnCaptureTable[!toMove][to][dir];
        if (from && board[from] == (Pawn | toMove) && (!pinned[from] ||
                             pinned[from] == pawnCaptureDir[!toMove][dir] ||
                           pinned[from] == -pawnCaptureDir[!toMove][dir])) {
            return (true);
        }
    }                           /* for dir */

    /* En passant */
    dir = toMove == White ? Up : Down;
    if (epSquare[nrGamePlies] == to + dir) {
        from = to + Right;
        if (from && board[from] == (Pawn | toMove) && (!pinned[from] ||
             pinned[from] == dir + Right || pinned[from] == -dir - Right)) {
            return (true);
        }                       /* if not pinned */
        from = to + Left;
        if (from && board[from] == (Pawn | toMove) && (!pinned[from] ||
               pinned[from] == dir + Left || pinned[from] == -dir - Left)) {
            return (true);
        }                       /* if not pinned */
    }                           /* if */
    return (false);
}                               /* PawnCaptureMovesAvailable */


/*----------------------------------------------------------------------
 | GenerateKnightCaptureMoves					940428
 |
 | Generate knight moves for color 'toMove', trying to disable check by
 | capturing the check-giving piece.
 +----------------------------------------------------------------------*/
static          Boolean
                KnightCaptureMovesAvailable(CheckPieceType * piece)
{
    Signed2         i;
    BoardIndexType  from,
                    to;

    to = piece->square;
    for (i = 0; i < MaxKnightMoves; i++) {
        if (knightDir[i] == -piece->dir) {
            continue;
        }
        from = knightTable[to][i];
        if (!from) {
            break;
        }
        if (board[from] == (Knight | toMove) && !pinned[from]) {
            return (true);
        }
    }
    return (false);
}                               /* KnightCaptureMovesAvailable */


/*----------------------------------------------------------------------
 | GenerateBishopCaptureMoves					940428
 |
 | Generate bishop moves for color 'toMove', trying to disable check by
 | capturing the check-giving piece.
 +----------------------------------------------------------------------*/
static          Boolean
                BishopCaptureMovesAvailable(CheckPieceType * piece)
{
    Signed2         i,
                    j;
    BoardIndexType  from,
                    to;

    to = piece->square;
    for (i = 0; i < 4; i++) {
        if (bishopDir[i] == -piece->dir) {
            continue;
        }
        for (j = 0; j < MaxBishopMoves; j++) {
            from = bishopTable[to][i][j];
            if (!from) {
                break;
            }
            if (IsEmpty(board[from])) {
                continue;
            }
            if ((board[from] == (Bishop | toMove) || board[from] == (Queen | toMove)) &&
                (!pinned[from] || pinned[from] == bishopDir[i] ||
                 pinned[from] == -bishopDir[i])) {
                return (true);
            } else {
                break;
            }
        }                       /* for j */
    }                           /* for i */
    return (false);
}                               /* BishopCaptureMovesAvailable */


/*----------------------------------------------------------------------
 | GenerateRookCaptureMoves					940428
 |
 | Generate rook moves for color 'toMove', trying to disable check by
 | capturing the check-giving piece.
 +----------------------------------------------------------------------*/
static          Boolean
                RookCaptureMovesAvailable(CheckPieceType * piece)
{
    Signed2         i,
                    j;
    BoardIndexType  from,
                    to;

    to = piece->square;
    for (i = 0; i < 4; i++) {
        if (rookDir[i] == -piece->dir) {
            continue;
        }
        for (j = 0; j < MaxRookMoves; j++) {
            from = rookTable[to][i][j];
            if (!from) {
                break;
            }
            if (IsEmpty(board[from])) {
                continue;
            }
            if ((board[from] == (Rook | toMove) || board[from] == (Queen | toMove)) &&
                (!pinned[from] || pinned[from] == rookDir[i] ||
                 pinned[from] == -rookDir[i])) {
                return (true);
            } else {
                break;
            }
        }                       /* for j */
    }                           /* for i */
    return (false);
}                               /* RookCaptureMovesAvailable */


/*----------------------------------------------------------------------
 | GenerateInterposingMoves					940428
 |
 | Generate moves for color 'toMove' to disable check by interposing
 | a piece.
 +----------------------------------------------------------------------*/
static          Boolean
                InterposingMovesAvailable(CheckPieceType * piece)
{
    BoardIndexType  to;
    DirectionType   dir;

    dir = piece->dir;
    for (to = kingSquare[toMove] + dir; to != piece->square; to += dir) {
        if (ToMovesAvailable(to)) {
            return (true);
        }
    }                           /* for square */
    return (false);
}                               /* InterposingMovesAvailable */


/*----------------------------------------------------------------------
 | GenerateToMoves						940428
 |
 | Generates moves for color 'toMove' to empty square 'to'.
 | NOTE: no king moves are generated.
 +----------------------------------------------------------------------*/
static          Boolean
                ToMovesAvailable(BoardIndexType to)
{
    if (PawnToMovesAvailable(to)) {
        return (true);
    }else
    if (KnightToMovesAvailable(to)) {
        return (true);
    }else
    if (BishopToMovesAvailable(to)) {
        return (true);
    }else
    
    if (RookToMovesAvailable(to)) {
           return (true);
    }
    return (false);
}                               /* ToMovesAvailable */


/*----------------------------------------------------------------------
 | GeneratePawnToMoves						940428
 |
 | Generates pawn moves for color 'toMove' to empty square 'to'.
 +----------------------------------------------------------------------*/
static          Boolean
                PawnToMovesAvailable(BoardIndexType to)
{
    Signed2         dir;
    BoardIndexType  from;

    for (dir = 0; dir < 2; dir++) {
        from = pawnMoveTable[!toMove][to][dir];
        if (from && board[from] == (Pawn | toMove) && (!pinned[from] ||
                              pinned[from] == Up || pinned[from] == Down)) {
            return (true);
        }
    }                           /* for dir */
    return (false);
}                               /* PawnToMovesAvailable */


/*----------------------------------------------------------------------
 | GenerateKnightToMoves						940428
 |
 | Generates knight moves for color 'toMove' to empty square 'to'.
 +----------------------------------------------------------------------*/
static          Boolean
                KnightToMovesAvailable(BoardIndexType to)
{
    Signed2         i;
    BoardIndexType  from;

    for (i = 0; i < MaxKnightMoves; i++) {
        from = knightTable[to][i];
        if (!from) {
            break;
        }
        if (board[from] == (Knight | toMove) && !pinned[from]) {
            return (true);
        }
    }
    return (false);
}                               /* KnightToMovesAvailable */


/*----------------------------------------------------------------------
 | GenerateBishopToMoves					940428
 |
 | Generates bishop moves for color 'toMove' to empty square 'to'.
 +----------------------------------------------------------------------*/
static          Boolean
                BishopToMovesAvailable(BoardIndexType to)
{
    Signed2         i,
                    j;
    BoardIndexType  from;

    for (i = 0; i < 4; i++) {
        for (j = 0; j < MaxBishopMoves; j++) {
            from = bishopTable[to][i][j];
            if (!from) {
                break;
            }
            if (IsEmpty(board[from])) {
                continue;
            }
            if ((board[from] == (Bishop | toMove) || board[from] == (Queen | toMove)) &&
                (!pinned[from] || pinned[from] == bishopDir[i] ||
                 pinned[from] == -bishopDir[i])) {
                return (true);
            } else {
                break;
            }
        }                       /* for j */
    }                           /* for i */
    return (false);
}                               /* BishopToMovesAvailable */


/*----------------------------------------------------------------------
 | GenerateRookToMoves						940428
 |
 | Generates rook moves for color 'toMove' to empty square 'to'.
 +----------------------------------------------------------------------*/
static          Boolean
                RookToMovesAvailable(BoardIndexType to)
{
    Signed2         i,
                    j;
    BoardIndexType  from;

    for (i = 0; i < 4; i++) {
        for (j = 0; j < MaxRookMoves; j++) {
            from = rookTable[to][i][j];
            if (!from) {
                break;
            }
            if (IsEmpty(board[from])) {
                continue;
            }
            if ((board[from] == (Rook | toMove) || board[from] == (Queen | toMove)) &&
                (!pinned[from] || pinned[from] == rookDir[i] ||
                 pinned[from] == -rookDir[i])) {
                return (true);
            } else {
                break;
            }
        }                       /* for j */
    }                           /* for i */
    return (false);
}                               /* RookToMovesAvailable */





/*----------------------------------------- -----------------------------
 | GENERATE							940422
 |
 | Contains all move generation procedures.
 +----------------------------------------------------------------------*/

static void     GeneratePawnMoves(BoardIndexType square, MoveType * list,
                                                  Unsigned1 * nrMoves);
static void     GenerateKnightMoves(BoardIndexType square, MoveType * list,
                                                    Unsigned1 * nrMoves);
static void     GenerateBishopMoves(BoardIndexType square, MoveType * list,
                                                    Unsigned1 * nrMoves);
static void     GenerateRookMoves(BoardIndexType square, MoveType * list,
                                                  Unsigned1 * nrMoves);
static void     GeneratePawnCaptureMoves(CheckPieceType * piece, MoveType * list,
                                                       Unsigned1 * nrMoves);
static void     GenerateKnightCaptureMoves(CheckPieceType * piece, MoveType * list,
                                                       Unsigned1 * nrMoves);
static void     GenerateBishopCaptureMoves(CheckPieceType * piece, MoveType * list,
                                                       Unsigned1 * nrMoves);
static void     GenerateRookCaptureMoves(CheckPieceType * piece, MoveType * list,
                                                       Unsigned1 * nrMoves);
static void     GenerateToMoves(BoardIndexType to, MoveType * list,
                                                Unsigned1 * nrMoves);
static void     GeneratePawnToMoves(BoardIndexType to, MoveType * list,
                                                    Unsigned1 * nrMoves);
static void     GenerateKnightToMoves(BoardIndexType to, MoveType * list,
                                                      Unsigned1 * nrMoves);
static void     GenerateBishopToMoves(BoardIndexType to, MoveType * list,
                                                      Unsigned1 * nrMoves);
static void     GenerateRookToMoves(BoardIndexType to, MoveType * list,
                                                    Unsigned1 * nrMoves);
static void     SiftUp(MoveType * moveList, Unsigned1 root, Unsigned1 leaf);


/*----------------------------------------------------------------------
 | GenerateMoves						940422
 |
 | Generates all legal moves.
 +----------------------------------------------------------------------*/
void            GenerateMoves(MoveType ** moveList, Unsigned1 * nrMoves)
{
    PieceType      *pieceTable;
    Unsigned1       nr;
    SquareType      piece;
    Signed2         i;
    MoveType        list[MaxMoves];

    pieceTable = pieces[toMove];
    nr = nrPieces[toMove];

    *nrMoves = 0;
    SearchForPinsAndCheck();
    switch (nrCheck) {
    case 0:
        for (i = 0; i < nr; i++) {
            
           
                             
                             
            piece = pieceTable[i].type;
            if (IsPawn(piece)) {
                GeneratePawnMoves(pieceTable[i].square, list, nrMoves);
            } else if (IsKnight(piece) && !pinned[pieceTable[i].square]) {
                GenerateKnightMoves(pieceTable[i].square, list, nrMoves);
            } else if (IsKing(piece)) {
                GenerateKingMoves(pieceTable[i].square, list, nrMoves);
            } else {
                if (MovesDiagonal(piece)) {
                    GenerateBishopMoves(pieceTable[i].square, list, nrMoves);
                }
                if (MovesStraight(piece)) {
                    GenerateRookMoves(pieceTable[i].square, list, nrMoves);
                }
            }
        }                       /* for i */
        break;
    case 1:
        /* Capture check-giving piece, NOT with king */
        GenerateCaptureMoves(&(checkingPiece[0]), list, nrMoves);
        /* Interpose piece */
        if (checkingPiece[0].dir &&
            kingSquare[toMove] + checkingPiece[0].dir !=
            checkingPiece[0].square) {
            GenerateInterposingMoves(&(checkingPiece[0]), list, nrMoves);
        }
        
    case 2:
        /* Move king away, including trying to capture (one of) the
         * check-giving piece(s) */
        GenerateKingMoves(kingSquare[toMove], list, nrMoves);
        break;
    default:
        printf("Error (times in check): %d\n", nrCheck);
        //exit(0);
        return;
    }                           /* switch */
    if (*nrMoves) {
        AllocateMoveList(*moveList, *nrMoves);
        memcpy(*moveList, list, *nrMoves * sizeof(MoveType));
    }
    
     
    nrGenerates++;
    nrMovesGenerated += *nrMoves;
}                               /* GenerateMoves */


/*----------------------------------------------------------------------
 | GeneratePawnMoves						940420
 |
 | Generates all legal pawn moves.
 +----------------------------------------------------------------------*/
static void     GeneratePawnMoves(BoardIndexType from, MoveType * list,
                                                  Unsigned1 * nrMoves)
{
    BoardIndexType  to;
    SquareType      piece;
    Unsigned1       dir;
    PieceType       attackingPiece;

    /* non-capture moves */
    if (!pinned[from] || pinned[from] == Up || pinned[from] == Down) {
        to = pawnMoveTable[toMove][from][0];
        if (IsEmpty(board[to])) {
            if (OnSeventhRank(toMove, from)) {
                PutMoveInTable(from, to, 0, Queen | toMove, Promotion, list,
                               *nrMoves);
                PutMoveInTable(from, to, 0, Knight | toMove, Promotion, list,
                               *nrMoves);
                PutMoveInTable(from, to, 0, Rook | toMove, Promotion, list,
                               *nrMoves);
                PutMoveInTable(from, to, 0, Bishop | toMove, Promotion, list,
                               *nrMoves);
            } else {
                PutMoveInTable(from, to, 0, 0, Normal, list, *nrMoves);
            }
            to = pawnMoveTable[toMove][from][1];
            if (IsEmpty(board[to])) {
                PutMoveInTable(from, to, 0, 0, Double, list, *nrMoves);
            }
        }                       /* if empty square */
    }                           /* if not pinned */
    /* capture moves */
    for (dir = 0; dir < 2; dir++) {
        if (!pinned[from] || pinned[from] == pawnCaptureDir[toMove][dir] ||
            pinned[from] == -pawnCaptureDir[toMove][dir]) {
          //  depth++;
            to = pawnCaptureTable[toMove][from][dir];
            if (to == epSquare[nrGamePlies]) {
                if (Rank(kingSquare[toMove]) != (toMove == White ? 5 : 4)) {
                    PutMoveInTable(from, to, Pawn | !toMove, 0,
                                   EnPassant | Capture, list, *nrMoves);
                } else {
                    /* remove pawns temporarily */
                    board[from] = Empty;
                    board[to + (toMove == White ? Down : Up)] = Empty;
                    if (!FindFirstPieceInDir((Unsigned1) MaxRookMoves,
                       rookTable[kingSquare[toMove]][2], &attackingPiece) ||
                        (attackingPiece.type != (Rook | !toMove) &&
                         attackingPiece.type != (Queen | !toMove))) {
                        if (!FindFirstPieceInDir((Unsigned1) MaxRookMoves,
                        rookTable[kingSquare[toMove]][3], &attackingPiece) ||
                            (attackingPiece.type != (Rook | !toMove) &&
                             attackingPiece.type != (Queen | !toMove))) {
                            PutMoveInTable(from, to, Pawn | !toMove, 0,
                                       EnPassant | Capture, list, *nrMoves);
                        }
                    }
                    /* Put pawns back */
                    board[from] = Pawn | toMove;
                    board[to + (toMove == White ? Down : Up)] = Pawn | !toMove;
                }
            } else {
                piece = board[to];
                if (piece && !IsEdge(piece) && !IsColor(piece, toMove)) {
                    if (OnSeventhRank(toMove, from)) {
                      //  depth++;
                        PutMoveInTable(from, to, piece, Queen | toMove,
                                       Promotion | Capture, list, *nrMoves);
                        PutMoveInTable(from, to, piece, Knight | toMove,
                                       Promotion | Capture, list, *nrMoves);
                        PutMoveInTable(from, to, piece, Rook | toMove,
                                       Promotion | Capture, list, *nrMoves);
                        PutMoveInTable(from, to, piece, Bishop | toMove,
                                       Promotion | Capture, list, *nrMoves);
                    } else {
                        PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
                    }
                }               /* if enemy piece */
            }                   /* else */
        }                       /* if not pinned */
    }                           /* for dir */
}                               /* GeneratePawnMoves */


/*----------------------------------------------------------------------
 | GenerateKnightMoves						940422
 |
 | Generates all legal knight moves.
 +----------------------------------------------------------------------*/
static void     GenerateKnightMoves(BoardIndexType from, MoveType * list,
                                                    Unsigned1 * nrMoves)
{
    Signed2         i;
    BoardIndexType  to;
    SquareType      piece;

    for (i = 0; i < MaxKnightMoves; i++) {
        to = knightTable[from][i];
        if (!to) {
            break;
        }
        piece = board[to];
        if (IsEmpty(piece)) {
            PutMoveInTable(from, to, 0, 0, Normal, list, *nrMoves);
        } else if (!IsEdge(piece) && !IsColor(piece, toMove)) {
            PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
        }
    }
}                               /* GenerateKnightMoves */


/*----------------------------------------------------------------------
 | GenerateBishopMoves						940422
 |
 | Generates all legal bishop moves.
 +----------------------------------------------------------------------*/
static void     GenerateBishopMoves(BoardIndexType from, MoveType * list,
                                                    Unsigned1 * nrMoves)
{
    Signed2         i,
                    j;
    BoardIndexType  to;
    SquareType      piece;

    for (i = 0; i < 4; i++) {
        if (!pinned[from] || pinned[from] == bishopDir[i] ||
            pinned[from] == -bishopDir[i]) {
            for (j = 0; j < MaxBishopMoves; j++) {
                to = bishopTable[from][i][j];
                if (!to) {
                    break;
                }
                piece = board[to];
                if (IsEmpty(piece)) {
                    PutMoveInTable(from, to, 0, 0, Normal, list, *nrMoves);
                } else if (!IsEdge(piece) && !IsColor(piece, toMove)) {
                    PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
                    break;
                } else {
                    break;
                }
            }                   /* for j */
        }                       /* if not pinned */
    }                           /* for i */
}                               /* GenerateBishopMoves */


/*----------------------------------------------------------------------
 | GenerateRookMoves						940422
 |
 | Generates all legal rook moves.
 +----------------------------------------------------------------------*/
static void     GenerateRookMoves(BoardIndexType from, MoveType * list,
                                                  Unsigned1 * nrMoves)
{
    Signed2         i,
                    j;
    BoardIndexType  to;
    SquareType      piece;

    for (i = 0; i < 4; i++) {
        if (!pinned[from] || pinned[from] == rookDir[i] ||
            pinned[from] == -rookDir[i]) {
            for (j = 0; j < MaxRookMoves; j++) {
                to = rookTable[from][i][j];
                if (!to) {
                    break;
                }
                piece = board[to];
                if (IsEmpty(piece)) {
                    PutMoveInTable(from, to, 0, 0, Normal, list, *nrMoves);
                } else if (!IsEdge(piece) && !IsColor(piece, toMove)) {
                    PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
                    break;
                } else {
                    break;
                }
            }                   /* for j */
        }                       /* if not pinned */
    }                           /* for i */
}                               /* GenerateRookMoves */





/*----------------------------------------------------------------------
 | Attacked							940426
 |
 | Checks if square 'square' is attacked by color 'color'.
 +----------------------------------------------------------------------*/
Boolean
Attacked(BoardIndexType square, SquareType color)
{
    Signed2         i;
    PieceType       attackingPiece;
    SquareType      piece;
    BoardIndexType  to;

    /* Attacked by Rook, Bishop or Queen */
    for (i = 0; i < 4; i++) {
        if (FindFirstPieceInDir((Unsigned1) MaxBishopMoves,
                                bishopTable[square][i], &attackingPiece)) {
            if (IsColor(attackingPiece.type, color) &&
                MovesDiagonal(attackingPiece.type)) {
                return (true);
            }
        }
        if (FindFirstPieceInDir((Unsigned1) MaxRookMoves, rookTable[square][i],
                                &attackingPiece)) {
            if (IsColor(attackingPiece.type, color) &&
                MovesStraight(attackingPiece.type)) {
                return (true);
            }
        }
    }
    /* Attacked by Knight */
    for (i = 0; i < 8; i++) {
        to = knightTable[square][i];
        if (!to) {
            break;
        }
        piece = board[to];
        if (IsKnight(piece) && IsColor(piece, color)) {
            return (true);
        }
    }
    /* Attacked by King */
    for (i = 0; i < 4; i++) {
        to = bishopTable[square][i][0];
        if (to) {
            piece = board[to];
            if (IsKing(piece) && IsColor(piece, color)) {
                return (true);
            }
        }
        to = rookTable[square][i][0];
        if (to) {
            piece = board[to];
            if (IsKing(piece) && IsColor(piece, color)) {
                return (true);
            }
        }
    }
    /* Attacked by Pawn */
    to = pawnCaptureTable[!color][square][0];
    if (to) {
        piece = board[to];
        if (IsPawn(piece) && IsColor(piece, color)) {
            return (true);
        }
    }
    to = pawnCaptureTable[!color][square][1];
    if (to) {
        piece = board[to];
        if (IsPawn(piece) && IsColor(piece, color)) {
            return (true);
        }
    }
    return (false);
}                               /* Attacked */


/*----------------------------------------------------------------------
 | FindFirstPieceInDir						940426
 |
 | Searches squares in table 'table' to find a piece. If no piece is
 | found, false is returned.
 +----------------------------------------------------------------------*/
#ifdef Bcc
Boolean
FindFirstPieceInDir(Unsigned1 max, BoardIndexType huge * table,
                    PieceType * attackingPiece)
#else
Boolean
FindFirstPieceInDir(Unsigned1 max, BoardIndexType * table,
                    PieceType * attackingPiece)
#endif
{
    Signed2         i;
    BoardIndexType  to;
    SquareType      piece;

    for (i = 0; i < max; i++) {
        to = table[i];
        if (!to) {
            return (false);
        }
        piece = board[to];
        if (!IsEmpty(piece)) {
            break;
        }
    }                           /* for i */
    if (IsEdge(piece)) {
        return (false);
    } else {
        attackingPiece->type = piece;
        attackingPiece->square = to;
        return (true);
    }
}                               /* FindFirstPieceInDir */


/*----------------------------------------------------------------------
 | SearchForPinsAndCheck					940427
 |
 | Checks if side 'toMove' is inCheck and which pieces are pinned and
 | in what direction.
 +----------------------------------------------------------------------*/
void            SearchForPinsAndCheck(void)
{
    BoardIndexType  square,
                    sq,
                    to;
    Signed2         i;
    SquareType      piece;
    PieceType       attackingPiece;

    nrCheck = 0;
    checkingPiece[0].dir = checkingPiece[1].dir = 0;
    for (i = 0; i < nrPieces[toMove]; i++) {
        pinned[pieces[toMove][i].square] = 0;
    }
    square = kingSquare[toMove];
    /* Check or pinned by Rook, Bishop or Queen */
    for (i = 0; i < 4; i++) {
        if (FindFirstPieceInDir((Unsigned1) MaxBishopMoves,
                                bishopTable[square][i], &attackingPiece)) {
            if (IsColor(attackingPiece.type, !toMove)) {
                if (MovesDiagonal(attackingPiece.type)) {
                    checkingPiece[nrCheck].square = attackingPiece.square;
                    checkingPiece[nrCheck++].dir = bishopDir[i];
                }
            } else {
                sq = attackingPiece.square;
                if (FindFirstPieceInDir((Unsigned1) MaxBishopMoves,
                                     bishopTable[sq][i], &attackingPiece) &&
                    IsColor(attackingPiece.type, !toMove)) {
                    if (MovesDiagonal(attackingPiece.type)) {
                        pinned[sq] = bishopDir[i];
                    }
                }               /* pinned */
            }                   /* else */
        }                       /* if piece */
        if (FindFirstPieceInDir((Unsigned1) MaxRookMoves,
                                rookTable[square][i], &attackingPiece)) {
            if (IsColor(attackingPiece.type, !toMove)) {
                if (MovesStraight(attackingPiece.type)) {
                    checkingPiece[nrCheck].square = attackingPiece.square;
                    checkingPiece[nrCheck++].dir = rookDir[i];
                }
            } else {
                sq = attackingPiece.square;
                if (FindFirstPieceInDir((Unsigned1) MaxRookMoves,
                                        rookTable[sq][i], &attackingPiece) &&
                    IsColor(attackingPiece.type, !toMove)) {
                    if (MovesStraight(attackingPiece.type)) {
                        pinned[sq] = rookDir[i];
                    }
                }               /* pinned */
            }                   /* else */
        }                       /* if piece */
    }
    /* Check by Knight */
    for (i = 0; i < 8; i++) {
        to = knightTable[square][i];
        if (!to) {
            break;
        }
        piece = board[to];
        if (IsKnight(piece) && IsColor(piece, !toMove)) {
            checkingPiece[nrCheck].square = to;
            checkingPiece[nrCheck++].dir = 0;
        }
    }
    /* Check by Pawn */
    to = pawnCaptureTable[toMove][square][0];
    if (to) {
        piece = board[to];
        if (IsPawn(piece) && IsColor(piece, !toMove)) {
            checkingPiece[nrCheck].square = to;
            checkingPiece[nrCheck++].dir = 0;
        }
    }
    to = pawnCaptureTable[toMove][square][1];
    if (to) {
        piece = board[to];
        if (IsPawn(piece) && IsColor(piece, !toMove)) {
            checkingPiece[nrCheck].square = to;
            checkingPiece[nrCheck++].dir = 0;
        }
    }

}                               /* SearchForPinsAndCheck */


/*----------------------------------------------------------------------
 | GenerateCaptureMoves						940428
 |
 | Generate moves for color 'toMove', trying to disable check by
 | capturing the check-giving piece.
 | NOTE: no king capture moves are generated because they are generated
 | later in GenerateKingMoves().
 +----------------------------------------------------------------------*/
void            GenerateCaptureMoves(CheckPieceType * piece, MoveType * list,
                                                     Unsigned1 * nrMoves)
{
    GeneratePawnCaptureMoves(piece, list, nrMoves);
    GenerateKnightCaptureMoves(piece, list, nrMoves);
    GenerateBishopCaptureMoves(piece, list, nrMoves);
    GenerateRookCaptureMoves(piece, list, nrMoves);
}                               /* GenerateCaptureMoves */


/*----------------------------------------------------------------------
 | GeneratePawnCaptureMoves					940428
 |
 | Generate pawn moves for color 'toMove', trying to disable check by
 | capturing the check-giving piece.
 +----------------------------------------------------------------------*/
static void     GeneratePawnCaptureMoves(CheckPieceType * piece, MoveType * list,
                                                         Unsigned1 * nrMoves)
{
    Signed2         dir;
    BoardIndexType  from,
                    to;

    to = piece->square;
    /* Normal capture */
    for (dir = 0; dir < 2; dir++) {
        if (pawnCaptureDir[!toMove][dir] == -piece->dir) {
            continue;
        }
        from = pawnCaptureTable[!toMove][to][dir];
        if (from && board[from] == (Pawn | toMove) && (!pinned[from] ||
                             pinned[from] == pawnCaptureDir[!toMove][dir] ||
                           pinned[from] == -pawnCaptureDir[!toMove][dir])) {
            if (OnSeventhRank(toMove, from)) {
                PutMoveInTable(from, to, board[to], Queen | toMove,
                               Promotion | Capture, list, *nrMoves);
                PutMoveInTable(from, to, board[to], Knight | toMove,
                               Promotion | Capture, list, *nrMoves);
                PutMoveInTable(from, to, board[to], Rook | toMove,
                               Promotion | Capture, list, *nrMoves);
                PutMoveInTable(from, to, board[to], Bishop | toMove,
                               Promotion | Capture, list, *nrMoves);
            } else {
                PutMoveInTable(from, to, board[to], 0, Capture, list,
                               *nrMoves);
            }
        }                       /* if not pinned */
    }                           /* for dir */

    /* En passant */
    dir = toMove == White ? Up : Down;
    if (epSquare[nrGamePlies] == to + dir) {
        from = to + Right;
        if (from && board[from] == (Pawn | toMove) && (!pinned[from] ||
             pinned[from] == dir + Right || pinned[from] == -dir - Right)) {
            PutMoveInTable(from, to + dir, board[to], 0, EnPassant | Capture,
                           list, *nrMoves);
                         
        }                       /* if not pinned */
        from = to + Left;
        if (from && board[from] == (Pawn | toMove) && (!pinned[from] ||
               pinned[from] == dir + Left || pinned[from] == -dir - Left)) {
            PutMoveInTable(from, to + dir, board[to], 0, EnPassant | Capture,
                           list, *nrMoves);
                        
        }                       /* if not pinned */
    }                           /* if */
}                               /* GeneratePawnCaptureMoves */


/*----------------------------------------------------------------------
 | GenerateKnightCaptureMoves					940428
 |
 | Generate knight moves for color 'toMove', trying to disable check by
 | capturing the check-giving piece.
 +----------------------------------------------------------------------*/
static void     GenerateKnightCaptureMoves(CheckPieceType * piece, MoveType * list,
                                                        Unsigned1 * nrMoves)
{
    Signed2         i;
    BoardIndexType  from,
                    to;

    to = piece->square;
    for (i = 0; i < MaxKnightMoves; i++) {
        if (knightDir[i] == -piece->dir) {
            continue;
        }
        from = knightTable[to][i];
        if (!from) {
            break;
        }
        if (board[from] == (Knight | toMove) && !pinned[from]) {
            PutMoveInTable(from, to, board[to], 0, Capture, list, *nrMoves);
          
        }
    }
}                               /* GenerateKnightCaptureMoves */


/*----------------------------------------------------------------------
 | GenerateBishopCaptureMoves					940428
 |
 | Generate bishop moves for color 'toMove', trying to disable check by
 | capturing the check-giving piece.
 +----------------------------------------------------------------------*/
static void     GenerateBishopCaptureMoves(CheckPieceType * piece, MoveType * list,
                                                        Unsigned1 * nrMoves)
{
    Signed2         i,
                    j;
    BoardIndexType  from,
                    to;

    to = piece->square;
    for (i = 0; i < 4; i++) {
        if (bishopDir[i] == -piece->dir) {
            continue;
        }
        for (j = 0; j < MaxBishopMoves; j++) {
            from = bishopTable[to][i][j];
            if (!from) {
                break;
            }
            if (IsEmpty(board[from])) {
                continue;
            }
            if ((board[from] == (Bishop | toMove) || board[from] == (Queen | toMove)) &&
                (!pinned[from] || pinned[from] == bishopDir[i] ||
                 pinned[from] == -bishopDir[i])) {
                PutMoveInTable(from, to, board[to], 0, Capture, list, *nrMoves);
                break;
            } else {
                break;
            }
        }                       /* for j */
    }                           /* for i */
}                               /* GenerateBishopCaptureMoves */


/*----------------------------------------------------------------------
 | GenerateRookCaptureMoves					940428
 |
 | Generate rook moves for color 'toMove', trying to disable check by
 | capturing the check-giving piece.
 +----------------------------------------------------------------------*/
static void     GenerateRookCaptureMoves(CheckPieceType * piece, MoveType * list,
                                                         Unsigned1 * nrMoves)
{
    Signed2         i,
                    j;
    BoardIndexType  from,
                    to;

    to = piece->square;
    for (i = 0; i < 4; i++) {
        if (rookDir[i] == -piece->dir) {
            continue;
        }
        for (j = 0; j < MaxRookMoves; j++) {
            from = rookTable[to][i][j];
            if (!from) {
                break;
            }
            if (IsEmpty(board[from])) {
                continue;
            }
            if ((board[from] == (Rook | toMove) || board[from] == (Queen | toMove)) &&
                (!pinned[from] || pinned[from] == rookDir[i] ||
                 pinned[from] == -rookDir[i])) {
                PutMoveInTable(from, to, board[to], 0, Capture, list, *nrMoves);
                break;
            } else {
                break;
            }
        }                       /* for j */
    }                           /* for i */
}                               /* GenerateRookCaptureMoves */


/*----------------------------------------------------------------------
 | GenerateInterposingMoves					940428
 |
 | Generate moves for color 'toMove' to disable check by interposing
 | a piece.
 +----------------------------------------------------------------------*/
void            GenerateInterposingMoves(CheckPieceType * piece, MoveType * list,
                                                         Unsigned1 * nrMoves)
{
    BoardIndexType  to;
    DirectionType   dir;

    dir = piece->dir;
    for (to = kingSquare[toMove] + dir; to != piece->square; to += dir) {
        GenerateToMoves(to, list, nrMoves);
    }                           /* for square */
}                               /* GenerateInterposingMoves */


/*----------------------------------------------------------------------
 | GenerateToMoves						940428
 |
 | Generates moves for color 'toMove' to empty square 'to'.
 | NOTE: no king moves are generated.
 +----------------------------------------------------------------------*/
static void     GenerateToMoves(BoardIndexType to, MoveType * list,
                                                Unsigned1 * nrMoves)
{
    GeneratePawnToMoves(to, list, nrMoves);
    GenerateKnightToMoves(to, list, nrMoves);
    GenerateBishopToMoves(to, list, nrMoves);
    GenerateRookToMoves(to, list, nrMoves);
}                               /* GenerateToMoves */


/*----------------------------------------------------------------------
 | GeneratePawnToMoves						940428
 |
 | Generates pawn moves for color 'toMove' to empty square 'to'.
 +----------------------------------------------------------------------*/
static void     GeneratePawnToMoves(BoardIndexType to, MoveType * list,
                                                    Unsigned1 * nrMoves)
{
    BoardIndexType  from;
    Unsigned1       type;

    
         
    
    from = pawnMoveTable[!toMove][to][0];
    


    /* Move from second rank? */
    if (IsEmpty(board[from]) &&
        Rank(from) == (IsWhite(toMove) ? 3 : 6)) {
        from = pawnMoveTable[!toMove][from][0];
        type = Double;
    } else {
        type = Normal;
    
   
}
      
        
    
    if (board[from] == (Pawn | toMove) && (!pinned[from] ||
                              pinned[from] == Up || pinned[from] == Down)) {
        if (OnSeventhRank(toMove, from)) {
            PutMoveInTable(from, to, 0, Queen | toMove, Promotion, list,
                           *nrMoves);
            PutMoveInTable(from, to, 0, Knight | toMove, Promotion, list,
                           *nrMoves);
            PutMoveInTable(from, to, 0, Rook | toMove, Promotion, list,
                           *nrMoves);
            PutMoveInTable(from, to, 0, Bishop | toMove, Promotion, list,
                           *nrMoves);
        } else {
            PutMoveInTable(from, to, 0, 0, type, list, *nrMoves);
        }
    }                           /* if not pinned */
}                               /* GeneratePawnToMoves */


/*----------------------------------------------------------------------
 | GenerateKnightToMoves						940428
 |
 | Generates knight moves for color 'toMove' to empty square 'to'.
 +----------------------------------------------------------------------*/
static void     GenerateKnightToMoves(BoardIndexType to, MoveType * list,
                                                      Unsigned1 * nrMoves)
{
    Signed2         i;
    BoardIndexType  from;

    for (i = 0; i < MaxKnightMoves; i++) {
        from = knightTable[to][i];
        if (!from) {
            break;
        }
        if (board[from] == (Knight | toMove) && !pinned[from]) {
            PutMoveInTable(from, to, 0, 0, Normal, list, *nrMoves);
        }
    }
}                               /* GenerateKnightToMoves */


/*----------------------------------------------------------------------
 | GenerateBishopToMoves					940428
 |
 | Generates bishop moves for color 'toMove' to empty square 'to'.
 +----------------------------------------------------------------------*/
static void     GenerateBishopToMoves(BoardIndexType to, MoveType * list,
                                                      Unsigned1 * nrMoves)
{
    Signed2         i,
                    j;
    BoardIndexType  from;

    for (i = 0; i < 4; i++) {
        for (j = 0; j < MaxBishopMoves; j++) {
            from = bishopTable[to][i][j];
            if (!from) {
                break;
            }
            if (IsEmpty(board[from])) {
                continue;
            }
            if ((board[from] == (Bishop | toMove) || board[from] == (Queen | toMove)) &&
                (!pinned[from] || pinned[from] == bishopDir[i] ||
                 pinned[from] == -bishopDir[i])) {
                PutMoveInTable(from, to, 0, 0, Normal, list, *nrMoves);
                break;
            } else {
                break;
            }
        }                       /* for j */
    }                           /* for i */
}                               /* GenerateBishopToMoves */


/*----------------------------------------------------------------------
 | GenerateRookToMoves						940428
 |
 | Generates rook moves for color 'toMove' to empty square 'to'.
 +----------------------------------------------------------------------*/
static void     GenerateRookToMoves(BoardIndexType to, MoveType * list,
                                                    Unsigned1 * nrMoves)
{
    Signed2         i,
                    j;
    BoardIndexType  from;

    for (i = 0; i < 4; i++) {
        for (j = 0; j < MaxRookMoves; j++) {
            from = rookTable[to][i][j];
            if (!from) {
                break;
            }
            if (IsEmpty(board[from])) {
                continue;
            }
            if ((board[from] == (Rook | toMove) || board[from] == (Queen | toMove)) &&
                (!pinned[from] || pinned[from] == rookDir[i] ||
                 pinned[from] == -rookDir[i])) {
                PutMoveInTable(from, to, 0, 0, Normal, list, *nrMoves);
                break;
            } else {
                break;
            }
        }                       /* for j */
    }                           /* for i */
}                               /* GenerateRookToMoves */


Signed2
CompareMoves(MoveType * move1, MoveType * move2)
{

   long      diff1, diff2;
   long      *eval1Table, *eval2Table;
 
    if (move1->to == lastMovedPieceSquare &&
        move2->to == lastMovedPieceSquare) {
        goto sameCapture;
    }
    if (move1->to == lastMovedPieceSquare) {
        return (-1);
    }
    if (move2->to == lastMovedPieceSquare) {
        return (1);
    }
    /* Promotion moves */
    if (move1->promotionPiece > move2->promotionPiece) {
        return (-1);
    }
    if (move1->promotionPiece < move2->promotionPiece) {
        return (1);
    }
    /* Capture moves */
    if (move1->capturedPiece > move2->capturedPiece) {
        return (-1);
    }
    if (move1->capturedPiece < move2->capturedPiece) {
        return (1);
    }


  // new - JA
  
   if (pieceValue[ move1->capturedPiece ]-pieceValue[ board[ move1->from ] ]>
   pieceValue[ move2->capturedPiece ]-pieceValue[ board[ move2->from ] ]) {
   return( -1 );
   }
   if (pieceValue[ move1->capturedPiece ]-pieceValue[ board[ move1->from ] ]<
   pieceValue[ move2->capturedPiece ]-pieceValue[ board[ move2->from ] ]) {
   return( 1 );
   }
    
    ///////////////////
 
 
sameCapture:
    if (board[move1->from] < board[move2->from]) {
        return (-1);
    }
    if (board[move1->from] > board[move2->from]) {
        return (1);
    }
    /* History heuristic */
    if (historyTable[toMove][move1->from][move1->to] >
        historyTable[toMove][move2->from][move2->to]) {
        return (-1);
    }
    if (historyTable[toMove][move1->from][move1->to] <
        historyTable[toMove][move2->from][move2->to]) {
        return (1);
    }


#ifndef WINDOWS
   // new - JA
   GetEvalTable( eval1Table, toMove, board[ move1->from ] );
   GetEvalTable( eval2Table, toMove, board[ move2->from ] );
   diff1 = eval1Table[ move1->to ] - eval1Table[ move1->from ];
   diff2 = eval2Table[ move2->to ] - eval2Table[ move2->from ];
   if (diff1 > diff2) {
   return( -1 );
   }
   if (diff1 < diff2) {
   return( 1 );
   }
#endif
   /////////////////
  
  
 
    return (0);
}                               /* CompareMoves */


void            HeapSort(MoveType * moveList, Unsigned1 nrMoves)
{
    Unsigned1       i;
    MoveType        temp;

    /* Construct heap */
    for (i = nrMoves / 2 - 1; i > 0; i--) {
        SiftUp(moveList, (Unsigned1) i, (Unsigned1) (nrMoves - 1));
    }
    /* Iterate */
    for (i = nrMoves - 1; i > 0; i--) {
        SiftUp(moveList, (Unsigned1) 0, (Unsigned1) i);
        temp = moveList[0];
        moveList[0] = moveList[i];
        moveList[i] = temp;
    }
}                               /* HeapSort */


static void     SiftUp(MoveType * moveList, Unsigned1 root, Unsigned1 leaf)
{
    Unsigned1       i;
    MoveType        temp;

    for (temp = moveList[root];;) {
        i = 2 * root + 1;       /* Left child */
        if (i <= leaf) {
            if (i < leaf) {
                if (CompareMoves(&(moveList[i + 1]), &(moveList[i])) == 1) {
                    i++;        /* Right child */
                }
            }
            if (CompareMoves(&(moveList[i]), &temp) == 1) {
                moveList[root] = moveList[i];
                root = i;
            } else {
                break;
            }
        } else {
            break;
        }
    }
    moveList[root] = temp;
}                               /* SiftUp */


void            SiftDown(MoveType * moveList, Unsigned1 root, Unsigned1 leaf)
{
    Unsigned1       i;
    MoveType        temp;

    for (temp = moveList[root];;) {
        i = 2 * root + 1;       /* Left child */
        if (i <= leaf) {
            if (i < leaf) {
                if (CompareMoves(&(moveList[i + 1]), &(moveList[i])) == -1) {
                    i++;        /* Right child */
                }
            }
            if (CompareMoves(&(moveList[i]), &temp) == -1) {
                moveList[root] = moveList[i];
                root = i;
            } else {
                break;
            }
        } else {
            break;
        }
    }
    moveList[root] = temp;
}                               /* SiftDown */






/*----------------------------------------------------------------------
 | IO							940420
 |
 | Contains the I/O-routines.
 +----------------------------------------------------------------------*/




static int CDECL CompareHistory(const void *h1, const void *h2);


/*----------------------------------------------------------------------
 | PrintBoard							940421
 |
 | Prints the board.
 +----------------------------------------------------------------------*/
void            PrintBoard(void)
{
    Signed2         i,
                    j;
    SquareType      square;
    char            s[MaxCommandLength];

    printf("%s\t", moveColorString[toMove]);
    if (epSquare[nrGamePlies] != NoEp) {
        SPrintSquare(s, epSquare[nrGamePlies]);
        printf("%s\t", s);
    }
    if (castling[nrGamePlies] & WhiteShort) {
        printf("WS ");
    }
    if (castling[nrGamePlies] & WhiteLong) {
        printf("WL ");
    }
    if (castling[nrGamePlies] & BlackShort) {
        printf("BS ");
    }
    if (castling[nrGamePlies] & BlackLong) {
        printf("BL ");
    }
    printf("%ld%c%d %ld%c%d", material[White],
        positionalValue[White] < 0 ? '-' : '+', abs(positionalValue[White]),
           material[Black], positionalValue[Black] < 0 ? '-' : '+',
           abs(positionalValue[Black]));
    printf("\t(%lx,%lx)", hashValue[nrGamePlies][0],
           hashValue[nrGamePlies][1]);
    printf("\n  +------------------------+\n");
    for (i = 8; i >= 1; i--) {
        printf("%d |", i);
        for (j = A; j <= H; j++) {
            square = Square(j, i);
            if (WhiteSquare(j, i)) {
                printf(":");
            } else {
                printf(" ");
            }
            if (IsEmpty(board[square])) {
                if (WhiteSquare(j, i)) {
                    printf(":");
                } else {
                    printf(" ");
                }
            } else {
                printf("%c", pieceSymbol[board[square]]);
            }
            if (WhiteSquare(j, i)) {
                printf(":");
            } else {
                printf(" ");
            }
        }                       /* for j */
        printf("|\n");
    }                           /* for i */
    printf("  +------------------------+\n");
    printf("    A  B  C  D  E  F  G  H\n");
}                               /* PrintBoard */


/*----------------------------------------------------------------------
 | PrintMoveList						940425
 |
 | Prints all moves from a move list.
 +----------------------------------------------------------------------*/
void            PrintMoveList(MoveType * list, Unsigned1 nrMoves)
{
    Signed2         i;
    char            s[MaxCommandLength];

    for (i = 0; i < nrMoves; i++) {
        SPrintMove(s, list[i]);
        printf("%s ", s);
    }
    printf("\n");
}                               /* PrintMoveList */


/*----------------------------------------------------------------------
 | PrintAllocVariables						940425
 |
 | Prints all allocate variables.
 +----------------------------------------------------------------------*/
void            PrintAllocVariables(void)
{
    printf("Allocated move lists: %d\n", nrAllocMoveLists);
    printf("Allocated path moves: %d\n", nrAllocPathMoves);
}                               /* PrintAllocVariables */


void            PrintGame(Signed2 from, Signed2 to)
{
    Signed2         i;

    for (i = from; i <= to; i++) {
        if (i % 2 == 0) {
            printf("%3d.", i / 2 + 1);
        }
        printf(" %s", gameString[i]);
        if (i % 8 == 7) {
            printf("\n");
        }
    }
    printf("\n");
}                               /* PrintGame */


/*----------------------------------------------------------------------
 | PrintPath							940506
 |
 | Prints a move path.
 +----------------------------------------------------------------------*/
void            PrintPath(PathType * path)
{
    PathType       *ptr;
    Signed2         i,
                    j;

    if (path == NULL) {
        return;
    }
    for (i = 0, ptr = path; ptr != NULL; ptr = ptr->next, i++) {
        if (i && !(i % 6)) {
            printf("\n                     ");
        }
        printf("%-8s", ptr->moveString);
    }
    for (j = 0; j < (6 - i % 6) % 6; j++) {
        printf("        ");
    }
}                               /* PrintPath */


void            PrintHistoryTable(void)
{
    BoardIndexType  i,
                    j;
    char            s[4];
    Unsigned2       nrHistoryMoves;
    History         table[500];

    printf("White:\n");
    nrHistoryMoves = 0;
    for (i = A1; i <= H8; i++) {
        for (j = A1; j <= H8; j++) {
            if (historyTable[White][i][j] != 0) {
                table[nrHistoryMoves].from = i;
                table[nrHistoryMoves].to = j;
                table[nrHistoryMoves++].nr = historyTable[White][i][j];
            }
        }
    }
    qsort(table, nrHistoryMoves, sizeof(History), CompareHistory);
    for (i = 0; i < (BoardIndexType) nrHistoryMoves; i++) {
        SPrintSquare(s, table[i].from);
        printf("%s", s);
        SPrintSquare(s, table[i].to);
        printf("%s%5d,", s, table[i].nr);
    }

    printf("\n\nBlack:\n");
    nrHistoryMoves = 0;
    for (i = A1; i <= H8; i++) {
        for (j = A1; j <= H8; j++) {
            if (historyTable[Black][i][j] != 0) {
                table[nrHistoryMoves].from = i;
                table[nrHistoryMoves].to = j;
                table[nrHistoryMoves++].nr = historyTable[Black][i][j];
            }
        }
    }
    qsort(table, nrHistoryMoves, sizeof(History), CompareHistory);
    for (i = 0; i < (BoardIndexType) nrHistoryMoves; i++) {
        SPrintSquare(s, table[i].from);
        printf("%s", s);
        SPrintSquare(s, table[i].to);
        printf("%s%5d,", s, table[i].nr);
    }
}                               /* PrintHistoryTable */


static int      CDECL
                CompareHistory(const void *his1, const void *his2)
{
    History        *h1,
                   *h2;

    h1 = (History *) his1;
    h2 = (History *) his2;
    if (h1->nr < h2->nr) {
        return (1);
    }
    if (h1->nr > h2->nr) {
        return (-1);
    }
    return (0);
}                               /* CompareHistory */


void            PrintHashes(void)
{
    Signed2         i;

    for (i = nrGamePlies; i >= startHashIndex[nrGamePlies]; i--) {
        printf("%3d: %x, %x\n", i, hashValue[i][0], hashValue[i][1]);
    }
}                               /* PrintHashes */


void            PrintSettings(void)
{
    printf("\nSettings\n");
    printf("--------\n");
    printf("Refutation table   : %s\n", logicString[useRefTable]);
    printf("Transposition table: %s\n", logicString[useTransTable]);
    if (useTransTable) {
        printf("\nClearing entries with age %d ply\n", keepPly + 1);
        printf("Keepmethod   : %s\n", methodString[keepMethod]);
        printf("TwoLevelTable: %s\n", logicString[useTwoLevelTable]);
        printf("UseTtValue   : %s\n", logicString[useTtValue]);
        printf("UseTtMove    : %s\n", logicString[useTtMove]);
        printf("useFlag      : %s\n", logicString[useFlag]);
        printf("timeStamp    : %s\n", logicString[timeStamp]);
    }
}                               /* PrintSettings */


void            PrintTestSettings(Signed2 testDepth, Signed2 testColor,
                                                  Signed4 testNrNodes)
{
    printf("\nTest settings\n");
    printf("-------------\n");
    printf("search with depth            : %d\n", testDepth);
    printf("search with color            : %s\n", moveColorString[testColor]);
    printf("search with max. number nodes: %d\n", testNrNodes);
    printf("----------------------------------------------------------------\n");
}




/*----------------------------------------------------------------------
 | MOVE							940426
 |
 | Contains all move procedures.
 +----------------------------------------------------------------------*/




static void     CheckRedundancies(void);


/*----------------------------------------------------------------------
 | DoMove							940426
 |
 | Performs a move internally and updates the board. Color to move
 | (toMove) is updated.
 +----------------------------------------------------------------------*/
void            DoMove(MoveType * move)
{
    BoardIndexType  square,
                    square1,
                    square2;
    SquareType      piece;
    Signed2        *evalTable;
    HashType       *hashTable;

    lastMovedPieceSquare = move->to;
    if (maxGamePlies > nrGamePlies &&
        EqualMoves(move, &(game[nrGamePlies]))) {
        ++nrGamePlies;
    } else {
        SPrintMove(gameString[nrGamePlies], *move);
        game[nrGamePlies++] = *move;
        maxGamePlies = nrGamePlies;
    }

    castling[nrGamePlies] = castling[nrGamePlies - 1];  /* Update castling and */
    HashIs(hashValue[nrGamePlies], hashValue[nrGamePlies - 1]); /* hash and */
    startHashIndex[nrGamePlies] = startHashIndex[nrGamePlies - 1];      /* index. */

    piece = board[move->from];

    /* Converting move? */
    if (IsPawn(piece) || move->capturedPiece != 0) {
        startHashIndex[nrGamePlies] = nrGamePlies;
    }
    GetEvalTable(evalTable, toMove, piece);
    positionalValue[toMove] += evalTable[move->to] - evalTable[move->from];
    GetHashTable(hashTable, toMove, piece);
    HashXorIs(hashValue[nrGamePlies], hashTable[move->from]);
    HashXorIs(hashValue[nrGamePlies], hashTable[move->to]);

    square = Square(H, 1);
    if (move->from == square || move->to == square) {
        if (castling[nrGamePlies] & WhiteShort) {
            castling[nrGamePlies] &= ~WhiteShort;
            HashXorIs(hashValue[nrGamePlies],
                      castlingHashTable[White][Short]);
        }
    }                           /* White short */
    square = Square(A, 1);
    if (move->from == square || move->to == square) {
        if (castling[nrGamePlies] & WhiteLong) {
            castling[nrGamePlies] &= ~WhiteLong;
            HashXorIs(hashValue[nrGamePlies],
                      castlingHashTable[White][Long]);
        }
    }                           /* White long */
    square = Square(H, 8);
    if (move->from == square || move->to == square) {
        if (castling[nrGamePlies] & BlackShort) {
            castling[nrGamePlies] &= ~BlackShort;
            HashXorIs(hashValue[nrGamePlies],
                      castlingHashTable[Black][Short]);
        }
    }                           /* Black short */
    square = Square(A, 8);
    if (move->from == square || move->to == square) {
        if (castling[nrGamePlies] & BlackLong) {
            castling[nrGamePlies] &= ~BlackLong;
            HashXorIs(hashValue[nrGamePlies],
                      castlingHashTable[Black][Long]);
        }
    }                           /* Black long */
    if (IsKing(piece)) {
        kingSquare[toMove] = move->to;
        if (toMove == White) {
            if (castling[nrGamePlies] & WhiteShort) {
                castling[nrGamePlies] &= ~WhiteShort;
                HashXorIs(hashValue[nrGamePlies],
                          castlingHashTable[White][Short]);
            }
            if (castling[nrGamePlies] & WhiteLong) {
                castling[nrGamePlies] &= ~WhiteLong;
                HashXorIs(hashValue[nrGamePlies],
                          castlingHashTable[White][Long]);
            }
        } else {
            if (castling[nrGamePlies] & BlackShort) {
                castling[nrGamePlies] &= ~BlackShort;
                HashXorIs(hashValue[nrGamePlies],
                          castlingHashTable[Black][Short]);
            }
            if (castling[nrGamePlies] & BlackLong) {
                castling[nrGamePlies] &= ~BlackLong;
                HashXorIs(hashValue[nrGamePlies],
                          castlingHashTable[Black][Long]);
            }
        }
    }
    /* En passant */
    if (IsEnPassantMove(move->type)) {
        square = pawnMoveTable[!toMove][move->to][0];
        material[!toMove] -= pieceValue[board[square]];
        pieces[!toMove][pieceIndex[square]] =
            pieces[!toMove][--nrPieces[!toMove]];
        pieceIndex[pieces[!toMove][pieceIndex[square]].square] =
            pieceIndex[square];
        board[square] = Empty;
        positionalValue[!toMove] -= pawnEvalTable[!toMove][square];
        HashXorIs(hashValue[nrGamePlies], pawnHashTable[!toMove][square]);
        /* Capture */
    } else if (IsCaptureMove(move->type)) {
        material[!toMove] -= pieceValue[board[move->to]];
        pieces[!toMove][pieceIndex[move->to]] =
            pieces[!toMove][--nrPieces[!toMove]];
        pieceIndex[pieces[!toMove][pieceIndex[move->to]].square] =
            pieceIndex[move->to];
        GetEvalTable(evalTable, !toMove, board[move->to]);
        positionalValue[!toMove] -= (evalTable[move->to]) + (incentive_capture);
        GetHashTable(hashTable, !toMove, board[move->to]);
        HashXorIs(hashValue[nrGamePlies], hashTable[move->to]);
    }
    /* Castling */
    if (IsShortCastleMove(move->type)) {
        square1 = Square(H, toMove == White ? 1 : 8);
        square2 = Square(F, toMove == White ? 1 : 8);
        board[square2] = board[square1];
        board[square1] = Empty;
        pieces[toMove][pieceIndex[square1]].square = square2;
        pieceIndex[square2] = pieceIndex[square1];
        pieceIndex[square1] = 0;
        positionalValue[toMove] += (rookEvalTable[toMove][square2] -
            rookEvalTable[toMove][square1]) + (incentive_castling);
        HashXorIs(hashValue[nrGamePlies], rookHashTable[toMove][square2]);
        HashXorIs(hashValue[nrGamePlies], rookHashTable[toMove][square1]);
    } else if (IsLongCastleMove(move->type)) {
        square1 = Square(A, toMove == White ? 1 : 8);
        square2 = Square(D, toMove == White ? 1 : 8);
        board[square2] = board[square1];
        board[square1] = Empty;
        pieces[toMove][pieceIndex[square1]].square = square2;
        pieceIndex[square2] = pieceIndex[square1];
        pieceIndex[square1] = 0;
        positionalValue[toMove] += (rookEvalTable[toMove][square2] -
            rookEvalTable[toMove][square1]) + (incentive_castling/2);
        HashXorIs(hashValue[nrGamePlies], rookHashTable[toMove][square2]);
        HashXorIs(hashValue[nrGamePlies], rookHashTable[toMove][square1]);
    }
    /* Promotion */
    if (IsPromotionMove(move->type)) {
        material[toMove] -= pieceValue[piece];
        board[move->from] = move->promotionPiece;
        material[toMove] += pieceValue[board[move->from]];
        pieces[toMove][pieceIndex[move->from]].type =
            move->promotionPiece;
        GetEvalTable(evalTable, toMove, move->promotionPiece);
        positionalValue[toMove] += evalTable[move->to] -
            pawnEvalTable[toMove][move->to];
        GetHashTable(hashTable, toMove, move->promotionPiece);
        HashXorIs(hashValue[nrGamePlies], hashTable[move->to]);
        HashXorIs(hashValue[nrGamePlies], pawnHashTable[toMove][move->to]);
    }
    board[move->to] = board[move->from];
    board[move->from] = Empty;
    pieces[toMove][pieceIndex[move->from]].square = move->to;
    pieceIndex[move->to] = pieceIndex[move->from];
    pieceIndex[move->from] = 0;
    if (IsDoubleMove(move->type)) {
        epSquare[nrGamePlies] = pawnMoveTable[toMove][move->from][0];
        HashXorIs(hashValue[nrGamePlies], enPassantHashTable[File(move->from)]);
    } else {
        epSquare[nrGamePlies] = NoEp;
    }
    if (epSquare[nrGamePlies - 1] != NoEp && nrGamePlies > 0) {
        HashXorIs(hashValue[nrGamePlies],
                  enPassantHashTable[File(epSquare[nrGamePlies - 1])]);
    }
    HashXorIs(hashValue[nrGamePlies], movedHash);
    toMove = !toMove;
#ifdef Debug
    CheckRedundancies();
#endif
}                               /* DoMove */


/*----------------------------------------------------------------------
 | UndoMove							940426
 |
 | Takes back a move internally and updates the board. Color to move
 | (toMove) is updated.
 +----------------------------------------------------------------------*/
void            UndoMove(void)
{
    BoardIndexType  square,
                    square1,
                    square2;
    MoveType       *move;
    SquareType      piece;
    Signed2        *table;

    move = &(game[--nrGamePlies]);
    if (nrGamePlies > 0) {
        lastMovedPieceSquare = game[nrGamePlies - 1].to;
    } else {
        lastMovedPieceSquare = 0;
    }
    toMove = !toMove;
    pieces[toMove][pieceIndex[move->to]].square = move->from;
    pieceIndex[move->from] = pieceIndex[move->to];
    pieceIndex[move->to] = 0;
    board[move->from] = board[move->to];
    board[move->to] = Empty;
    piece = board[move->from];
    if (IsKing(piece)) {
        kingSquare[toMove] = move->from;
    }
    /* Promotion */
    if (IsPromotionMove(move->type)) {
        material[toMove] -= pieceValue[board[move->from]];
        board[move->from] = Pawn | toMove;
        material[toMove] += pieceValue[board[move->from]];
        pieces[toMove][pieceIndex[move->from]].type = Pawn | toMove;
        GetEvalTable(table, toMove, piece);
        positionalValue[toMove] -= table[move->to] -
            pawnEvalTable[toMove][move->to];
        piece = Pawn | toMove;
    }
    /* Castling */
    if (IsShortCastleMove(move->type)) {
        square2 = Square(H, toMove == White ? 1 : 8);
        square1 = Square(F, toMove == White ? 1 : 8);
        board[square2] = board[square1];
        board[square1] = Empty;
        pieces[toMove][pieceIndex[square1]].square = square2;
        pieceIndex[square2] = pieceIndex[square1];
        pieceIndex[square1] = 0;
        positionalValue[toMove] -= (rookEvalTable[toMove][square1] -
            rookEvalTable[toMove][square2]) + (incentive_castling);
    } else if (IsLongCastleMove(move->type)) {
        square2 = Square(A, toMove == White ? 1 : 8);
        square1 = Square(D, toMove == White ? 1 : 8);
        board[square2] = board[square1];
        board[square1] = Empty;
        pieces[toMove][pieceIndex[square1]].square = square2;
        pieceIndex[square2] = pieceIndex[square1];
        pieceIndex[square1] = 0;
        positionalValue[toMove] -= (rookEvalTable[toMove][square1] -
            rookEvalTable[toMove][square2]) + (incentive_castling/2);
    }
    /* En passant */
    if (IsEnPassantMove(move->type)) {
        square = pawnMoveTable[!toMove][move->to][0];
        material[!toMove] += pieceValue[move->capturedPiece];
        pieceIndex[square] = nrPieces[!toMove]++;
        pieces[!toMove][pieceIndex[square]].type = move->capturedPiece;
        pieces[!toMove][pieceIndex[square]].square = square;
        board[square] = move->capturedPiece;
        positionalValue[!toMove] += pawnEvalTable[!toMove][square];
        /* Capture */
    } else if (IsCaptureMove(move->type)) {
        material[!toMove] += pieceValue[move->capturedPiece];
        pieceIndex[move->to] = nrPieces[!toMove]++;
        pieces[!toMove][pieceIndex[move->to]].type = move->capturedPiece;
        pieces[!toMove][pieceIndex[move->to]].square = move->to;
        board[move->to] = move->capturedPiece;
        GetEvalTable(table, !toMove, move->capturedPiece);
        positionalValue[!toMove] += (table[move->to]) + (incentive_capture);
    }
    GetEvalTable(table, toMove, piece);
    positionalValue[toMove] -= table[move->to] - table[move->from];
}                               /* UndoMove */


/*----------------------------------------------------------------------
 | CheckRedundancies						940427
 |
 | Checks if the board, pieces and pieceIndex are consistent.
 +----------------------------------------------------------------------*/
static void     CheckRedundancies(void)
{
    Signed2         i,
                    j;
    BoardIndexType  square;
    char            s[MaxCommandLength];

    for (i = A; i <= H; i++) {
        for (j = 1; j <= 8; j++) {
            square = Square(i, j);
            SPrintSquare(s, square);
            if (!IsEmpty(board[square])) {
                if (pieceIndex[square] >= nrPieces[Color(board[square])]) {
                    printf("Error (in nrPieces on square): %s\n", s);
                }
                if (pieces[Color(board[square])][pieceIndex[square]].type
                    != board[square]) {
                    printf("Error (in type on square): %s\n", s);
                }
                if (pieces[Color(board[square])][pieceIndex[square]].square
                    != square) {
                    printf("Error (in square on square): %s\n", s);
                }
            }
        }
    }
}                               /* CheckRedundancies */




/*----------------------------------------------------------------------
 | QUIES							940513
 |
 | Contains all quiescence-search functions.
 +----------------------------------------------------------------------*/


static void     GenerateQuiesMoves(MoveType ** list, Unsigned1 * nrMoves);
static void     GeneratePawnQuiesMoves(BoardIndexType from, MoveType * list,
                                                       Unsigned1 * nrMoves);
static void     GenerateKnightQuiesMoves(BoardIndexType from, MoveType * list,
                                                       Unsigned1 * nrMoves);
static void     GenerateBishopQuiesMoves(BoardIndexType from, MoveType * list,
                                                       Unsigned1 * nrMoves);
static void     GenerateRookQuiesMoves(BoardIndexType from, MoveType * list,
                                                       Unsigned1 * nrMoves);
static void     GenerateKingQuiesMoves(BoardIndexType from, MoveType * list,
                                                       Unsigned1 * nrMoves);


/*----------------------------------------------------------------------
 | Quiescence.							940509
 |
 | Quiescence search.
 +----------------------------------------------------------------------*/
ValueType
Quiescence(ValueType alpha, ValueType beta, PathType ** bestPath,
           Signed1 ttDepth, ValueType ttValue, Unsigned1 flag,
           Unsigned4 ttNodes)
{
    ValueType       bestValue,
                    value;
    Unsigned1       nrMoves;
    MoveType       *moveList;
    PathType       *tempPath;
    Signed2         i;
    MoveType        refMove;

    
    bestValue = Evaluate(ttDepth, ttValue, flag, ttNodes);
    
  
    
    if (bestValue >= beta) {
        ++nrLeafNodes;
        ++nrTotalNodes;
        FreePath(*bestPath);
        *bestPath = NULL;
        return (bestValue);
    }
    if (bestValue > alpha) {
        alpha = bestValue;
    }
    GenerateQuiesMoves(&moveList, &nrMoves);
    if (nrMoves == 0) {         /* (stale)mate already recognized in
                                 * Evaluate() */
        ++nrLeafNodes;
        ++nrTotalNodes;
        FreePath(*bestPath);
        *bestPath = NULL;
        return (bestValue);
    }
    ++nrInternalNodes;
    ++nrQuiesNodes;
    ++nrTotalNodes;

    /* Try refutation table move first */
    if (useRefTable && *bestPath != NULL) {
        refMove = (*bestPath)->move;
        DoMove(&refMove);
        value = -Quiescence(-beta, -alpha, &((*bestPath)->next), -2, 0, 0, 0);
        UndoMove();
        if (value <= bestValue) {
            FreePath(*bestPath);
            *bestPath = NULL;
        } else {
            bestValue = value;
            if (bestValue >= beta) {
                goto BetaCutOff;
            }
            if (bestValue > alpha) {
                alpha = bestValue;
            }
        }
    } else {
        refMove.from = 0;       /* no refutation table move */
        FreePath(*bestPath);
        *bestPath = NULL;
    }

    /* Construct heap */
    for (i = nrMoves / 2 - 1; i > 0; i--) {
        SiftDown(moveList, (Unsigned1) i, (Unsigned1) (nrMoves - 1));
    }
    for (i = nrMoves - 1; i >= 0; i--) {
        if (i != 0) {           /* Put best move above in list */
            SiftDown(moveList, (Unsigned1) 0, (Unsigned1) i);
        }
        if (EqualMoves(&(moveList[0]), &refMove)) {
            goto Next;
        }
        DoMove(&(moveList[0]));
        tempPath = NULL;
        value = -Quiescence(-beta, -alpha, &tempPath, -2, 0, 0, 0);
        UndoMove();
        if (value > bestValue) {
            bestValue = value;
            FreePath(*bestPath);
            AllocatePathMove(*bestPath);
            SPrintMove((*bestPath)->moveString, moveList[0]);
            (*bestPath)->move = moveList[0];
            (*bestPath)->next = tempPath;
            if (bestValue >= beta) {
                goto BetaCutOff;
            }
            if (bestValue > alpha) {
                alpha = bestValue;
            }
        } else {
            FreePath(tempPath);
        }
Next:
        if (i != 0) {
            moveList[0] = moveList[i];
        }
    }                           /* for */
BetaCutOff:
    FreeMoveList(moveList);
    return (bestValue);
}                               /* Quiescence */


/*----------------------------------------------------------------------
 | GenerateQuiesMoves						940513
 |
 | Generates all legal quiescence moves.
 +----------------------------------------------------------------------*/
static void     GenerateQuiesMoves(MoveType ** moveList, Unsigned1 * nrMoves)
{
    PieceType      *pieceTable;
    Unsigned1       nr;
    SquareType      piece;
    Signed2         i;
    MoveType        list[MaxMoves];
   

    pieceTable = pieces[toMove];
    nr = nrPieces[toMove];

    *nrMoves = 0;
    /* already done in Evaluate() */
//	SearchForPinsAndCheck();  //JA 
    switch (nrCheck) {
    case 0:
        for (i = 0; i < nr; i++) {
            piece = pieceTable[i].type;
             
            if (IsPawn(piece)) {
                GeneratePawnQuiesMoves(pieceTable[i].square, list, nrMoves);
            } else if (IsKnight(piece) && !pinned[pieceTable[i].square]) {
                GenerateKnightQuiesMoves(pieceTable[i].square, list, nrMoves);
            } else if (IsKing(piece)) {
                GenerateKingQuiesMoves(pieceTable[i].square, list, nrMoves);
            } else {
                if (MovesDiagonal(piece)) {
                    GenerateBishopQuiesMoves(pieceTable[i].square, list, nrMoves);
                }
                if (MovesStraight(piece)) {
                    GenerateRookQuiesMoves(pieceTable[i].square, list, nrMoves);
                }
            }
        }                       /* for i */
        break;
    case 1:
        /* Capture check-giving piece, NOT with king */
        GenerateCaptureMoves(&(checkingPiece[0]), list, nrMoves);
        /* Interpose piece */
        if (checkingPiece[0].dir &&
            kingSquare[toMove] + checkingPiece[0].dir !=
            checkingPiece[0].square) {
            GenerateInterposingMoves(&(checkingPiece[0]), list, nrMoves);
        }
    case 2:
        /* Move king away, including trying to capture (one of) the
         * check-giving piece(s) */
        GenerateKingMoves(kingSquare[toMove], list, nrMoves);
        break;
    default:
        printf("Error (times in check): %d\n", nrCheck);
        //exit(0);
        return;
    }                           /* switch */
    if (*nrMoves) {
        AllocateMoveList(*moveList, *nrMoves);
        memcpy(*moveList, list, *nrMoves * sizeof(MoveType));
    }
    
   // nrGenerates++;
  //  nrMovesGenerated += *nrMoves;
    
  
 }                               


/* GenerateQuiesMoves */


/*----------------------------------------------------------------------
 | GeneratePawnQuiesMoves					940513
 |
 | Generates all legal pawn quiescence moves.
 +----------------------------------------------------------------------*/
static void     GeneratePawnQuiesMoves(BoardIndexType from, MoveType * list,
                                                       Unsigned1 * nrMoves)
{
    BoardIndexType  to;
    SquareType      piece;
    Unsigned1       dir;
    PieceType       attackingPiece;

  

    /* promotion moves */
    if (!pinned[from] || pinned[from] == Up || pinned[from] == Down) {
        to = pawnMoveTable[toMove][from][0];
        if (IsEmpty(board[to]) && OnSeventhRank(toMove, from)) {
            PutMoveInTable(from, to, 0, Queen | toMove, Promotion, list,
                           *nrMoves);
            PutMoveInTable(from, to, 0, Knight | toMove, Promotion, list,
                           *nrMoves);
            PutMoveInTable(from, to, 0, Rook | toMove, Promotion, list,
                           *nrMoves);
            PutMoveInTable(from, to, 0, Bishop | toMove, Promotion, list,
                           *nrMoves);
        }                       /* if promotion move */
    }                           /* if not pinned */
    /* capture moves */
    for (dir = 0; dir < 2; dir++) {
        if (!pinned[from] || pinned[from] == pawnCaptureDir[toMove][dir] ||
            pinned[from] == -pawnCaptureDir[toMove][dir]) {
            to = pawnCaptureTable[toMove][from][dir];
            if (to == epSquare[nrGamePlies]) {
                if (Rank(kingSquare[toMove]) != (toMove == White ? 5 : 4)) {
                    PutMoveInTable(from, to, Pawn | !toMove, 0,
                                   EnPassant | Capture, list, *nrMoves);
                } else {
                    /* remove pawns temporarily */
                    board[from] = Empty;
                    board[to + (toMove == White ? Down : Up)] = Empty;
                    if (!FindFirstPieceInDir((Unsigned1) MaxRookMoves,
                       rookTable[kingSquare[toMove]][2], &attackingPiece) ||
                        (attackingPiece.type != (Rook | !toMove) &&
                         attackingPiece.type != (Queen | !toMove))) {
                        if (!FindFirstPieceInDir((Unsigned1) MaxRookMoves,
                        rookTable[kingSquare[toMove]][3], &attackingPiece) ||
                            (attackingPiece.type != (Rook | !toMove) &&
                             attackingPiece.type != (Queen | !toMove))) {
                            PutMoveInTable(from, to, Pawn | !toMove, 0,
                                       EnPassant | Capture, list, *nrMoves);
                        }
                    }
                    /* Put pawns back */
                    board[from] = Pawn | toMove;
                    board[to + (toMove == White ? Down : Up)] = Pawn | !toMove;
                }
            } else {            /* no en-passant move */
                piece = board[to];
                if (piece && !IsEdge(piece) && !IsColor(piece, toMove)) {
                    if (OnSeventhRank(toMove, from)) {
                        PutMoveInTable(from, to, piece, Queen | toMove,
                                       Promotion | Capture, list, *nrMoves);
                        PutMoveInTable(from, to, piece, Knight | toMove,
                                       Promotion | Capture, list, *nrMoves);
                        PutMoveInTable(from, to, piece, Rook | toMove,
                                       Promotion | Capture, list, *nrMoves);
                        PutMoveInTable(from, to, piece, Bishop | toMove,
                                       Promotion | Capture, list, *nrMoves);
                    } else {
                        PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
                    }
                }               /* if enemy piece */
            }                   /* else */
        }                       /* if not pinned */
    }                           /* for dir */
}                               /* GeneratePawnQuiesMoves */


/*----------------------------------------------------------------------
 | GenerateKnightQuiesMoves					940513
 |
 | Generates all legal knight quiescence moves.
 +----------------------------------------------------------------------*/
static void     GenerateKnightQuiesMoves(BoardIndexType from, MoveType * list,
                                                         Unsigned1 * nrMoves)
{
    Signed2         i;
    BoardIndexType  to;
    SquareType      piece;

    
    for (i = 0; i < MaxKnightMoves; i++) {
        to = knightTable[from][i];
        if (!to) {
            break;
        }
        piece = board[to];
        /* capture moves only */
        if (!IsEmpty(piece) && !IsEdge(piece) && !IsColor(piece, toMove)) {
            PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
        }
    }
}                               /* GenerateKnightQuiesMoves */


/*----------------------------------------------------------------------
 | GenerateBishopQuiesMoves					940513
 |
 | Generates all legal bishop quiescence moves.
 +----------------------------------------------------------------------*/
static void     GenerateBishopQuiesMoves(BoardIndexType from, MoveType * list,
                                                         Unsigned1 * nrMoves)
{
    Signed2         i,
                    j;
    BoardIndexType  to;
    SquareType      piece;

    
    for (i = 0; i < 4; i++) {
        if (!pinned[from] || pinned[from] == bishopDir[i] ||
            pinned[from] == -bishopDir[i]) {
            for (j = 0; j < MaxBishopMoves; j++) {
                to = bishopTable[from][i][j];
                if (!to) {
                    break;
                }
                piece = board[to];
                if (IsEmpty(piece)) {
                    continue;
                }
                /* capture moves only */
                if (!IsEdge(piece) && !IsColor(piece, toMove)) {
                    PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
                    break;
                } else {
                    break;
                }
            }                   /* for j */
        }                       /* if not pinned */
    }                           /* for i */
}                               /* GenerateBishopQuiesMoves */


/*----------------------------------------------------------------------
 | GenerateRookQuiesMoves					940513
 |
 | Generates all legal quiescence rook moves.
 +----------------------------------------------------------------------*/
static void     GenerateRookQuiesMoves(BoardIndexType from, MoveType * list,
                                                       Unsigned1 * nrMoves)
{
    Signed2         i,
                    j;
    BoardIndexType  to;
    SquareType      piece;
 
    
    for (i = 0; i < 4; i++) {
        if (!pinned[from] || pinned[from] == rookDir[i] ||
            pinned[from] == -rookDir[i]) {
            for (j = 0; j < MaxRookMoves; j++) {
                to = rookTable[from][i][j];
                if (!to) {
                    break;
                }
                piece = board[to];
                if (IsEmpty(piece)) {
                    continue;
                }
                /* capture moves only */
                if (!IsEdge(piece) && !IsColor(piece, toMove)) {
                    PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
                    break;
                } else {
                    break;
                }
            }                   /* for j */
        }                       /* if not pinned */
    }                           /* for i */
}                               /* GenerateRookQuiesMoves */


/*----------------------------------------------------------------------
 | GenerateKingQuiesMoves					940513
 |
 | Generates all legal king quiescence moves.
 +----------------------------------------------------------------------*/
static void     GenerateKingQuiesMoves(BoardIndexType from, MoveType * list,
                                                       Unsigned1 * nrMoves)
{
    Signed2         i;
    BoardIndexType  to;
    SquareType      piece;

  //  SearchForPinsAndCheck(); 
    
    /* Remove king temporarily in view of Attacked() */
    board[kingSquare[toMove]] = Empty;
    for (i = 0; i < 4; i++) {
        to = rookTable[from][i][0];
        if (!to) {
            continue;
        }
        piece = board[to];
        /* capture moves only */
        if (!IsEmpty(piece) && !IsEdge(piece) && !IsColor(piece, toMove)) {
            if (!IsCheckingDir(-rookDir[i]) &&
                !Attacked(to, (SquareType) ! toMove)) {
                PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
            }
        }
    }
    for (i = 0; i < 4; i++) {
        to = bishopTable[from][i][0];
        if (!to) {
            continue;
        }
        piece = board[to];
        /* capture moves only */
        if (!IsEmpty(piece) && !IsEdge(piece) && !IsColor(piece, toMove)) {
            if (!IsCheckingDir(-bishopDir[i]) &&
                !Attacked(to, (SquareType) ! toMove)) {
                PutMoveInTable(from, to, piece, 0, Capture, list, *nrMoves);
            }
        }
    }
    board[kingSquare[toMove]] = King | toMove;
}                               /* GenerateKingQuiesMoves */





/*----------------------------------------------------------------------
 | SEARCH                                                    940608
 |
 | Contains all search functions.
 +----------------------------------------------------------------------*/


void            PreProcessing(void)
{
    Signed2         i,
                    j;
    BoardIndexType  square;

    ClearPieceSquareTables();
    for (i = A; i <= H; i++) {
        for (j = 1; j <= 8; j++) {
            square = Square(i, j);
            IScore = 0;
        
            if (!ENDGAME_REACHED) {
            pawnEvalTable[White][square]   = PawnTable[square] + 6 * (9 - j);
            pawnEvalTable[Black][square]   = PawnTable[square] + 6 * j;
            
            knightEvalTable[White][square] = knightEvalTable[Black][square] = KnightTable[square];
           
            bishopEvalTable[White][square] = bishopEvalTable[Black][square] = BishopTable[square];
            
            rookEvalTable[White][square]   = rookEvalTable[Black][square]   = RookTable[square];
            
            queenEvalTable[White][square]  = queenEvalTable[Black][square]  = QueenTable[square];
            
            
            kingEvalTable[White][square]   = kingEvalTable[Black][square]   = KingTable[square];  
            
            if (computer == White) {
            
            IScore += (pawnEvalTable[White][square]     +  knightEvalTable[White][square] +
                       bishopEvalTable[White][square]   +  rookEvalTable[White][square]   +
                       queenEvalTable[White][square]    +  kingEvalTable[White][square]) ;
                       }
                       
            if (computer == Black) {
            
            IScore += (pawnEvalTable[Black][square]     +  knightEvalTable[Black][square] +
                       bishopEvalTable[Black][square]   +  rookEvalTable[Black][square]   +
                       queenEvalTable[Black][square]    +  kingEvalTable[Black][square]) ;
                       }           
                       
                       
                
            }else{
            
            pawnEvalTable[White][square]   = PawnTable_Endgame[square] + 6 * j;
            pawnEvalTable[Black][square]   = PawnTable_Endgame[square] + 6 * (9 - j);
            
            knightEvalTable[White][square] = knightEvalTable[Black][square] = KnightTable[square];
                                 
            bishopEvalTable[White][square] = bishopEvalTable[Black][square] = BishopTable_Endgame[square];
                      
            rookEvalTable[White][square]   = rookEvalTable[Black][square]   = RookTable_Endgame[square];
           
            queenEvalTable[White][square]  = queenEvalTable[Black][square]  = QueenTable_Endgame[square];
            
            kingEvalTable[White][square]   = kingEvalTable[Black][square]  =  KingTable_Endgame[square];                
           
           
             if (computer == White) {
            
            IScore += (pawnEvalTable[White][square]     +  knightEvalTable[White][square] +
                       bishopEvalTable[White][square]   +  rookEvalTable[White][square]   +
                       queenEvalTable[White][square]    +  kingEvalTable[White][square]) ;
                       }
            
            
            if (computer == Black) {
            
            IScore += (pawnEvalTable[Black][square]     +  knightEvalTable[Black][square] +
                       bishopEvalTable[Black][square]   +  rookEvalTable[Black][square]   +
                       queenEvalTable[Black][square]    +  kingEvalTable[Black][square]) ;
                       }
           
           
            }
            
           
        }
    }
    InitPositionalValue();
}                               /* PreProcessing */


Signed2
ItIsADraw(void)
{
    Signed2         i;

    if (nrGamePlies - startHashIndex[nrGamePlies] >= 100) { // 50 move rule
        return (true);
    }
    for (i = (Signed2) nrGamePlies - 2; i >= (Signed2) startHashIndex[nrGamePlies]; // 3 fold rep rule
         i -= 2) {
        if (HashEqual(hashValue[nrGamePlies], hashValue[i])) {
            return (true);
        }
    }
    return (false);
}                               /* ItIsADraw */










////////////////////////////////// END //////////////////////////////////



