I'm making a simple chess game in C and I wanted to know about the optimizations I could make to it. Currently, I have a struct Game that has the current state of the game (Main Menu, Pause Menu, Playing etc), the turn, 3 integers that work as booleans, pointer to a board and pointer to the selected piece:
typedef struct game{
ChessBoard *board;
ChessPiece *selectedPiece;
ChessColor turn;
State state;
//Booleans
int inGame;
int checkmate;
int check;
}Game;
The Board has a 2D array of pointers to pieces, the players and the last moved pieces (for en passant):
typedef struct chessboard{
ChessPiece *pieces[8][8];
Player *player1;
Player *player2;
ChessPiece *lastMovedBlackPiece;
ChessPiece *lastMovedWhitePiece;
} ChessBoard;
And finally the piece:
typedef struct chesspiece{
//Properties
int x;
int y;
ChessColor color;
//Type
Type type;
int numberOfMoves;
} ChessPiece;
Each time the player selects a piece, the program calculates and shows the valid moves of the selected piece, and after moving a piece the program verifies whether the enemy king is in check or it was checkmate by checking the possible moves of the pieces (if a piece can protect him, if the king can move elsewhere).
I see people creating lists for valid moves instead of calculating every time, but I'd have to create a list for every piece and calculate all the possible moves for a player when the turn changes? Would that improve the performance? I also saw the board being just an array, would that have greater performance as well?
Basically, which are the possible optimizations I can do in my code for better performance?
Basically, which are the possible optimizations I can do in my code for better performance?
This is a broad and deep topic. I've written a fully functional chess engine in Java (https://github.com/amir650/BlackWidow-Chess) and I can tell you, there are a lot of things you can do.
Start by reading: https://chessprogramming.wikispaces.com. First focus on the correctness of your engine. Does it handle castling, en-passant, check, checkmate, discovered check, etc. Without getting this correct, performance doesn't matter!
Next write a minimax and evaluation function - which serve as your basic search procedure, and measure the number of boards it can evaluate for you per second.
From there, things start to open up:
1) Alpha Beta Pruning
2) Board representation (bit-board vs array)
3) Null Move Heuristic
4) DB for opening
5) DB end engame
6) Transposition tables
7) ..it goes on
Whatever optimizations you do, make sure correctness does not regress. This means having decent unit tests written.