Click here to Skip to main content
15,881,690 members
Articles / Multimedia / OpenGL

3D Chess (openGL) with Artificial Intelligence

,
Rate me:
Please Sign up or sign in to vote.
4.64/5 (13 votes)
20 May 2010CPOL3 min read 62.2K   7.3K   48   14
A 3D chess game that can be played between a computer and a human
Image 1

Introduction

Chess is a two-player game of strategy in which players take turns trying check the opponent's King. On each turn, a player must move one of his pieces. Each piece has a particular way of moving over the board of 64 squares of alternate black & white ones. For further rules of the game, visit the chess article on Wikipedia.

Background

The chess game has been developed in mainly 5 stages:

  1. Board Representation: Two unsigned int numbers are used to represent the board since the compiler is 32 bit. A class having all the functions of 64 bit has been made by overloading all the required operators.
  2. Move Generation: All the different pieces' possible moves have been precalculated and stored in bitboard. The calculation becomes easy as it requires only shift operations.
  3. Evaluation function: Points have been allotted to the pieces and for protecting & attacking an opponent's piece. Points for checking and checkmating the king are allotted.
  4. Depth Searching: Adding evaluation function was not enough, thinking in depth was required, Minmax tree was implemented.
  5. End game: The possible moves that led itself to king check were blocked and the condition for checkmate was implemented so that the game could end.

Using the Code

The class defines a bit board which comprises two U32 numbers. This makes a board of 64 bits. All the bitwise operators are overloaded so as to work with two 32 bit numbers.

C++
class U64 
{ 
public: 
    U32 l, h;
    U64()
    {  
        l = 0x0; 
        h = 0x0; 
    }

    U64 operator |(U64); 
    U64 operator &(U64); 
    U64 operator ^(U64); 
    U64 operator ~(void); 
    U64 operator <<(int a); 
    U64 operator >>(int b); 
    void operator =(int sq); 
    void operator |=(int sq); 
 
    void display(); 
    int getAndClearLSB(); 

    bool check(){ 
        if( !( l | h) ) 
            return false; 
        else 
            return true; 
    }  
};

The class defining bitboard of various pieces also defines various boards that are precalculated and stored such as possible moves. The constructor declares the initial status of all the bitboards of various pieces.

C++
class CBoard {

public:   

    int side; 
    U64 Pieces[2][7]; 
    U64 Knightsmove[64]; 
    U64 Kingmove[64]; 
    U64 right_board[64]; 
    U64 left_board[64]; 
    U64 up_board[64]; 
    U64 down_board[64]; 
    U64 _45deg_board[64]; 
    U64 _225deg_board[64]; 
    U64 _135deg_board[64]; 
    U64 _315deg_board[64]; 
    U64 Pawnsmove[64][2]; 
    U64 Pawnsdoublemove[64][2]; 
    U64 Pawnsattackmove[64][2]; 
    U64 fullboard[2]; 
    U64 occupiedboard[2]; 
    U64 unoccupiedboard[2]; 
    U64 enemyboard[2]; 
    U64 notfriendlyboard[2]; 
    U64 friendlyboard[2]; 
    U64 attackboard[2]; 
    U64 doubledpawn[2]; 
    U64 isolatedpawn[2]; 
    U64 backwardpawn[2]; 
    U64 kngchk[7]; 

    void validmove();
    CBoard(); 
}bitboard;

I would like to demonstrate the generation of rook's possible moves using bit shift operations. First, precalculate the following bitboards:

  • right_board[64] - A bitboard for every square with all squares to the right of the square set
  • left_board[64] - A bitboard for every square with all squares to the left of the square set
  • up_board[64] - A bitboard for every square with all squares above the square set
  • down_board[64] - A bitboard for every square with all squares below the square set

To calculate the squares to the right where the rook can move to, we do the following:

C++
//right_moves = right_board[sq] AND occupiedboard

We do this because the first piece will stop the rook moving to the right. Because the first piece will stop the rook, we need to fill in all the squares to the right of the piece (<< 1 means shift left one, < 2 means shift left 2, etc):

C++
right_moves = (right_moves<<1) OR (right_moves<<2) OR (right_moves<<3) OR 
(right_moves<<4) OR (right_moves<<5) OR (right_moves<<6)

To get rid of the bits that overflowed to the next row, we AND the result with right_board:

C++
right_moves = right_moves AND right_board

This is all the squares to the right where the rook can't move to. To get the squares where the rook can move to, we exclusive OR the board with right_board:

C++
right_moves = right_moves XOR right_board

You will notice that that all the squares to the right of the rook where it can move to. But what if the pawn on F3 was a black pawn? Then we can't capture it, thus we need one last operation: right_moves = right moves AND enemy_and_empty_squares.

C++
inline U64 genRookAttackBoard(int sq)
{     
    bool side=bitboard.side;
    U64 leftboard = (bitboard.occupiedboard[side] & bitboard.left_board[sq]); 
    leftboard = (leftboard>>1)|(leftboard>>2)|(leftboard>>3)|
	(leftboard>>4)|(leftboard>>5)|(leftboard>>6); 
    leftboard = (leftboard & bitboard.left_board[sq])^bitboard.left_board[sq]; 
 
    U64 rightboard = (bitboard.occupiedboard[side] & bitboard.right_board[sq]); 
    rightboard = (rightboard<<1)|(rightboard<<2)|(rightboard<<3)|
                 (rightboard<<4)|(rightboard<<5)|(rightboard<<6); 
    rightboard = (rightboard & bitboard.right_board[sq]) ^ bitboard.right_board[sq]; 
 
    U64 upboard = (bitboard.occupiedboard[side] & bitboard.up_board[sq]); 
    upboard = (upboard<<8)|(upboard<<16)|(upboard<<24)|
              (upboard<<32)|(upboard<<40)|(upboard<<48); 
    upboard = (upboard & bitboard.up_board[sq]) ^ bitboard.up_board[sq]; 

    U64 downboard = (bitboard.occupiedboard[side] & bitboard.down_board[sq]); 
    downboard = (downboard>>8)|(downboard>>16)|(downboard>>24)|
                (downboard>>32)|(downboard>>40)|(downboard>>48); 
    downboard = (downboard & bitboard.down_board[sq]) ^ bitboard.down_board[sq]; 

    return (leftboard | rightboard | upboard | downboard) & 
	bitboard.notfriendlyboard[side]; 
}

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
IIITA
India India
I am pursuing my btech from iiit allahabad in IT branch.

Written By
IIIT Allahabad
India India
I am 2nd year student pursuing my btech degree in Information Technology from IIITA.

Comments and Discussions

 
QuestionRunning the code Pin
Member 1520192616-May-21 19:09
Member 1520192616-May-21 19:09 
Generalmy vote of 4 Pin
David_LoveCpp27-May-10 16:52
David_LoveCpp27-May-10 16:52 
GeneralRe: my vote of 4 Pin
Prateek Vaishnav27-May-10 20:04
Prateek Vaishnav27-May-10 20:04 
GeneralMy vote of 1 Pin
MyBlindy20-May-10 23:37
MyBlindy20-May-10 23:37 
GeneralRe: My vote of 1 [modified] Pin
Prateek Vaishnav27-May-10 20:16
Prateek Vaishnav27-May-10 20:16 
QuestionWhere's the AI? Pin
Jim Crafton19-May-10 5:14
Jim Crafton19-May-10 5:14 
AnswerRe: Where's the AI? Pin
Gaurav Kishore19-May-10 5:19
Gaurav Kishore19-May-10 5:19 
QuestionPlatform?? Pin
Sharjith18-May-10 9:29
professionalSharjith18-May-10 9:29 
AnswerRe: Platform?? Pin
Ali BaderEddin18-May-10 11:56
Ali BaderEddin18-May-10 11:56 
GeneralRe: Platform?? Pin
Gaurav Kishore18-May-10 15:10
Gaurav Kishore18-May-10 15:10 
General@Catabre Pin
Prateek Vaishnav19-May-10 20:23
Prateek Vaishnav19-May-10 20:23 
AnswerRe: Platform?? Pin
Gaurav Kishore18-May-10 15:13
Gaurav Kishore18-May-10 15:13 
AnswerRe: Platform?? Pin
ReymonARG19-May-10 9:54
ReymonARG19-May-10 9:54 
Wich error are you getting? I can fix, to work with Windows. Blush | :O
GeneralRe: Platform?? Pin
Sharjith19-May-10 10:06
professionalSharjith19-May-10 10:06 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.