Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified chess
Binary file not shown.
65 changes: 41 additions & 24 deletions chess.cc
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,23 @@ Chess::Chess(): colorToMove{(1 << 7)} {
memset(board, 0, sizeof(board));
}


int Chess::getPiece(int row, int col) const {
return board[row][col];
}

int Chess::getEmpty() const {
return Empty;
}

int Chess::getBlack() const {
return Black;
}

int Chess::getWhite() const {
return White;
}

void Chess::kingMoves(int startIndex) {
int startRow = startIndex / 8;
int startCol = startIndex % 8;
Expand All @@ -30,8 +47,8 @@ void Chess::kingMoves(int startIndex) {
int targetIndex = newRow * 8 + newCol;
int targetPiece = board[newRow][newCol];
int targetColor = targetPiece & (White | Black);
if (targetPiece == None || (targetColor != kingColor)) {
validMoves.push_back({startIndex, targetIndex, targetPiece == None ? -1 : targetIndex});
if (targetPiece == Empty || (targetColor != kingColor)) {
validMoves.push_back({startIndex, targetIndex, targetPiece == Empty ? -1 : targetIndex});
}
}
}
Expand All @@ -43,9 +60,9 @@ void Chess::castleMove() {
if (board[row][4] == (colorToMove | King)) {
bool leftCastle = true, rightCastle = true;
for (int i = 3; i > 0; --i)
if (board[row][i] != None) leftCastle = false;
if (board[row][i] != Empty) leftCastle = false;
for (int i = 5; i < 7; ++i)
if (board[row][i] != None) rightCastle = false;
if (board[row][i] != Empty) rightCastle = false;

if (leftCastle && board[row][0] == (colorToMove | Rook))
validMoves.push_back({row*8 + 4, row*8 + 2, -2});
Expand All @@ -60,20 +77,20 @@ void Chess::pawnMove(int startIndex) {

if (board[row][col] == (Pawn | White)) { // white pawn
if (row == 1) { // initial position
if (board[row + 1][col] == None) validMoves.push_back({startIndex, startIndex + 8, -1}); // move one
if (board[row + 2][col] == None) validMoves.push_back({startIndex, startIndex + 16, -1}); // move two
if (board[row + 1][col] == Empty) validMoves.push_back({startIndex, startIndex + 8, -1}); // move one
if (board[row + 2][col] == Empty) validMoves.push_back({startIndex, startIndex + 16, -1}); // move two
} else {
if (board[row + 1][col] == None) validMoves.push_back({startIndex, startIndex + 8, -1}); // move one
if (board[row + 1][col] == Empty) validMoves.push_back({startIndex, startIndex + 8, -1}); // move one
}

// en passant
if (row == 4) { // en passant for white only on row 5
// left capture check
if (col > 0 && board[row][col - 1] == (Pawn | Black) && board[row + 1][col - 1] == None) {
if (col > 0 && board[row][col - 1] == (Pawn | Black) && board[row + 1][col - 1] == Empty) {
validMoves.push_back({startIndex, startIndex + 7, startIndex - 1});
}
// right capture check
if (col < 7 && board[row][col + 1] == (Pawn | Black) && board[row + 1][col + 1] == None) {
if (col < 7 && board[row][col + 1] == (Pawn | Black) && board[row + 1][col + 1] == Empty) {
validMoves.push_back({startIndex, startIndex + 9, startIndex + 1});
}
}
Expand All @@ -88,20 +105,20 @@ void Chess::pawnMove(int startIndex) {

} else if (board[row][col] == (Pawn | Black)) { // black pawn
if (row == 6) { // initial position
if (board[row - 1][col] == None) validMoves.push_back({startIndex, startIndex - 8, -1}); // move one
if (board[row - 2][col] == None) validMoves.push_back({startIndex, startIndex - 16, -1}); // move two
if (board[row - 1][col] == Empty) validMoves.push_back({startIndex, startIndex - 8, -1}); // move one
if (board[row - 2][col] == Empty) validMoves.push_back({startIndex, startIndex - 16, -1}); // move two
} else {
if (board[row - 1][col] == None) validMoves.push_back({startIndex, startIndex - 8, -1}); // move one
if (board[row - 1][col] == Empty) validMoves.push_back({startIndex, startIndex - 8, -1}); // move one
}

// en passant
if (row == 3) { // en passant for black only on row 4 (0 indexed)
// left capture check
if (col > 0 && board[row][col - 1] == (Pawn | White) && board[row - 1][col - 1] == None) {
if (col > 0 && board[row][col - 1] == (Pawn | White) && board[row - 1][col - 1] == Empty) {
validMoves.push_back({startIndex, startIndex - 9, startIndex - 1});
}
// right capture check
if (col < 7 && board[row][col + 1] == (Pawn | White) && board[row - 1][col + 1] == None) {
if (col < 7 && board[row][col + 1] == (Pawn | White) && board[row - 1][col + 1] == Empty) {
validMoves.push_back({startIndex, startIndex - 7, startIndex + 1});
}
}
Expand All @@ -123,7 +140,7 @@ void Chess::knightMove(int startIndex) {
int a = (i&1 ? -1 : 1)*8, b = (i&2 ? -1 : 1)*2;
int row = (startIndex + a)/8, col = (startIndex + b)%8;
if (row >= 0 && row < 8 && col >= 0 && col < 8) {
if (board[row][col] == None) validMoves.push_back({startIndex, row*8+col, -1});
if (board[row][col] == Empty) validMoves.push_back({startIndex, row*8+col, -1});
else if (!(board[row][col] & colorToMove)) validMoves.push_back({startIndex, row*8+col, row*8+col});
}
}
Expand All @@ -133,7 +150,7 @@ void Chess::knightMove(int startIndex) {
int row = (startIndex + a)/8, col = (startIndex + b)%8;
cout << row << " " << col << '\n';
if (row >= 0 && row < 8 && col >= 0 && col < 8) {
if (board[row][col] == None) validMoves.push_back({startIndex, row*8+col, -1});
if (board[row][col] == Empty) validMoves.push_back({startIndex, row*8+col, -1});
else if (!(board[row][col] & colorToMove)) validMoves.push_back({startIndex, row*8+col, row*8+col});
}
}
Expand All @@ -147,7 +164,7 @@ void Chess::horizontalVerticalMoves(int startIndex){

//horizontal to the right
for(int i = col + 1; i < 8; ++i){
if(board[row][i] == None){
if(board[row][i] == Empty){
validMoves.push_back({startIndex, row*8 + i, -1}); // move if nothing in path
}else{
if((board[row][i] & (White | Black)) != color){
Expand All @@ -159,7 +176,7 @@ void Chess::horizontalVerticalMoves(int startIndex){

//horizontal to the left
for(int i = col - 1; i >= 0; --i){
if(board[row][i] == None){
if(board[row][i] == Empty){
validMoves.push_back({startIndex, row*8 + i, -1}); // move if nothing in path
}else{
if((board[row][i] & (White | Black)) != color){
Expand All @@ -171,7 +188,7 @@ void Chess::horizontalVerticalMoves(int startIndex){

//vertical upwards
for(int i = row + 1; i < 8; ++i){
if(board[i][col] == None){
if(board[i][col] == Empty){
validMoves.push_back({startIndex, i*8 + col, -1}); // go up all the way
cout << "(" << startIndex << "," << i*8+col<< ")" << endl;
}else{
Expand All @@ -184,7 +201,7 @@ void Chess::horizontalVerticalMoves(int startIndex){

//vertical downwards
for(int i = row - 1; i >= 0; --i){
if(board[i][col] == None){
if(board[i][col] == Empty){
validMoves.push_back({startIndex, i*8 + col, -1}); // go up all the way

}else{
Expand Down Expand Up @@ -246,7 +263,7 @@ void Chess::diagonalMove(int startIndex) {
int f = (i > 1) ? 2*(i%2) - 9 : 9 - 2*(i%2), t = startIndex + r*f;
int row = t/8, col = t%8;
if (row >= 0 && row < 8 && col >= 0 && col < 8) {
if (board[row][col] == None) validMoves.push_back({startIndex, t, -1});
if (board[row][col] == Empty) validMoves.push_back({startIndex, t, -1});
else {
if (!(board[row][col] & colorToMove)) validMoves.push_back({startIndex, t, t});
notCovered ^= d;
Expand Down Expand Up @@ -333,14 +350,14 @@ bool Chess::playMove(string start, string target) {
if (startIndex == i.start && targetIndex == i.target) {

if (i.isCapture != -1)
board[i.isCapture/8][i.isCapture%8] = None;
board[i.isCapture/8][i.isCapture%8] = Empty;



int piece = board[startIndex/8][startIndex%8];
int capturedPiece = board[targetIndex/8][targetIndex%8];

board[startIndex/8][startIndex%8] = None;
board[startIndex/8][startIndex%8] = Empty;
board[targetIndex/8][targetIndex%8] = piece;

// Is a castling move, so put rook in appropriate position
Expand Down Expand Up @@ -416,7 +433,7 @@ void Chess::print() {
cout << row + 1 << ' ';
for (int col = 0; col < 8; ++col) {
int Piece = board[row][col];
if (Piece == None) cout << ((row + col)%2 ? '-' : ' ');
if (Piece == Empty) cout << ((row + col)%2 ? '-' : ' ');
else {
char Letter = Piece&((1 << 7) - 1);
cout << ((Piece&Black) ? char(Letter + 32) : Letter);
Expand Down
26 changes: 16 additions & 10 deletions chess.h
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
#ifndef CHESS_H
#define CHESS_H

#include <vector>
#include <iostream>
using namespace std;



class Chess {

const int None = 0;
const int Empty = 0; // Renamed from None to avoid conflict
const int King = 75;
const int Queen = 81;
const int Knight = 78;
Expand All @@ -20,18 +18,18 @@ class Chess {
const int Black = (1 << 8);

struct Move {
int start; // start square
int target; // final square
int isCapture; // see if opposite coloure peice available for capture
int start;
int target;
int isCapture;
};

int board[8][8];
int colorToMove;

vector<Move> validMoves;// valid moves from start to end square 0 - 63
vector<Move> validMoves;

void kingMoves(int);
void pawnMove(int); // parameter is start of square where pawn is
void pawnMove(int);
void knightMove(int);
void castleMove();
void pawnPromotions(int);
Expand All @@ -47,7 +45,15 @@ class Chess {
Chess();
Chess(string);

bool playMove(string, string);// start and end for entering
bool playMove(string, string);

void print();

// Accessor methods
int getPiece(int row, int col) const;
int getEmpty() const;
int getBlack() const;
int getWhite() const;
};

#endif
35 changes: 30 additions & 5 deletions chessgame.cc
Original file line number Diff line number Diff line change
@@ -1,19 +1,44 @@
#include <iostream>
#include <unistd.h>
#include "chess.h"
#include "window.h"
// g++ -I/opt/X11/include -L/opt/X11/lib -o chess chessgame.cc chess.cc window.cc -lX11 -std=c++20
using namespace std;

// g++ -o chess -std=c++17 chess.cc chessgame.cc

int main() {
Chess game("");
ChessWindow window;
int squareSize = 80;

XEvent event;
string start, end;


game.print();

while (1) {
window.clear();
drawBoard(window, game, squareSize);

while (XPending(window.display) > 0) {
XNextEvent(window.display, &event);
if (event.type == Expose) {
drawBoard(window, game, squareSize);
}
}

cout << "Play move: ";
string start, end;
cin >> start >> end;
bool res = game.playMove(start, end);
if (!res) cout << "Invalid move!\n";
if (!res) {
cout << "Invalid move!\n";
} else {
cout << "Move played: " << start << " to " << end << "\n";
}
game.print();

usleep(100000);
}
}

return 0;
}
78 changes: 78 additions & 0 deletions window.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#include "window.h"
#include <iostream>

ChessWindow::ChessWindow() {
display = XOpenDisplay(NULL);
if (!display) {
std::cerr << "Unable to open X display" << std::endl;
exit(1);
}

screen = DefaultScreen(display);
win = XCreateSimpleWindow(display, RootWindow(display, screen), 10, 10, 720, 720, 0,
0x0000FF, WhitePixel(display, screen));

XSelectInput(display, win, ExposureMask | KeyPressMask);
gc = XCreateGC(display, win, 0, NULL);
XSetForeground(display, gc, BlackPixel(display, screen));

XMapWindow(display, win);
}

ChessWindow::~ChessWindow() {
XFreeGC(display, gc);
XDestroyWindow(display, win);
XCloseDisplay(display);
}

void ChessWindow::clear() {
XClearWindow(display, win);
}

void ChessWindow::drawSquare(int x, int y, int size, bool isWhite) {
XSetForeground(display, gc, isWhite ? 0xE5E6D5 : 0x799359);
XFillRectangle(display, win, gc, x, y, size, size);
}

void ChessWindow::drawPiece(int x, int y, char piece, bool isBlack) {
unsigned long color = isBlack ? 0x000000 : 0x000000;
XSetForeground(display, gc, color);
XDrawString(display, win, gc, x + 10, y + 30, &piece, 1);
}


void ChessWindow::drawText(int x, int y, const char* text) {
XSetForeground(display, gc, BlackPixel(display, screen));
XDrawString(display, win, gc, x, y, text, strlen(text));
}

void drawBoard(ChessWindow& window, const Chess& game, int squareSize) {
for (int row = 0; row < 8; ++row) {
for (int col = 0; col < 8; ++col) {
bool isWhite = (row + col) % 2 == 0;
window.drawSquare((col + 1) * squareSize, (7 - row + 1) * squareSize, squareSize, isWhite);
int piece = game.getPiece(row, col);
if (piece != game.getEmpty()) {
char pieceChar = piece & ((1 << 7) - 1);
bool isBlack = piece & game.getBlack();
if (isBlack) {
pieceChar = tolower(pieceChar);
}
window.drawPiece((col + 1) * squareSize, (7 - row + 1) * squareSize, pieceChar, isBlack);
}
}
}

for (int col = 0; col < 8; ++col) {
char letter = 'a' + col;
window.drawText((col + 1) * squareSize + squareSize / 2, 9 * squareSize + 20, &letter); // bottom letters
window.drawText((col + 1) * squareSize + squareSize / 2, squareSize - 10, &letter); // top letters
}

for (int row = 0; row < 8; ++row) {
char number = '1' + row;
window.drawText(10, (8 - row) * squareSize + squareSize / 2, &number); // left numbers
window.drawText(9 * squareSize + 10, (8 - row) * squareSize + squareSize / 2, &number); // right numbers
}

}
Loading