Home Previous Bottom Next

Writing a chess program in 99 steps


15  Mate and draw detection

From this point onwards, most improvements are  aimed at improving the search algorithm.  However, before we continue doing that, there are some loose ends that need to be attended. First, we are going to detect if the game has ended due to a checkmate or draw.  Draws can be due to:
     1) insufficient material to mate
          1a) king versus king
          1b) king + knight versus king
          1c) kings with one or more bishops, and all bishops on the same color
     2) stalemate
     3) a threefold repetition of the position (see section 16)
     4) the 50-move rule
All, except the 'threefold repetition', will be implemented now.  It basically means that you can start playing a real game (using the command 'go'), and the program can also play a game versus itself (using the 'cc' command).  If the game has ended, the program will stop playing and show the result.  Note that, when using the cc command, you can interrupt the game by hitting any key.

Checkmate / stalemate detection

Detection of checkmate and stalemate can be done at the end of the search, after all moves have been tried. If no legal moves were found, then it must be either checkmate or stalemate (depending on if our own king is attacked or not), and we return the corresponding score.  The checkmate score is slightly modified so that the program will prefer the shortest line of play leading to checkmate:

       if (!movesfound)
       {
              if (isOwnKingAttacked())  return (-CHECKMATESCORE+ply-1);
              else  return (STALEMATESCORE);
       }

50-move rule

The fiftyMove counter is kept up to date in the board structure, so we just have to add this test at the end of the search function, after all moves have been tried:

if (fiftyMove >= 100) return DRAWSCORE;

Insufficient material

Insufficient material to checkmate is detected in the evaluation function.
          1a) king versus king
          1b) king + knight versus king
          1c) 2 kings with one or more bishops, and all bishops on the same color
In case any of these three situations exists, the evaluation function will return a draw score.

Apart from above tests, there is also a function board::isEndOfgame() that is called before and after think(), to see if the current position is an 'end-of-game' position, in which case we don't start the search and just display the result.

Move disambiguation

I think it's important to give quality information to the user. This includes showing current search speed (in knods/s), total number of nodes visited, total time searched, the currently searched root move, and last but not least the complete principal variation (in SAN notation). It just makes the search much easier to follow for chess players.  Our algorithm will also take care of disambiguation.  Ambiguity happens if, for example, two rooks (one on a5, one on e1) can move to the same square, in this case e5.  Displaying this move as 'Re5' is not very helpful, because it's not telling us which rook is moving to e5.  Depending on the location of the other rooks, the move will either be displayed as 'Rae5', 'R1e5', or 'Ra5e5' (in case there are three rooks that can move to e5). The SAN disambiguation rules are followed.
 

step 59: globals.h

#ifndef WINGLET_GLOBALS_H
#define WINGLET_GLOBALS_H
 
#include "defines.h"
#include "board.h"
 
char CMD_BUFF[MAX_CMD_BUFF];
int CMD_BUFF_COUNT = 0;
 
Board board;
 
extern const int A8 = 56; extern const int B8 = 57; extern const int C8 = 58; extern const int D8 = 59;
extern const int E8 = 60; extern const int F8 = 61; extern const int G8 = 62; extern const int H8 = 63;
extern const int A7 = 48; extern const int B7 = 49; extern const int C7 = 50; extern const int D7 = 51;
extern const int E7 = 52; extern const int F7 = 53; extern const int G7 = 54; extern const int H7 = 55;
extern const int A6 = 40; extern const int B6 = 41; extern const int C6 = 42; extern const int D6 = 43;
extern const int E6 = 44; extern const int F6 = 45; extern const int G6 = 46; extern const int H6 = 47;
extern const int A5 = 32; extern const int B5 = 33; extern const int C5 = 34; extern const int D5 = 35;
extern const int E5 = 36; extern const int F5 = 37; extern const int G5 = 38; extern const int H5 = 39;
extern const int A4 = 24; extern const int B4 = 25; extern const int C4 = 26; extern const int D4 = 27;
extern const int E4 = 28; extern const int F4 = 29; extern const int G4 = 30; extern const int H4 = 31;
extern const int A3 = 16; extern const int B3 = 17; extern const int C3 = 18; extern const int D3 = 19;
extern const int E3 = 20; extern const int F3 = 21; extern const int G3 = 22; extern const int H3 = 23;
extern const int A2 =  8; extern const int B2 =  9; extern const int C2 = 10; extern const int D2 = 11;
extern const int E2 = 12; extern const int F2 = 13; extern const int G2 = 14; extern const int H2 = 15;
extern const int A1 =  0; extern const int B1 =  1; extern const int C1 =  2; extern const int D1 =  3;
extern const int E1 =  4; extern const int F1 =  5; extern const int G1 =  6; extern const int H1 =  7;
 
const char* SQUARENAME[64] = {"a1","b1","c1","d1","e1","f1","g1","h1",
                              "a2","b2","c2","d2","e2","f2","g2","h2",
                              "a3","b3","c3","d3","e3","f3","g3","h3",
                              "a4","b4","c4","d4","e4","f4","g4","h4",
                              "a5","b5","c5","d5","e5","f5","g5","h5",
                              "a6","b6","c6","d6","e6","f6","g6","h6",
                              "a7","b7","c7","d7","e7","f7","g7","h7",
                              "a8","b8","c8","d8","e8","f8","g8","h8"};
 
extern const int FILES[64] = {
       1, 2, 3, 4, 5, 6, 7, 8,
       1, 2, 3, 4, 5, 6, 7, 8,
       1, 2, 3, 4, 5, 6, 7, 8,
       1, 2, 3, 4, 5, 6, 7, 8,
       1, 2, 3, 4, 5, 6, 7, 8,
       1, 2, 3, 4, 5, 6, 7, 8,
       1, 2, 3, 4, 5, 6, 7, 8,
       1, 2, 3, 4, 5, 6, 7, 8
};
 
extern const int RANKS[64] = {
       1, 1, 1, 1, 1, 1, 1, 1,
       2, 2, 2, 2, 2, 2, 2, 2,
       3, 3, 3, 3, 3, 3, 3, 3,
       4, 4, 4, 4, 4, 4, 4, 4,
       5, 5, 5, 5, 5, 5, 5, 5,
       6, 6, 6, 6, 6, 6, 6, 6,
       7, 7, 7, 7, 7, 7, 7, 7,
       8, 8, 8, 8, 8, 8, 8, 8
};
 
// Identifier of next move:
extern const unsigned char WHITE_MOVE  = 0;
extern const unsigned char BLACK_MOVE  = 1;
 
// Piece identifiers, 4 bits each.
// Usefull bitwise properties of this numbering scheme:
// white = 0..., black = 1..., sliding = .1.., nonsliding = .0..
// rank/file sliding pieces = .11., diagonally sliding pieces = .1.1
// pawns and kings (without color bits), are < 3
// major pieces (without color bits set), are > 5
// minor and major pieces (without color bits set), are > 2
extern const unsigned char EMPTY = 0;                //  0000
extern const unsigned char WHITE_PAWN = 1;           //  0001
extern const unsigned char WHITE_KING = 2;           //  0010
extern const unsigned char WHITE_KNIGHT = 3;         //  0011
extern const unsigned char WHITE_BISHOP =  5;        //  0101
extern const unsigned char WHITE_ROOK = 6;           //  0110
extern const unsigned char WHITE_QUEEN = 7;          //  0111
extern const unsigned char BLACK_PAWN = 9;           //  1001
extern const unsigned char BLACK_KING = 10;          //  1010
extern const unsigned char BLACK_KNIGHT = 11;        //  1011
extern const unsigned char BLACK_BISHOP = 13;        //  1101
extern const unsigned char BLACK_ROOK = 14;          //  1110
extern const unsigned char BLACK_QUEEN = 15;         //  1111
 
const char* PIECENAMES[16] = {"  ","P ","K ","N ","  ","B ","R ","Q ",
                              "  ","P*","K*","N*","  ","B*","R*","Q*"};
const char* PIECECHARS[16] = {" "," ","K","N"," ","B","R","Q"," "," ","K","N"," ","B","R","Q"};
 
BitMap BITSET[64];
int BOARDINDEX[9][9]; // index 0 is not used, only 1..8.
 
// Value of material, in centipawns:
extern const int PAWN_VALUE = 100;
extern const int KNIGHT_VALUE = 300;
extern const int BISHOP_VALUE = 300;
extern const int ROOK_VALUE = 500;
extern const int QUEEN_VALUE = 900;
extern const int KING_VALUE = 9999;
extern const int CHECK_MATE = KING_VALUE;
 
// used in Eugene Nalimov's bitScanReverse
int MS1BTABLE[256];
 
// Attack tables:
BitMap WHITE_PAWN_ATTACKS[64];
BitMap WHITE_PAWN_MOVES[64];
BitMap WHITE_PAWN_DOUBLE_MOVES[64];
BitMap BLACK_PAWN_ATTACKS[64];
BitMap BLACK_PAWN_MOVES[64];
BitMap BLACK_PAWN_DOUBLE_MOVES[64];
BitMap KNIGHT_ATTACKS[64];
BitMap KING_ATTACKS[64];
BitMap RANK_ATTACKS[64][64];      // 32KB
BitMap FILE_ATTACKS[64][64];      // 32KB
BitMap DIAGA8H1_ATTACKS[64][64];  // 32KB
BitMap DIAGA1H8_ATTACKS[64][64];  // 32KB
 
// Move generator shift for ranks:
extern const int RANKSHIFT[64] = {
        1,  1,  1,  1,  1,  1,  1,  1,
        9,  9,  9,  9,  9,  9,  9,  9,
       17, 17, 17, 17, 17, 17, 17, 17, 
       25, 25, 25, 25, 25, 25, 25, 25,
       33, 33, 33, 33, 33, 33, 33, 33,
       41, 41, 41, 41, 41, 41, 41, 41,
       49, 49, 49, 49, 49, 49, 49, 49,
       57, 57, 57, 57, 57, 57, 57, 57
};
 
// Move generator magic multiplication numbers for files:
extern const BitMap _FILEMAGICS[8] = {
       0x8040201008040200,
       0x4020100804020100,
       0x2010080402010080,
       0x1008040201008040,
       0x0804020100804020,
       0x0402010080402010,
       0x0201008040201008,
       0x0100804020100804
};
 
// Move generator magic multiplication numbers for diagonals:
extern const BitMap _DIAGA8H1MAGICS[15] = {
       0x0,
       0x0,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0080808080808080,
       0x0040404040404040,
       0x0020202020202020,
       0x0010101010101010,
       0x0008080808080808,
       0x0,
       0x0
};
 
// Move generator magic multiplication numbers for diagonals:
extern const BitMap _DIAGA1H8MAGICS[15] = {
       0x0,
       0x0,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x0101010101010100,
       0x8080808080808000,
       0x4040404040400000,
       0x2020202020000000,
       0x1010101000000000,
       0x0808080000000000,
       0x0,
       0x0
};
 
// Move generator 6-bit masking and magic multiplication numbers:
BitMap RANKMASK[64];
BitMap FILEMASK[64];
BitMap FILEMAGIC[64];
BitMap DIAGA8H1MASK[64];
BitMap DIAGA8H1MAGIC[64];
BitMap DIAGA1H8MASK[64];
BitMap DIAGA1H8MAGIC[64];
 
// We use one generalized sliding attacks array: [8 squares][64 states]
// the unsigned char (=8 bits) contains the attacks for a rank, file or diagonal
unsigned char GEN_SLIDING_ATTACKS[8][64];
 
// Used for castling:
unsigned char CANCASTLEOO = 1;
unsigned char CANCASTLEOOO = 2;
BitMap maskEG[2];
BitMap maskFG[2];
BitMap maskBD[2];
BitMap maskCE[2];
unsigned int WHITE_OOO_CASTL;
unsigned int BLACK_OOO_CASTL;
unsigned int WHITE_OO_CASTL;
unsigned int BLACK_OO_CASTL;
 
int ICAPT;
int IEP;
int IPROM;
int ICASTLOO;
int ICASTLOOO;
int ICHECK;
 
// Evaluation scores start here, all scores are in centipawns.
// If there are scoring data that is supposed to be symmetrical (i.e. same for BLACK & WHITE),
// then only the data for WHITE is supplied, and data for BLACK is calculated in dataInit().
// This is done to make data entry easier, eliminate typos and guarantuee symmetry.
//
// MIRRORED:
// Some scoring arrays are supplied MIRRORED, i.e. starting with the last rank (see the comments below).
// They are mirrored back in the right order in dataInit().
// This is only done to make data entry easier, because you can enter the scoring data as if you're
// looking at the chess board from White's point of perspective.
 
int PENALTY_DOUBLED_PAWN          = 10;
int PENALTY_ISOLATED_PAWN         = 20;
int PENALTY_BACKWARD_PAWN         =  8;
int BONUS_PASSED_PAWN             = 20;
int BONUS_BISHOP_PAIR             = 10;
int BONUS_ROOK_BEHIND_PASSED_PAWN = 20;
int BONUS_ROOK_ON_OPEN_FILE       = 20;
int BONUS_TWO_ROOKS_ON_OPEN_FILE  = 20;
 
int BONUS_PAWN_SHIELD_STRONG = 9;
int BONUS_PAWN_SHIELD_WEAK = 4;
 
int PAWN_OWN_DISTANCE[8] =           { 0,   8,  4,  2,  0,  0,  0,  0 };
int PAWN_OPPONENT_DISTANCE[8] =      { 0,   2,  1,  0,  0,  0,  0,  0 };
int KNIGHT_DISTANCE[8] =             { 0,   4,  4,  0,  0,  0,  0,  0 };
int BISHOP_DISTANCE[8] =             { 0,   5,  4,  3,  2,  1,  0,  0 };
int ROOK_DISTANCE[8] =               { 0,   7,  5,  4,  3,  0,  0,  0 };
int QUEEN_DISTANCE[8] =              { 0,  10,  8,  5,  4,  0,  0,  0 };
 
// *** This array is MIRRORED                          ***
// *** You can enter the scoring data as if you're     ***
// *** looking at the chess board from white's point   ***
// *** of perspective. Lower left corner is square a1: ***
int PAWNPOS_W[64] = {
         0,   0,   0,   0,   0,   0,   0,   0,
         5,  10,  15,  20,  20,  15,  10,   5,
         4,   8,  12,  16,  16,  12,   8,   4,
         3,   6,   9,  12,  12,   9,   6,   3,
         2,   4,   6,   8,   8,   6,   4,   2,
         1,   2,   3, -10, -10,   3,   2,   1,
         0,   0,   0, -40, -40,   0,   0,   0,
         0,   0,   0,   0,   0,   0,   0,   0
};
 
// *** This array is MIRRORED                          ***
// *** You can enter the scoring data as if you're     ***
// *** looking at the chess board from white's point   ***
// *** of perspective. Lower left corner is square a1: ***
int KNIGHTPOS_W[64] = {
       -10, -10, -10, -10, -10, -10, -10, -10,
       -10,   0,   0,   0,   0,   0,   0, -10,
       -10,   0,   5,   5,   5,   5,   0, -10,
       -10,   0,   5,  10,  10,   5,   0, -10,
       -10,   0,   5,  10,  10,   5,   0, -10,
       -10,   0,   5,   5,   5,   5,   0, -10,
       -10,   0,   0,   0,   0,   0,   0, -10,
       -10, -30, -10, -10, -10, -10, -30, -10
};
 
// *** This array is MIRRORED                          ***
// *** You can enter the scoring data as if you're     ***
// *** looking at the chess board from white's point   ***
// *** of perspective. Lower left corner is square a1: ***
int BISHOPPOS_W[64] = {
       -10, -10, -10, -10, -10, -10, -10, -10,
       -10,   0,   0,   0,   0,   0,   0, -10,
       -10,   0,   5,   5,   5,   5,   0, -10,
       -10,   0,   5,  10,  10,   5,   0, -10,
       -10,   0,   5,  10,  10,   5,   0, -10,
       -10,   0,   5,   5,   5,   5,   0, -10,
       -10,   0,   0,   0,   0,   0,   0, -10,
       -10, -10, -20, -10, -10, -20, -10, -10
};
 
// *** This array is MIRRORED                          ***
// *** You can enter the scoring data as if you're     ***
// *** looking at the chess board from white's point   ***
// *** of perspective. Lower left corner is square a1: ***
int ROOKPOS_W[64] = {
      0,  0,  0,  0,   0,  0,  0,   0,
     15, 15, 15, 15,  15, 15, 15,  15,
      0,  0,  0,  0,   0,  0,  0,   0,
      0,  0,  0,  0,   0,  0,  0,   0,
      0,  0,  0,  0,   0,  0,  0,   0,
      0,  0,  0,  0,   0,  0,  0,   0,
      0,  0,  0,  0,   0,  0,  0,   0,
    -10,  0,  0, 10,  10,  0,  0, -10
};
 
// *** This array is MIRRORED                          ***
// *** You can enter the scoring data as if you're     ***
// *** looking at the chess board from white's point   ***
// *** of perspective. Lower left corner is square a1: ***
int QUEENPOS_W[64] = {
       -10, -10, -10, -10, -10, -10, -10, -10,
       -10,   0,   0,   0,   0,   0,   0, -10,
       -10,   0,   5,   5,   5,   5,   0, -10,
       -10,   0,   5,  10,  10,   5,   0, -10,
       -10,   0,   5,  10,  10,   5,   0, -10,
       -10,   0,   5,   5,   5,   5,   0, -10,
       -10,   0,   0,   0,   0,   0,   0, -10,
       -10, -10, -20, -10, -10, -20, -10, -10
};
 
// *** This array is MIRRORED                          ***
// *** You can enter the scoring data as if you're     ***
// *** looking at the chess board from white's point   ***
// *** of perspective. Lower left corner is square a1: ***
int KINGPOS_W[64]  = {
       -40, -40, -40, -40, -40, -40, -40, -40,
       -40, -40, -40, -40, -40, -40, -40, -40,
       -40, -40, -40, -40, -40, -40, -40, -40,
       -40, -40, -40, -40, -40, -40, -40, -40,
       -40, -40, -40, -40, -40, -40, -40, -40,
       -40, -40, -40, -40, -40, -40, -40, -40,
       -20, -20, -20, -20, -20, -20, -20, -20,
         0,  20,  40, -20,   0, -20,  40,  20
};
 
// *** This array is MIRRORED                          ***
// *** You can enter the scoring data as if you're     ***
// *** looking at the chess board from white's point   ***
// *** of perspective. Lower left corner is square a1: ***
int KINGPOS_ENDGAME_W[64] = {
         0,  10,  20,  30,  30,  20,  10,   0,
        10,  20,  30,  40,  40,  30,  20,  10,
        20,  30,  40,  50,  50,  40,  30,  20,
        30,  40,  50,  60,  60,  50,  40,  30,
        30,  40,  50,  60,  60,  50,  40,  30,
        20,  30,  40,  50,  50,  40,  30,  20,
        10,  20,  30,  40,  40,  30,  20,  10,
         0,  10,  20,  30,  30,  20,  10,   0
};
 
int MIRROR[64] = {
        56,  57,  58,  59,  60,  61,  62,  63,
        48,  49,  50,  51,  52,  53,  54,  55,
        40,  41,  42,  43,  44,  45,  46,  47,
        32,  33,  34,  35,  36,  37,  38,  39,
        24,  25,  26,  27,  28,  29,  30,  31,
        16,  17,  18,  19,  20,  21,  22,  23,
         8,   9,  10,  11,  12,  13,  14,  15, 
         0,   1,   2,   3,   4,   5,   6,   7
};
 
int DISTANCE[64][64];
int PAWNPOS_B[64];
int KNIGHTPOS_B[64];
int BISHOPPOS_B[64];
int ROOKPOS_B[64];
int QUEENPOS_B[64];
int KINGPOS_B[64];
int KINGPOS_ENDGAME_B[64];
BitMap PASSED_WHITE[64];
BitMap PASSED_BLACK[64];
BitMap ISOLATED_WHITE[64];
BitMap ISOLATED_BLACK[64];
BitMap BACKWARD_WHITE[64];
BitMap BACKWARD_BLACK[64];
BitMap KINGSHIELD_STRONG_W[64];
BitMap KINGSHIELD_STRONG_B[64];
BitMap KINGSHIELD_WEAK_W[64];
BitMap KINGSHIELD_WEAK_B[64];
BitMap WHITE_SQUARES;
BitMap BLACK_SQUARES;
 
// Search parameters start here:
int LARGE_NUMBER = KING_VALUE + 1;
int CHECKMATESCORE = KING_VALUE;
int STALEMATESCORE = 0;
int DRAWSCORE = 0;
Move NOMOVE;
 
#endif

 

step 60: extglobals.h

#ifndef WINGLET_EXTGLOBALS_H
#define WINGLET_EXTGLOBALS_H
 
#include "defines.h"
#include "board.h"
 
extern char CMD_BUFF[];
extern int CMD_BUFF_COUNT;
 
extern Board board;
 
extern const int A8; extern const int B8; extern const int C8; extern const int D8;
extern const int E8; extern const int F8; extern const int G8; extern const int H8;
extern const int A7; extern const int B7; extern const int C7; extern const int D7;
extern const int E7; extern const int F7; extern const int G7; extern const int H7;
extern const int A6; extern const int B6; extern const int C6; extern const int D6;
extern const int E6; extern const int F6; extern const int G6; extern const int H6;
extern const int A5; extern const int B5; extern const int C5; extern const int D5;
extern const int E5; extern const int F5; extern const int G5; extern const int H5;
extern const int A4; extern const int B4; extern const int C4; extern const int D4;
extern const int E4; extern const int F4; extern const int G4; extern const int H4;
extern const int A3; extern const int B3; extern const int C3; extern const int D3;
extern const int E3; extern const int F3; extern const int G3; extern const int H3;
extern const int A2; extern const int B2; extern const int C2; extern const int D2;
extern const int E2; extern const int F2; extern const int G2; extern const int H2;
extern const int A1; extern const int B1; extern const int C1; extern const int D1;
extern const int E1; extern const int F1; extern const int G1; extern const int H1;
 
extern const char* SQUARENAME[];
 
extern const int FILES[];
extern const int RANKS[];
 
extern const unsigned char WHITE_MOVE;
extern const unsigned char BLACK_MOVE;
 
extern const unsigned char EMPTY;
extern const unsigned char WHITE_KNIGHT;
extern const unsigned char WHITE_PAWN;
extern const unsigned char WHITE_KING;
extern const unsigned char WHITE_BISHOP;
extern const unsigned char WHITE_ROOK;
extern const unsigned char WHITE_QUEEN;
extern const unsigned char BLACK_KNIGHT;
extern const unsigned char BLACK_PAWN;
extern const unsigned char BLACK_KING;
extern const unsigned char BLACK_BISHOP;
extern const unsigned char BLACK_ROOK;
extern const unsigned char BLACK_QUEEN;
 
extern const char* PIECENAMES[];
extern const char* PIECECHARS[];
 
extern BitMap BITSET[];
extern int BOARDINDEX[9][9];
 
extern const int PAWN_VALUE;
extern const int KNIGHT_VALUE;
extern const int BISHOP_VALUE;
extern const int ROOK_VALUE;
extern const int QUEEN_VALUE;
extern const int KING_VALUE;
extern const int CHECK_MATE;
 
extern int MS1BTABLE[];
 
extern BitMap WHITE_PAWN_ATTACKS[];
extern BitMap WHITE_PAWN_MOVES[];
extern BitMap WHITE_PAWN_DOUBLE_MOVES[];
extern BitMap BLACK_PAWN_ATTACKS[];
extern BitMap BLACK_PAWN_MOVES[];
extern BitMap BLACK_PAWN_DOUBLE_MOVES[];
extern BitMap KNIGHT_ATTACKS[];
extern BitMap KING_ATTACKS[];
extern BitMap RANK_ATTACKS[64][64];
extern BitMap FILE_ATTACKS[64][64];
extern BitMap DIAGA8H1_ATTACKS[64][64];
extern BitMap DIAGA1H8_ATTACKS[64][64];
 
extern const int RANKSHIFT[];
extern const BitMap _FILEMAGICS[];
extern const BitMap _DIAGA8H1MAGICS[];
extern const BitMap _DIAGA1H8MAGICS[];
 
extern BitMap RANKMASK[];
extern BitMap FILEMAGIC[];
extern BitMap FILEMASK[];
extern BitMap DIAGA8H1MASK[];
extern BitMap DIAGA8H1MAGIC[];
extern BitMap DIAGA1H8MASK[];
extern BitMap DIAGA1H8MAGIC[];
 
extern unsigned char GEN_SLIDING_ATTACKS[8][64];
 
extern unsigned char CANCASTLEOO;
extern unsigned char CANCASTLEOOO;
extern BitMap maskEG[];
extern BitMap maskFG[];
extern BitMap maskBD[];
extern BitMap maskCE[];
extern unsigned int WHITE_OOO_CASTL;
extern unsigned int BLACK_OOO_CASTL;
extern unsigned int WHITE_OO_CASTL;
extern unsigned int BLACK_OO_CASTL;
 
extern int ICAPT;
extern int IEP;
extern int IPROM;
extern int ICASTLOO;
extern int ICASTLOOO;
extern int ICHECK;
 
extern int PENALTY_DOUBLED_PAWN;
extern int PENALTY_ISOLATED_PAWN;
extern int PENALTY_BACKWARD_PAWN;
extern int BONUS_PASSED_PAWN;
extern int BONUS_BISHOP_PAIR;
extern int BONUS_ROOK_BEHIND_PASSED_PAWN;
extern int BONUS_ROOK_ON_OPEN_FILE;
extern int BONUS_PAWN_SHIELD_STRONG;
extern int BONUS_PAWN_SHIELD_WEAK;
extern int PAWN_OWN_DISTANCE[];
extern int PAWN_OPPONENT_DISTANCE[];
extern int KNIGHT_DISTANCE[];
extern int BISHOP_DISTANCE[];
extern int ROOK_DISTANCE[];
extern int QUEEN_DISTANCE[];
extern int PAWNPOS_W[];
extern int KNIGHTPOS_W[];
extern int BISHOPPOS_W[];
extern int ROOKPOS_W[];
extern int QUEENPOS_W[];
extern int KINGPOS_W[];
extern int KINGPOS_ENDGAME_W[];
extern int MIRROR[];
extern int DISTANCE[64][64];
extern int PAWNPOS_B[];
extern int KNIGHTPOS_B[];
extern int BISHOPPOS_B[];
extern int ROOKPOS_B[];
extern int QUEENPOS_B[];
extern int KINGPOS_B[];
extern int KINGPOS_ENDGAME_B[];
extern BitMap PASSED_WHITE[];
extern BitMap PASSED_BLACK[];
extern BitMap ISOLATED_WHITE[];
extern BitMap ISOLATED_BLACK[];
extern BitMap BACKWARD_WHITE[];
extern BitMap BACKWARD_BLACK[];
extern BitMap KINGSHIELD_STRONG_W[];
extern BitMap KINGSHIELD_STRONG_B[];
extern BitMap KINGSHIELD_WEAK_W[];
extern BitMap KINGSHIELD_WEAK_B[];
extern BitMap WHITE_SQUARES;
extern BitMap BLACK_SQUARES;
 
extern int LARGE_NUMBER;
extern int CHECKMATESCORE;
extern int STALEMATESCORE;
extern int DRAWSCORE;
extern Move NOMOVE;
 
#endif

 

step 61: protos.h

#ifndef WINGLET_PROTOS_H
#define WINGLET_PROTOS_H
 
#include "board.h"
#include "move.h"
 
unsigned int  bitCnt(BitMap);
void          dataInit();
void          displayBitmap(BitMap);
void          displayMove(Move &);
void            displayPV();
BOOLTYPE      doCommand(const char *);
unsigned int  firstOne(BitMap);
void          info();
BOOLTYPE      isAttacked(BitMap &, const unsigned char &);
BOOLTYPE      isOtherKingAttacked();
BOOLTYPE      isOwnKingAttacked();
BOOLTYPE      isValidTextMove(char *, Move &);
unsigned int  lastOne(BitMap);
void          makeBlackPromotion(unsigned int, unsigned int &);
void          makeCapture(unsigned int &, unsigned int &);
void          makeMove(Move &);
void          makeWhitePromotion(unsigned int, unsigned int &);
int           movegen(int);
U64           perft(int, int);
void          readCommands();
BOOLTYPE      readFen(char *, int);
void          setup();
void          setupFen(char *, char *, char *, char *, int , int );
BOOLTYPE      toSan(Move &, char *);
void          unmakeBlackPromotion(unsigned int, unsigned int &);
void          unmakeCapture(unsigned int &, unsigned int &);
void          unmakeMove(Move &);
void          unmakeWhitePromotion(unsigned int, unsigned int &);
 
#endif

 

step 62: board.h

#ifndef WINGLET_BOARD_H_
#define WINGLET_BOARD_H_
 
#include "defines.h"
#include "move.h"
#include "gameline.h"
#include "timer.h"
 
struct Board
{
       BitMap whiteKing, whiteQueens, whiteRooks, whiteBishops, whiteKnights, whitePawns;
       BitMap blackKing, blackQueens, blackRooks, blackBishops, blackKnights, blackPawns;
       BitMap whitePieces, blackPieces, occupiedSquares;
 
       unsigned char nextMove;        // WHITE_MOVE or BLACK_MOVE
       unsigned char castleWhite;     // White's castle status, CANCASTLEOO = 1, CANCASTLEOOO = 2
       unsigned char castleBlack;     // Black's castle status, CANCASTLEOO = 1, CANCASTLEOOO = 2
       int epSquare;                  // En-passant target square after double pawn move
       int fiftyMove;                 // Moves since the last pawn move or capture
 
       // additional variables:
       int Material;                  // incrementally updated, total material on board,
                                                              // in centipawns, from white’s side of view
       int square[64];                // incrementally updated, this array is usefull if we want to
                                                              // probe what kind of piece is on a particular square.
       BOOLTYPE viewRotated;          // only used for displaying the board. TRUE or FALSE.
 
       // storing moves:
       Move moveBuffer[MAX_MOV_BUFF]; // all generated moves of the current search tree are stored in this array.
       int moveBufLen[MAX_PLY];       // this arrays keeps track of which moves belong to which ply
       int endOfGame;                 // index for board.gameLine
       int endOfSearch;               // index for board.gameLine
       GameLineRecord gameLine[MAX_GAME_LINE];
 
       // search variables:
       int triangularLength[MAX_PLY];
       Move triangularArray[MAX_PLY][MAX_PLY];
       Timer timer;
       U64 msStart, msStop;
       int searchDepth;
       U64 inodes;
 
       void init();
       int eval();
       Move think();
       int minimax(int ply, int depth);
       int alphabeta(int ply, int depth, int alpha, int beta);
       int alphabetapvs(int ply, int depth, int alpha, int beta);
       void displaySearchStats(int mode, int depth, int score);
       BOOLTYPE isEndOfgame(int &legalmoves, Move &singlemove);
       void mirror();
       void initFromSquares(int input[64], unsigned char next, int fiftyM, int castleW, int castleB, int epSq);
       void initFromFen(char fen[], char fencolor[], char fencastling[], char fenenpassant[], int fenhalfmoveclock, int fenfullmovenumber);
       void display();
};
 
#endif

 


Home Previous Top Next

last update: Friday 17 June 2011