In this course we will be developing a simple multi file multi-threaded program (henceforth termed an engine) named Quixotic that plays chess. We will use the Microsoft free Community version of C++ as a better C, MSVS 2022. Let's get started.
First we will make some files.
Quixotic.cpp
Defines.cpp
Globals.cpp
Initialize.cpp
GetCommand.cpp
Move.cpp
Search.cpp
Main.cpp
Quixotic.cpp is the main program file. All other files will be brought into Quixotic using #include.
Defines.cpp will contain everything we define that helps us in the writing of the code.
Globals.cpp will be all the variables that can be accessed from anywhere in the program.
Initialize.cpp will contain all initialization code that almost all programs need to do.
GetCommand.cpp will handel all commands for this chess engine.
Move.cpp will will handle all moves, game moves and internal engine moves.
Search.cpp is all about deciding upon a game move to play.
Main.cpp contains only the required main function.
Code: Select all
// Quixotic.cpp
#include "Defines.cpp"
#include "Globals.cpp"
#include "Initialize.cpp"
#include "GetCommand.cpp"
#include "Move.cpp"
#include "Search.cpp"
#include "Main.cpp"
Code: Select all
// Defines.cpp
// Type defines are used, by the professor's prerogative, to give alternate names to internal variable types
typedef char s08;
typedef int s32;
typedef unsigned long long u64;
// There are 'black' and 'white' pieces that are enumerated as BLACK = 0 and WHITE = 1
enum { BLACK, WHITE };
// Some mode settings
enum { EXIT, GETCMD, SEARCH, MOVE };
// WP stands for white pawn ... WRC for a white rook that can castle ... ES for empty square
enum { WP, WN, WB, WRC, WR, WQ, WKC, WK,
BP, BN, BB, BRC, BR, BQ, BKC, BK,
ES };
// The names of the files
enum { FILEa, FILEb, FILEc, FILEd, FILEe, FILEf, FILEg, FILEh };
// The names of the ranks
enum { RANK1, RANK2, RANK3, RANK4, RANK5, RANK6, RANK7, RANK8 };
// The names of the squares
enum {
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
};
// Structure to contain a single move
struct Move {
s08 fs; // from square
s08 ts; // to square
s08 ft; // from square piece type
s08 tt; // to square piece type including ES for no piece
s32 sc; // score
};
// A thread structure to allow for a multi-threaded engine
struct Thread {
s32 stm; // side to move
s32 ply; // a counter to denote how deep we are in the search
s08 board[64]; // The chessboard
};
// Defines for cleaner looking code
#define stm t->stm
#define ply t->ply
#define board t->board
Code: Select all
//Globals.cpp
// Global variables
s32 mode; // tells the engine what mode it is in
Code: Select all
// Initialize.cpp
// Initialization code
void Initialize() {
mode = GETCMD; // start the engine off in get command mode
}
Code: Select all
// GetCommand.cpp
// Tell the engine what to do
void GetCommand() {
mode = Search; // temporary code to test program flow
}
Code: Select all
Move.cpp
// Performs a move in the game being played
void GameMove() {
mode = EXIT; // temporary code to test program flow
}
Code: Select all
// Search.cpp
// Beginning of the code that will produce a move to be played
void StartSearch() {
mode = MOVE; // temporary code to test program flow
}
Code: Select all
// Main.cpp
// Where the code starts running and controls the flow of the engine
s32 main() {
Initialize();
while (mode != EXIT) {
if (mode == GETCMD) GetCommand();
if (mode == SEARCH) StartSearch();
if (mode == MOVE) GameMove();
}
return 0;
}