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
13 changes: 3 additions & 10 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
SOURCEDIR = src
DESTDIR = bin

CFLAGS = -std=c11 -Wno-return-local-addr
CFLAGS = -std=c11 -Wno-return-local-addr
LIBS := $(shell ncursesw5-config --libs) -ltinfo
SRCS := $(wildcard $(SOURCEDIR)/*.c)
OBJS := $(patsubst %.c, %.o, $(SRCS))
OBJS := $(patsubst %.c, %.o, $(wildcard $(SOURCEDIR)/*.c))
OUT = chess

$(OUT): $(OBJS)
gcc -g $(OBJS) $(CFLAGS) -o $(DESTDIR)/$(OUT)
#NCURSES build
#gcc $(OBJS) $(CFLAGS) $(LIBS) $(shell ncursesw5-config --cflags) --enable-widec -o $(DESTDIR)/$(OUT)
gcc $(OBJS) $(CFLAGS) $(LIBS) $(shell ncursesw5-config --cflags) --enable-widec -o $(DESTDIR)/$(OUT)

%.o: %.c
gcc -c $< $(CFLAGS) -o $@

clean:
rm $(OBJS) $(DESTDIR)/$(OUT)

test:
$(foreach src, $(SRCS), gcc -c $(src) -DTEST $(CFLAGS) -o $(basename $(src)).o;)
gcc $(OBJS) $(CFLAGS) -o $(DESTDIR)/$(OUT)
12 changes: 6 additions & 6 deletions src/board.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ void PrintBoard(Board *b) {
printf("%d ║", rank + 1);
for (int file = 0; file < 8; ++file) {
if(!b->board[file][rank]->hl){
printf(" %lc ", GetUnicode(b->board[file][rank]->piece, b->board[file][rank]->color));
printf(" %lc ", GetUnicode(b->board[file][rank], false));
}else{
printf("<%lc>", GetUnicode(b->board[file][rank]->piece, b->board[file][rank]->color));
printf("<%lc>", GetUnicode(b->board[file][rank], false));
}
if (file != 7) printf("│");
}
Expand Down Expand Up @@ -104,9 +104,9 @@ void FillBoardTest(Board *chessBoard) {

//return the corresponding chess piece character (e.g. white pawn ♙ = 0x2659) given the color and piece type
//note: unicode characters must be stored in the wchar_t type due to their larger size
wchar_t GetUnicode(EPieceType piece, EColor color) {
if (color == BLACK) {
switch (piece) {
wchar_t GetUnicode(Piece *p, bool whiteTile) {
if ((p->color == WHITE && whiteTile) || (p->color == BLACK && !whiteTile)) {
switch (p->piece) {
case PAWN:
return 0x2659;
case ROOK:
Expand All @@ -124,7 +124,7 @@ wchar_t GetUnicode(EPieceType piece, EColor color) {
}
}
else {
switch (piece) {
switch (p->piece) {
case PAWN:
return 0x265F; //0x265F;
case ROOK:
Expand Down
5 changes: 3 additions & 2 deletions src/board.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ typedef enum {
} EPieceType;

typedef enum {
PROGRESS,
WHITE_WIN,
BLACK_WIN,
STALEMATE
Expand Down Expand Up @@ -41,8 +42,8 @@ typedef struct {
//captured board, black starts at 2*8=16
Piece *cap[4][8];
int nCapW, nCapB;
EColor p1;
EColor currentPlayerTurn;
EColor p1;
EGameState gameState;
} Board;

Expand All @@ -52,5 +53,5 @@ void FillBoard(Board *board);
void FillBoardTest(Board *board);
void CopyBoard(Board *b1, Board *b2);
void DeleteBoard(Board *b);
wchar_t GetUnicode(EPieceType, EColor);
wchar_t GetUnicode(Piece *p, bool whiteTile);
#endif
179 changes: 156 additions & 23 deletions src/game.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <ncurses.h>

const int VALID_MOVE_SIZE = 63;

Expand All @@ -12,9 +13,9 @@ char *Move(int f0, int r0, int f1, int r1, Board *b) {
if (IsValid(f0, r0, f1, r1, b)) {
//-------- Update Misc. Board Data --------
//To count the total number of moves of each piece
b->board[f0][r0]->counter ++;
b->board[f0][r0]->counter++;

if(b->board[f0][r0]->color == BLACK){
if(b->currentPlayerTurn == BLACK) {
b->currentPlayerTurn = WHITE;
}else{
b->currentPlayerTurn = BLACK;
Expand All @@ -23,10 +24,46 @@ char *Move(int f0, int r0, int f1, int r1, Board *b) {
//---------- Move the Piece ----------------
//store the moving piece temporarily
Piece *p = b->board[f0][r0];


//White Pawn En Passant
if (b->board[f1][r1-1]->piece == PAWN && (b->board[f0][r0]->color != b->board[f1][r1-1]->color) && b->board[f0][r0]->color == WHITE ) {
if(r0 == 4 && b->board[f1][r1-1]->counter == 1){
b->board[f0][r0]->isCapturing = true; //so that CAN know that it is capturing
printf("%d\n", b->board[f0][r0]->isCapturing);
CAN(f0, r0, f1, r1, b);
printf("CAPTURING");
Capture(f1, r1-1, b);
b->board[f1][r1] = p;
b->board[f0][r0] = malloc(sizeof(Piece));
b->board[f0][r0]->piece = EMPTY;
b->board[f0][r0]->color = NO_COLOR;
b->board[f1][r1-1] = malloc(sizeof(Piece));
b->board[f1][r1-1]->piece = EMPTY;
b->board[f1][r1-1]->color = NO_COLOR;
}
}
//Black Pawn En Passant
if (b->board[f1][r1+1]->piece == PAWN && (b->board[f0][r0]->color != b->board[f1][r1+1]->color) && b->board[f0][r0]->color == BLACK ) {
if(r0 == 3 && b->board[f1][r1+1]->counter == 1){
b->board[f0][r0]->isCapturing = true; //so that CAN know that it is capturing
printf("%d\n", b->board[f0][r0]->isCapturing);
CAN(f0, r0, f1, r1, b);

printf("CAPTURING");
Capture(f1, r1 + 1, b);
b->board[f1][r1] = p;
b->board[f0][r0] = malloc(sizeof(Piece));
b->board[f0][r0]->piece = EMPTY;
b->board[f0][r0]->color = NO_COLOR;
b->board[f1][r1+1] = malloc(sizeof(Piece));
b->board[f1][r1+1]->piece = EMPTY;
b->board[f1][r1+1]->color = NO_COLOR;
}
}

//normal move
if (b->board[f1][r1]->piece == EMPTY) {
CAN(f0, r0, f1, r1, b);
//CAN(f0, r0, f1, r1, b);
b->board[f0][r0] = b->board[f1][r1];
b->board[f1][r1] = p;
Castling (f0, r0, f1, r1, b);
Expand All @@ -35,24 +72,22 @@ char *Move(int f0, int r0, int f1, int r1, Board *b) {
//capturing move (prevent capturing king)
else if (b->board[f1][r1]->piece != KING) {
b->board[f0][r0]->isCapturing = true; //so that CAN know that it is capturing
printf("%d\n", b->board[f0][r0]->isCapturing);
CAN(f0, r0, f1, r1, b);
//printf("%d\n", b->board[f0][r0]->isCapturing);
//CAN(f0, r0, f1, r1, b);

printf("CAPTURING");
//printf("CAPTURING");
Capture(f1, r1, b);
b->board[f1][r1] = p;
b->board[f0][r0] = malloc(sizeof(Piece));
b->board[f0][r0]->piece = EMPTY;
b->board[f0][r0]->color = NO_COLOR;
}
if (b->board[f0][r0]->piece == PAWN) printf("dOMOSF");

//promotion (PAWN HAS BEEN MOVED)
if (b->board[f1][r1]->piece == PAWN) {
if ((r1 == 7 && b->board[f1][r1]->color == WHITE) || (r1 == 0 && b->board[f1][r1]->color == BLACK)) {
char promoteTo;
printf("Please choose a piece to promote your pawn to: \nQ:Queen\nN:Knight\nB:Bishop\nR:Rook\nPiece:");
scanf(" %c", &promoteTo);
//printf("Please choose a piece to promote your pawn to: \nQ:Queen\nN:Knight\nB:Bishop\nR:Rook\nPiece:");
//scanf(" %c", &promoteTo);
switch(promoteTo){
case 'B':
b->board[f1][r1]->isPromoted = true;
Expand All @@ -74,10 +109,11 @@ char *Move(int f0, int r0, int f1, int r1, Board *b) {
}
}
}

mvprintw(1,1, " ");

}else{
printf("Invalid move!\n");
mvprintw(1,1,"INVALID MOVE!");
//printf("Invalid move!\n");
}
return "";
}
Expand Down Expand Up @@ -321,6 +357,7 @@ LL *getValidMovesQueen(int f, int r, Board *b){
LL *out = malloc(sizeof(LL));
out->first = NULL;
out->last = NULL;

//check vertical line up
for(int i = r+1; i < 8; i++){
//b->board[f][i]->hl = 1;
Expand Down Expand Up @@ -407,21 +444,21 @@ LL *getValidMovesQueen(int f, int r, Board *b){
}
}
//check diagonal bottom right
for(int i = f+1, j=r-1; i<8 && j>=0; i++,j--){
//b->board[i][j]->hl = 1;
if(b->board[i][j]->color != b->board[f][r]->color){
for (int i = f+1, j= r-1; i < 8 && j>=0; i++, j--){
if (b->board[f][r]->color != b->board[i][j]->color){
MOVE *curr = malloc(sizeof(MOVE));
curr->r0 = r;
curr->r0 = r;
curr->f0 = f;
curr->r1 = j;
curr->f1 = i;
Append(out, curr);
if(b->board[i][j]->color != EMPTY){
//b->board[i][j]->hl = 1;
if (b->board[i][j]->piece != EMPTY){
break;
}
}else{
break;
}

else break;
}
//check diagonal bottom left
for(int i = f-1, j=r-1; i>=0 && j>=0; i--,j--){
Expand Down Expand Up @@ -844,6 +881,34 @@ LL *getValidMovesPawn(int f0, int r0, Board *b){
Append(out, curr);
}
//}

//EN PASSANT for WHITE PAWN
f = f0+1, r = r0+1;
if (f < 8 && r < 8){
if(b->board[f0+1][r0]->piece == PAWN && b->board[f0+1][r0]->color == BLACK){
if(r0 == 4 && b->board[f0+1][r0]->counter == 1){
MOVE *curr = malloc(sizeof(MOVE));
curr -> f0 = f0;
curr -> r0 = r0;
curr -> f1 = f;
curr -> r1 = r;
Append(out, curr);
}
}
}
f = f0-1, r = r0+1;
if (f >= 0 && r < 8){
if(b->board[f0-1][r0]->piece == PAWN && b->board[f0-1][r0]->color == BLACK){
if(r0 == 4 && b->board[f0-1][r0]->counter == 1){
MOVE *curr = malloc(sizeof(MOVE));
curr -> f0 = f0;
curr -> r0 = r0;
curr -> f1 = f;
curr -> r1 = r;
Append(out, curr);
}
}
}
//check to see if white pawn can capture left diagonally
f = f0 - 1, r = r0 + 1; //left diagonal
//if(!IsInCheck(f0, r0, f, r, b)){ //check to see if move to be made will put King in check
Expand Down Expand Up @@ -901,7 +966,34 @@ LL *getValidMovesPawn(int f0, int r0, Board *b){
curr -> r1 = r;
Append(out, curr);
}
//PROMOTION FOR BLACK PAWN
//EN PASSANT for BLACK PAWN
f = f0-1, r = r0-1;
if (f >= 0 && r >= 0){
if(b->board[f0-1][r0]->piece == PAWN && b->board[f0-1][r0]->color == WHITE){

if(r0 == 3 && b->board[f0-1][r0]->counter == 1){
MOVE *curr = malloc(sizeof(MOVE));
curr -> f0 = f0;
curr -> r0 = r0;
curr -> f1 = f;
curr -> r1 = r;
Append(out, curr);
}
}
}
f = f0+1, r = r0-1;
if (f < 8 && r >= 0){
if(b->board[f0+1][r0]->piece == PAWN && b->board[f0+1][r0]->color == WHITE){
if(r0 == 3 && b->board[f0+1][r0]->counter == 1){
MOVE *curr = malloc(sizeof(MOVE));
curr -> f0 = f0;
curr -> r0 = r0;
curr -> f1 = f;
curr -> r1 = r;
Append(out, curr);
}
}
}
}
return out;
}
Expand Down Expand Up @@ -1007,6 +1099,13 @@ LL *getValidMoves(Board * board, EColor player){
return out;
}

bool IsMated(Board *b, EColor color) {
LL *m = getValidMoves(b, color);
bool mated = (m->first == NULL);
DeleteList(m);
return mated;
}

void Castling(int f0, int r0, int f1, int r1, Board *b)
{
if (f1 == 6 && r1 == 0 && f0 == 4 && r0 == 0)
Expand Down Expand Up @@ -1114,7 +1213,7 @@ int EvaluateBoard(Board *b){
}
return value;
}

/*
MOVE *IdealMove(Board *b, EColor player){
LL *moves;
int score = EvaluateBoard(b);
Expand All @@ -1126,7 +1225,6 @@ MOVE *IdealMove(Board *b, EColor player){
DeleteBoard(b2);
return best;
}
/*
void GenerateTree(Board *source, TREE *out, int depth){
MOVE * valid[VALID_MOVE_SIZE];

Expand Down Expand Up @@ -1167,6 +1265,29 @@ void GenerateTree(Board *source, TREE *out, int depth){
}
*/

MOVE *IdealMove(Board *b, EColor color) {
srand(time(NULL));

LL *m = getValidMoves(b, color);
int size = GetListSize(m);
int n = rand() % size;

//iterate through n elements of the moves list
LLElem *curr = m->first;
for (; n >= 0; --n) {
curr = curr->next;
}

//deep copy move to allow freeing
MOVE *move = malloc(sizeof(MOVE));
move->f0 = ((MOVE *)curr->data)->f0;
move->r0 = ((MOVE *)curr->data)->r0;
move->f1 = ((MOVE *)curr->data)->f1;
move->r1 = ((MOVE *)curr->data)->r1;

DeleteList(m);
return move;
}



Expand Down Expand Up @@ -1342,5 +1463,17 @@ void DeleteList(LL *list){
curr = next;
}
free(list);
list = NULL;
}

int GetListSize(LL *list) {
int i = 0;
LLElem *curr = list->first;

while (curr->next) {
i++;
curr = curr->next;
}

return i;
}
Loading