Home Previous Bottom Next

Writing a chess program in 99 steps


 
step 45: board.h

#ifndef WINGLET_BOARD_H_
#define WINGLET_BOARD_H_
 
#include "defines.h"
#include "move.h"
#include "gameline.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 game and search 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];
 
       void init();
       int eval();
       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

 
step 46: board.cpp

#include <iostream>
#include <iomanip>
#include "defines.h"
#include "protos.h"
#include "extglobals.h"
#include "board.h"
 
void Board::init()
{
       viewRotated = false;
 
       for (int i = 0; i < 64; i++) square[i] = EMPTY;
 
       square[E1] = WHITE_KING;
       square[D1] = WHITE_QUEEN;
       square[A1] = WHITE_ROOK;
       square[H1] = WHITE_ROOK;
       square[B1] = WHITE_KNIGHT;
       square[G1] = WHITE_KNIGHT;
       square[C1] = WHITE_BISHOP;
       square[F1] = WHITE_BISHOP;
       square[A2] = WHITE_PAWN;
       square[B2] = WHITE_PAWN;
       square[C2] = WHITE_PAWN;
       square[D2] = WHITE_PAWN;
       square[E2] = WHITE_PAWN;
       square[F2] = WHITE_PAWN;
       square[G2] = WHITE_PAWN;
       square[H2] = WHITE_PAWN;
 
       square[E8] = BLACK_KING;
       square[D8] = BLACK_QUEEN;
       square[A8] = BLACK_ROOK;
       square[H8] = BLACK_ROOK;
       square[B8] = BLACK_KNIGHT;
       square[G8] = BLACK_KNIGHT;
       square[C8] = BLACK_BISHOP;
       square[F8] = BLACK_BISHOP;
       square[A7] = BLACK_PAWN;
       square[B7] = BLACK_PAWN;
       square[C7] = BLACK_PAWN;
       square[D7] = BLACK_PAWN;
       square[E7] = BLACK_PAWN;
       square[F7] = BLACK_PAWN;
       square[G7] = BLACK_PAWN;
       square[H7] = BLACK_PAWN;
 
       initFromSquares(square, WHITE_MOVE, 0, CANCASTLEOO + CANCASTLEOOO, CANCASTLEOO + CANCASTLEOOO, 0);
 
       return;
}
 
void Board::mirror()
{
       // Mirrors the board position (NOTE: move buffers are not effected!!!).
       // The intended use is to test symmetry of the evalaution function.
       // Don't forget to mirror the position back to the original position, after testing the evaluation function.
 
       int i, mirroredBoard[64];
       unsigned char nextMirror;
       int fiftyMMirror, castleWMirror, castleBMirror, epSqMirror;
       int kmoveBufLen, kendOfGame, kendOfSearch;
 
       nextMirror = !nextMove;
       fiftyMMirror = fiftyMove;
       castleWMirror = castleBlack;
       castleBMirror = castleWhite;
       if (epSquare)
       {
              if (epSquare < 24) epSqMirror = epSquare + 24;
              else epSqMirror = epSquare - 24;
       }
 
       for (i = 0; i < 64; i++)
       {
              mirroredBoard[i] = square[MIRROR[i]];
              // swap piece color (4th bit):
              if (mirroredBoard[i] != EMPTY) mirroredBoard[i] ^= 8;
       }
 
       // keep the move buffer intact:
       kmoveBufLen = moveBufLen[0];
       kendOfGame = endOfGame;
       kendOfSearch = endOfSearch;
       initFromSquares(mirroredBoard, nextMirror, fiftyMMirror, castleWMirror, castleBMirror, epSqMirror);
       moveBufLen[0] = kmoveBufLen;
       endOfGame = kendOfGame;
       endOfSearch = kendOfSearch;
 
       return;
}
 
void Board::initFromSquares(int input[64], unsigned char next, int fiftyM, int castleW, int castleB, int epSq)
{
       // sets up the board variables according to the information found in
       // the input[64] array
       // All board & game initializations are done through this function (including readfen and setup).
 
       int i;
 
       // bitboards
       whiteKing    = 0;
       whiteQueens  = 0;
       whiteRooks   = 0;
       whiteBishops = 0;
       whiteKnights = 0;
       whitePawns   = 0;
       blackKing    = 0;
       blackQueens  = 0;
       blackRooks   = 0;
       blackBishops = 0;
       blackKnights = 0;
       blackPawns   = 0;
       whitePieces  = 0;
       blackPieces  = 0;
       occupiedSquares = 0;
 
       // populate the 12 bitboard:
       for (i = 0; i < 64; i++)
       {
              square[i] = input[i];
              if (square[i] == WHITE_KING)   whiteKing    = whiteKing    | BITSET[i];
              if (square[i] == WHITE_QUEEN)  whiteQueens  = whiteQueens  | BITSET[i];
              if (square[i] == WHITE_ROOK)   whiteRooks   = whiteRooks   | BITSET[i];
              if (square[i] == WHITE_BISHOP) whiteBishops = whiteBishops | BITSET[i];
              if (square[i] == WHITE_KNIGHT) whiteKnights = whiteKnights | BITSET[i];
              if (square[i] == WHITE_PAWN)   whitePawns   = whitePawns   | BITSET[i];
              if (square[i] == BLACK_KING)   blackKing    = blackKing    | BITSET[i];
              if (square[i] == BLACK_QUEEN)  blackQueens  = blackQueens  | BITSET[i];
              if (square[i] == BLACK_ROOK)   blackRooks   = blackRooks   | BITSET[i];
              if (square[i] == BLACK_BISHOP) blackBishops = blackBishops | BITSET[i];
              if (square[i] == BLACK_KNIGHT) blackKnights = blackKnights | BITSET[i];
              if (square[i] == BLACK_PAWN)   blackPawns   = blackPawns   | BITSET[i];
       }
 
       whitePieces = whiteKing | whiteQueens | whiteRooks | whiteBishops | whiteKnights | whitePawns;
       blackPieces = blackKing | blackQueens | blackRooks | blackBishops | blackKnights | blackPawns;
       occupiedSquares = whitePieces | blackPieces;
 
       nextMove = next;
       castleWhite = castleW;
       castleBlack = castleB;
       epSquare = epSq;
       fiftyMove = fiftyM;
 
       moveBufLen[0] = 0;
       endOfGame = 0;
       endOfSearch = 0;
 
       Material    =        bitCnt(whitePawns) * PAWN_VALUE +
                                  bitCnt(whiteKnights) * KNIGHT_VALUE +
                                  bitCnt(whiteBishops) * BISHOP_VALUE +
                                  bitCnt(whiteRooks) * ROOK_VALUE +
                                  bitCnt(whiteQueens) * QUEEN_VALUE;
       Material      -= (bitCnt(blackPawns) * PAWN_VALUE +
                                  bitCnt(blackKnights) * KNIGHT_VALUE +
                                  bitCnt(blackBishops) * BISHOP_VALUE +
                                  bitCnt(blackRooks) * ROOK_VALUE +
                                  bitCnt(blackQueens) * QUEEN_VALUE);
 
       return;
}
 
void Board::display()
{
       int rank, file;
 
       std::cout << std::endl;
       {
              if (!viewRotated)
              {
                     for (rank = 8; rank >= 1; rank--)
                     {
                           std::cout << "    +---+---+---+---+---+---+---+---+" << std::endl;
                           std::cout << std::setw(3) << rank <<  " |";
                           for (file = 1; file <= 8; file++)
                           {
                                  std::cout << " " << PIECENAMES[square[BOARDINDEX[file][rank]]] << "|";
                           }
                           std::cout << std::endl;
                     }
                     std::cout << "    +---+---+---+---+---+---+---+---+" << std::endl;
                     std::cout << "      a   b   c   d   e   f   g   h" << std::endl << std::endl;
              }
              else
              {
                     std::cout << "      h   g   f   e   d   c   b   a" << std::endl;
                     for (rank = 1; rank <= 8; rank++)
                     {
                           std::cout << "    +---+---+---+---+---+---+---+---+" << std::endl;
                           std::cout << "    |";
                           for (file = 8; file >= 1; file--)
                            {
                    std::cout << " " << PIECENAMES[square[BOARDINDEX[file][rank]]] << "|";
                           }
                           std::cout << std::setw(3) << rank << std::endl;
                     }
                     std::cout << "    +---+---+---+---+---+---+---+---+" << std::endl << std::endl;
              }
       }
       return;
}

 
 
step 47: defines.h

#ifndef WINGLET_DEFINES_H
#define WINGLET_DEFINES_H
 
#define WINGLET_PROG_VERSION "winglet 0.0, Copyright (C) 2011, Stef Luijten"
//#define WINGLET_DEBUG_PERFT
//#define WINGLET_DEBUG_MOVES
//#define WINGLET_VERBOSE_EVAL
//#define WINGLET_DEBUG_EVAL
 
typedef unsigned long long U64;
typedef unsigned long long BitMap;
typedef short SHORTINT;
typedef unsigned short USHORTINT;
typedef int BOOLTYPE;
 
#define MAX_CMD_BUFF 256   // Console command input buffer
#define MAX_MOV_BUFF 4096   // Number of moves that we can store (all plies)
#define MAX_PLY                     64    // Search depth
#define MAX_GAME_LINE      1024   // Number of moves in the (game + search) line that we can store
 
#endif

 
step 48: wingletx.cpp  

#include <iostream>
#include "defines.h"
#include "protos.h"
#include "globals.h"
 
int main(int argc, char *argv[])
{
       std::cout << WINGLET_PROG_VERSION << std::endl;
       #ifdef WINGLET_DEBUG_PERFT
          std::cout << "WINGLET_DEBUG_PERFT defined" << std::endl;
       #endif
       #ifdef WINGLET_DEBUG_MOVES
          std::cout << "WINGLET_DEBUG_MOVES defined" << std::endl;
       #endif
       #ifdef WINGLET_VERBOSE_EVAL
          std::cout << "WINGLET_VERBOSE_EVAL defined" << std::endl;
       #endif
       #ifdef WINGLET_DEBUG_EVAL
          std::cout << "WINGLET_DEBUG_EVAL defined" << std::endl;
       #endif
    std::cout << std::endl;
    dataInit();
    readCommands();
    return 0;
}

 


Home Previous Top Next

last update: Friday 10 June 2011