Thread: Incorporating en-passant and Castling into a chess program

  1. #1
    Registered User
    Join Date
    Jan 2006
    Posts
    16

    Exclamation Incorporating en-passant and Castling into a chess program

    just wondering what to do here... i will link the code i have... i am using borland builder... thanks guys

    Code:
    #pragma hdrstop
    #include <condefs.h>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    #define BOARD_SIZE 8
    #define BLOCKSIZE 10
    
    typedef enum { empty = 0, pawn, rook, knight, bishop, queen, king } Piece;
    typedef enum { white, black } Colour;
    typedef enum {FALSE, TRUE} Bool;
    typedef struct {
    	Piece piece;
    	Colour colour;
    } Square;
    typedef Square Board[BOARD_SIZE][BOARD_SIZE];
    
    char BlackPieces[7] = {' ','p','r','n','b','q','k'};
    char WhitePieces[7] = {' ','P','R','N','B','Q','K'};
    
    
    Board *boards; /* Array of all boards */
    #define board boards[number_of_used_boards - 1]   /* Current (last) board */
    int number_of_allocated_boards;
    int number_of_used_boards;
    
    int read_line(char str[], int n);
    void init_board (void);
    void init_boards (void);
    void add_boards (void);
    void next_board (void);
    void print_board (int n);
    void print_last_board (void);
    void print_all_boards (void);
    int move_piece (Colour colour);
    
    Bool move_vh (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	      int from_col, int from_row, int to_col, int to_row);
    Bool move_dia (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	      int from_col, int from_row, int to_col, int to_row);
    Bool move_pawn (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	       const char *move, Colour colour);
    void convert_pawn (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    		   int col, int row);
    Bool move_queen (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    		 const char *move, Colour colour);
    Bool move_rook (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    		const char *move, Colour colour);
    Bool move_bishop (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    		 const char *move, Colour colour);
    Bool move_knight (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    		  const char *move, Colour colour);
    Bool move_king (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    		const char *move, Colour colour);
    void perform_move (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    		   int from_col, int from_row,
    		   int to_col, int to_row);
    int translate_col (char col);
    int translate_row (int row);
    Bool check_std_move (const char *move, int *from_col_num,
    		     int *to_col_num, int *from_row_num, int *to_row_num);
    
    
    //---------------------------------------------------------------------------
    #pragma argsused
    int main(int argc, char* argv[])
    {
            Colour next = white;
    	int res;
    
    	init_boards ();
    	print_last_board ();
    	while ((res = move_piece (next)) != 1)
    	{
    		if (res == 0) {
    			print_last_board ();
    			next = (next == white) ? black : white;
    		}
    		if (res == 3)
    			print_all_boards ();
    	}
            return 0;
    }
    /************************************************
     * check_std_move checks whether the move is a  *
     * regular a2a4 type move.                      *
     ************************************************/
    Bool check_std_move (const char *move, int *from_col_num,
    		     int *to_col_num, int *from_row_num, int *to_row_num)
    {
    	char from_col, to_col;
    	int  from_row, to_row;
    	int  items;
    
    	items = sscanf (move, "%c%d%c%d", &from_col, &from_row, &to_col, &to_row);
    	if (items != 4) {
    		fprintf (stderr, "ERROR: This is not a valid move.\n");
    		return FALSE;
    	}
    
    	*from_col_num = translate_col (from_col);
    	*to_col_num = translate_col (to_col);
    	*from_row_num = translate_row (from_row);
    	*to_row_num = translate_row (to_row);
    
    
    	return (!(*from_col_num < 0 || *to_col_num < 0 ||
    		  *from_row_num < 0 || *to_row_num < 0 ||
    		  (*from_col_num == *to_col_num && *from_row_num == *to_row_num)));
    }
    
    
    /************************************************
     *  translate_col turns column letter into      *
     *                column number                 *
     ************************************************/
    int
    translate_col (char col)
    {
    	if (col > 'h')
    		return -1;
    	if (col < 'a')
    		return -1;
    	return (col - 'a');
    }
    
    /************************************************
     *  translate_row turns row spec into           *
     *                row number                    *
     ************************************************/
    int
    translate_row (int row)
    {
    	if (row > BOARD_SIZE)
    		return -1;
    	if (row < 1)
    		return -1;
    	return (row - 1);
    }
    
    
    /************************************************
     * perform_move performs the specified move     *
     *              assuming it is valid            *
     ************************************************/
    void
    perform_move (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	      int from_col, int from_row,
    	      int to_col, int to_row)
    {
    	boards[length][to_row][to_col] = boards[length][from_row][from_col];
    	boards[length][from_row][from_col].piece = empty;
    	return;
    }
    
    /************************************************
     *  move_vh  handles a single vertical or       *
     *  horizontal move attempt
     *  return values:
     *    TRUE   successful move
     *    FALSE  unsuccessful move, try again.
     *
     ************************************************/
    Bool move_vh (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	      int from_col, int from_row, int to_col, int to_row)
    {
    	if (from_col == to_col) {
    		/* vertical move */
    		if (from_row < to_row) {
    			int i;
    			for (i = to_row - 1; i > from_row; i--)
    				if (boards[length][i][from_col].piece != empty)
    					return FALSE;
    			return TRUE;
    		} else {
    			int i;
    			for (i = to_row + 1; i < from_row; i++)
    				if (boards[length][i][from_col].piece != empty)
    					return FALSE;
    			return TRUE;
    		}
    	}
    
    	if (from_row == to_row) {
    		/* horizontal move */
    		if (from_col < to_col) {
    			int i;
    			for (i = to_col - 1; i > from_col; i--)
    				if (boards[length][from_row][i].piece != empty)
    					return FALSE;
    			return TRUE;
    		} else {
    			int i;
    			for (i = to_col + 1; i < from_col; i++)
    				if (boards[length][from_row][i].piece != empty)
    					return FALSE;
    			return TRUE;
    		}
    	}
    	return FALSE;
    }
    
    /************************************************
     *  move_dia  handles a single diagonal         *
     *  move attempt
     *  return values:
     *    TRUE   successful move
     *    FALSE  unsuccessful move, try again.
     *
     ************************************************/
    Bool move_dia (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	      int from_col, int from_row, int to_col, int to_row)
    {
    	if (abs(from_row - to_row)  ==  abs(from_col - to_col)) {
    		if (from_col < to_col) {
    			int diff = (from_row < to_row) ? 1 : -1;
    			int i, j;
    			for (i = to_col - 1, j = to_row - diff; i > from_col; i--, j -= diff)
    				if (boards[length][j][i].piece != empty)
    					return FALSE;
    			return TRUE;
    		} else {
    			int diff = (from_row < to_row) ? 1 : -1;
    			int i, j;
    			for (i = to_col + 1, j = to_row - diff; i < from_col; i++, j -= diff)
    				if (boards[length][j][i].piece != empty)
    					return FALSE;
    			return TRUE;
    		}
    	}
    	return FALSE;
    }
    
    /************************************************
     *  move_knight  handles a single move attempt   *
     *  return values:
     *    TRUE   successful move
     *    FALSE  unsuccessful move, try again.
     *
     ************************************************/
    Bool
    move_knight (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	       const char *move, Colour colour)
    {
    	int from_col, to_col, from_row, to_row;
    
    	if (!(check_std_move (move, &from_col, &to_col, &from_row, &to_row)) ||
    	    (boards[length][to_row][to_col].piece != empty &&
    	     boards[length][to_row][to_col].colour == colour)) {
    		fprintf (stderr, "ERROR: This is not "
    			 "a valid move for a knight.\n");
    		return FALSE;
    	}
    
    	if (abs((from_col - to_col) * (from_row - to_row)) == 2) {
    		perform_move (boards, length, from_col, from_row, to_col, to_row);
    		return TRUE;
    	}
    
    	fprintf (stderr, "ERROR: This is not "
    		 "a valid move for a knight.\n");
    	return FALSE;
    }
    
    /************************************************
     *  move_king  handles a single move attempt   *
     *  return values:
     *    TRUE   successful move
     *    FALSE  unsuccessful move, try again.
     *
     ************************************************/
    Bool
    move_king (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	       const char *move, Colour colour)
    {
    	int from_col, to_col, from_row, to_row;
    
    	if (!(check_std_move (move, &from_col, &to_col, &from_row, &to_row)) ||
    	    (boards[length][to_row][to_col].piece != empty &&
    	     boards[length][to_row][to_col].colour == colour)) {
    		fprintf (stderr, "ERROR: This is not "
    			 "a valid move for a king.\n");
    		return FALSE;
    	}
    
    	if (abs (from_col - to_col) <= 1 && abs (from_row - to_row) <= 1) {
     		perform_move (boards, length, from_col, from_row, to_col, to_row);
     		return TRUE;
    	}
    
    	fprintf (stderr, "ERROR: This is not "
    		 "a valid move for a king.\n");
    	return FALSE;
    }
    
    /************************************************
     *  move_queen  handles a single move attempt   *
     *  return values:
     *    TRUE   successful move
     *    FALSE  unsuccessful move, try again.
     *
     ************************************************/
    Bool
    move_queen (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	       const char *move, Colour colour)
    {
    	int from_col, to_col, from_row, to_row;
    
    	if (!(check_std_move (move, &from_col, &to_col, &from_row, &to_row)) ||
    	    (boards[length][to_row][to_col].piece != empty &&
    	     boards[length][to_row][to_col].colour == colour)) {
    		fprintf (stderr, "ERROR: This is not "
    			 "a valid move for a queen.\n");
    		return FALSE;
    	}
    
    	if (move_vh (boards, length, from_col, from_row, to_col, to_row)) {
    		perform_move (boards, length, from_col, from_row, to_col, to_row);
    		return TRUE;
    	}
    
    	if (move_dia (boards, length, from_col, from_row, to_col, to_row)) {
    		perform_move (boards, length, from_col, from_row, to_col, to_row);
    		return TRUE;
    	}
    
    	fprintf (stderr, "ERROR: This is not "
    		 "a valid move for a queen.\n");
    	return FALSE;
    }
    
    /************************************************
     *  move_rook  handles a single move attempt   *
     *  return values:
     *    TRUE   successful move
     *    FALSE  unsuccessful move, try again.
     *
     ************************************************/
    Bool
    move_rook (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	       const char *move, Colour colour)
    {
    	int from_col, to_col, from_row, to_row;
    
    	if (!(check_std_move (move, &from_col, &to_col, &from_row, &to_row)) ||
    	    (boards[length][to_row][to_col].piece != empty &&
    	     boards[length][to_row][to_col].colour == colour)) {
    		fprintf (stderr, "ERROR: This is not "
    			 "a valid move for a rook.\n");
    		return FALSE;
    	}
    	
    	if (move_vh (boards, length, from_col, from_row, to_col, to_row)) {
    		perform_move (boards, length, from_col, from_row, to_col, to_row);
    		return TRUE;
    	}
    
    	fprintf (stderr, "ERROR: This is not "
    		 "a valid move for a rook.\n");
    	return FALSE;
    }
    
    /************************************************
     *  move_bishop  handles a single move attempt   *
     *  return values:
     *    TRUE   successful move
     *    FALSE  unsuccessful move, try again.
     *
     ************************************************/
    Bool
    move_bishop (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	       const char *move, Colour colour)
    {
    	int from_col, to_col, from_row, to_row;
    
    	if (!(check_std_move (move, &from_col, &to_col, &from_row, &to_row)) ||
    	    (boards[length][to_row][to_col].piece != empty &&
    	     boards[length][to_row][to_col].colour == colour)) {
    		fprintf (stderr, "ERROR: This is not "
    			 "a valid move for a bishop.\n");
    		return FALSE;
    	}
    	
    	if (move_dia (boards, length, from_col, from_row, to_col, to_row)) {
    		perform_move (boards, length, from_col, from_row, to_col, to_row);
    		return TRUE;
    	}
    
    	fprintf (stderr, "ERROR: This is not "
    		 "a valid move for a bishop.\n");
    	return FALSE;
    }
    
    /************************************************
     * convert_pawn changes the pawn into a queen   *
     ************************************************/
    
    void
    convert_pawn (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	      int col, int row)
    {
    	boards[length][row][col].piece = queen;
    }
    
    /************************************************
     *  move_pawn  handles a single move attempt    *
     *  return values:
     *    TRUE  successful move
     *    FALSE  unsuccessful move, try again.
     *
     ************************************************/
    Bool
    move_pawn (Square boards[][BOARD_SIZE][BOARD_SIZE], int length,
    	       const char *move, Colour colour)
    {
    	int diff = (colour == white) ? 1 : -1;
    	int initial = (colour == white) ? 1 : 6;
    	int last = (colour == white) ? 7 : 0;
    	int from_col, to_col, from_row, to_row;
    
    	if (check_std_move (move, &from_col, &to_col, &from_row, &to_row))
    	{
    		switch (abs(from_col - to_col)) {
    		case 0: if (from_row + diff == to_row &&
    			    boards[length][from_row + diff][from_col].piece 
    			    == empty) {
    		        perform_move (boards, length, from_col, from_row, 
    				      to_col, to_row);
    			if (to_row == last)
    				convert_pawn (boards, length, to_col, to_row);
    		        return TRUE;
    	        }  
    			if (from_row == initial &&  
    			    from_row + 2 * diff == to_row &&
    			    boards[length][from_row + diff][from_col].piece == empty &&
    			    boards[length][from_row + 2 * diff][from_col].piece == empty) {
    				perform_move (boards, length, from_col, from_row, to_col, to_row);
    				return TRUE;
    			}  
    			/* Move not valid */
    			break;
    		case 1: if (from_row + diff == to_row &&
    			    boards[length][from_row + diff][to_col].piece != empty &&
    			    boards[length][from_row + diff][to_col].colour != colour) {
    		        perform_move (boards, length, from_col, from_row, to_col, to_row);
    			if (to_row == last)
    				convert_pawn (boards, length, to_col, to_row);
    		        return TRUE;
    	        }  
    			/* Move not valid */
    			break;
    		default: /* Move not valid */
    			break;
    		}
    	}
    	fprintf (stderr, "ERROR: This is not a valid move for a pawn.\n");
    	return FALSE;
    }
    
    
    /************************************************
     *  move_piece  handles a single move attempt   *
     *  return values:
     *    0  successful move
     *    1  exit
     *    2  unsuccessful move, try again.
     *    3  print boards
     *
     ************************************************/
    
    int 
    move_piece (Colour colour)
    {
    	char move[5];
    	char from_col;
    	int  from_col_num;
    	int  from_row;
    	int  from_row_num;
    	int  items;
    	Bool move_valid;
    
    	printf ((colour == white) ? "White: " : "Black: ");
    	read_line (move, 4);
    	if (strcmp(move, "exit") == 0)
    		return 1;
    	if (strcmp(move, "prin") == 0)
    		return 3;
    	items = sscanf (move, "%c%d", &from_col, &from_row);
    	if (items != 2) {
    		fprintf (stderr, "ERROR: This is not a valid move.\n");
    		return 2;
    	}
    	from_col_num = translate_col (from_col);
    	from_row_num = translate_row (from_row);
    
    	if (from_col_num < 0 ||
    	    from_row_num < 0 ||
    	    board[from_row_num][from_col_num].colour != colour ||
    	    board[from_row_num][from_col_num].piece == empty) {
    		fprintf (stderr, "ERROR: This is not a valid move.\n");
    		return 2;		
    	}
    
    	switch (board[from_row_num][from_col_num].piece) {
    	case pawn: move_valid = move_pawn (boards, number_of_used_boards, 
    				     move, colour);
    		break;
    	case rook: move_valid = move_rook (boards, number_of_used_boards,
                                         move, colour);
    		break;
    	case knight: move_valid = move_knight (boards, number_of_used_boards,
    				     move, colour);
    		break;
    	case bishop: move_valid = move_bishop (boards, number_of_used_boards,
    				     move, colour);
    		break;
    	case queen: move_valid = move_queen (boards, number_of_used_boards, 
    				     move, colour);
    		break;
    	case king: move_valid = move_king (boards, number_of_used_boards,
    		                     move, colour);
    		break;
    	case empty:
    		fprintf (stderr, "We should not be getting here!\n");
    		return 1;
    	default:
    		fprintf (stderr, "Moving this figure is "
    			         "not implemented yet.\n");
    		return 2;
    	}
    
    	if (move_valid)
    		next_board ();
    
    	return (move_valid ? 0 : 2);
    }
    
    /************************************************
     *  init_board initializes the board            *
     ************************************************/
    void
    init_board (void)
    {
    	int i, j;
    
    	for (i = 0; i < BOARD_SIZE; i++)
    		for (j = 0; j < BOARD_SIZE; j++) {
    			boards[0][i][j].piece = empty;
    			boards[0][i][j].colour = white;
    		}
    
    	for (j = 0; j < BOARD_SIZE; j++) {
    		boards[0][1][j].piece = pawn;
    		/* boards[0][1][j].colour = white; */
    		boards[0][BOARD_SIZE - 2][j].piece = pawn;
    		boards[0][BOARD_SIZE - 2][j].colour = black;
    	}
    
    	for (j = 0; j < BOARD_SIZE; j++)
    		boards[0][BOARD_SIZE - 1][j].colour = black;
    
    	boards[0][0][0].piece = boards[0][0][7].piece = rook;
    	boards[0][7][0].piece = boards[0][7][7].piece = rook;
    	boards[0][0][1].piece = boards[0][0][6].piece = knight;
    	boards[0][7][1].piece = boards[0][7][6].piece = knight;
    	boards[0][0][2].piece = boards[0][0][5].piece = bishop;
    	boards[0][7][2].piece = boards[0][7][5].piece = bishop;
    	boards[0][0][3].piece = queen;
    	boards[0][7][3].piece = queen;
    	boards[0][0][4].piece = king;
    	boards[0][7][4].piece = king;
    
    	return;
    }
    
    /************************************************
     *  init_boards initializes the array of board  *
     ************************************************/
    void
    init_boards (void)
    {
    	boards = (Board *)calloc(BLOCKSIZE, sizeof (Board));
    
    	if (boards == NULL) {
    		fprintf (stderr, "ERROR: Unable to allocate "
    			         "initial boards!\n");
    		exit(1);
    	}
    
    	number_of_allocated_boards = BLOCKSIZE;
    	number_of_used_boards = 0;
    	init_board();
    	next_board();
    }
    
    /************************************************
     *  print_board prints the board #n             *
     ************************************************/
    void
    print_board (int n)
    {
    	int i, j;
    	
    	printf ("\n**abcdefgh**\n**--------**\n");
    	for (i = BOARD_SIZE; i > 0 ; i--) {
    		printf ("%i|", i);
    		for (j = 0; j < BOARD_SIZE; j++) {
    			printf ("%c", (boards[n][i-1][j].colour == white) ?
    				WhitePieces[boards[n][i-1][j].piece] : 
    				BlackPieces[boards[n][i-1][j].piece]);	
    		}
    		printf ("|%i\n", i);
    	}
    	printf ("**--------**\n**abcdefgh**  ");
    
    	return;
    }
    
    /************************************************
     *  print_last_board prints the board           *
     *  #number_of_used_boards-1                    *
     ************************************************/
    void
    print_last_board (void)
    {
    	print_board (number_of_used_boards-1);
    }
    
    /************************************************
     *  print_all_boards prints all boards          *
     ************************************************/
    void
    print_all_boards (void)
    {
    	int i;
    	for (i = 0; i < number_of_used_boards; i++) {
    		print_board (i);
    	}
    }
    
    /************************************************
     *  add_boards enlarges the array               *
     ************************************************/
    void add_boards (void) {
    	Board *newboards;
    
    	newboards = (Board *) realloc(boards, 
    			    (number_of_allocated_boards + BLOCKSIZE) 
    			    * sizeof (Board));
    	if (newboards == NULL) {
    		fprintf (stderr, "ERROR: out of memory");
    		exit(1);
    	}
    	number_of_allocated_boards += BLOCKSIZE;
    }
    
    /************************************************
     *  next_board moves to next board              *
     *  note: we always keep an additional copy of  *
     *        the last board                        *
     ************************************************/
    void next_board (void) {
    	int i, j;
    	if (number_of_allocated_boards - 1 <= number_of_used_boards)
    		add_boards();
    	for (i = 0; i < BOARD_SIZE; i++) {
    		for (j = 0; j < BOARD_SIZE; j++) {
    			boards[number_of_used_boards + 1][i][j] = 
    				boards[number_of_used_boards][i][j];
    		}
    	}
    	number_of_used_boards++;
    }
    
    /************************************************
     *  read_line reads a complete line storing n   *
     *            chars                             *
     ************************************************/
    int 
    read_line(char str[], int n)
    {
    	char ch;
    	int i = 0;
    
    	while ((ch = getchar()) != '\n')
    		if (i < n)
    			str[i++] = ch;
    
    	str[i] = '\0';
    	return i;
    }

  2. #2
    Anti-Poster
    Join Date
    Feb 2002
    Posts
    1,401
    Yup, looks like a lot of code. Got any specific problems? After all, I'm pretty sure you didn't write the code. If you did, your name would probably be Tom Kerrigan, since this is Tom Kerrigan's Simple Chess Program.
    If I did your homework for you, then you might pass your class without learning how to write a program like this. Then you might graduate and get your degree without learning how to write a program like this. You might become a professional programmer without knowing how to write a program like this. Someday you might work on a project with me without knowing how to write a program like this. Then I would have to do you serious bodily harm. - Jack Klein

  3. #3
    aoeuhtns
    Join Date
    Jul 2005
    Posts
    581
    to incorporate en passant, just make a way to store the last square moved to, every time a move is made. Then check...

    Incorporating castling simply requires a few variables for which castles may be castled with, and some threat-checking if that's not there already...
    There are 10 types of people in this world, those who cringed when reading the beginning of this sentence and those who salivated to how superior they are for understanding something as simple as binary.

Popular pages Recent additions subscribe to a feed