#include "chess_board.h" #include #include #include "stdio.h" #include #include #include "pieces.hpp" #define MARGIN 300 #define PAWN_WHITE 0u #define PAWN_BLACK 1u #define KING_WHITE 2u #define KING_BLACK 3u #define ROOK_WHITE 4u #define ROOK_BLACK 5u #define KNIGHT_WHITE 6u #define KNIGHT_BLACK 7u #define BISHOP_WHITE 8u #define BISHOP_BLACK 9u #define QUEEN_WHITE 10u #define QUEEN_BLACK 11u #define SQUARE_EMPTY 12u #define LIGHT_OFF 0u #define POTENTIAL_MOVE 1u #define POTENTIAL_TAKE 2u #define SUGGESTED_MOVE 3u #define ERROR_MOVE 4u #define PEICE_ORIGIN 5u #define PEICE_NEEDS_TO_BE_HERE 6u #define POTENTIAL_CASTLE 7u #define GAME_STATE_IDLE 0u #define GAME_STATE_P1_TURN_BEGINING 1u #define GAME_STATE_P1_TURN_IN_PROGRESS 2u #define GAME_STATE_P1_TURN_TAKING 3u #define GAME_STATE_P2_TURN_BEGINING 4u #define GAME_STATE_P2_TURN_IN_PROGRESS 5u #define GAME_STATE_P2_TURN_TAKING 6u #define GAME_STATE_ERROR_DETECTED 7u const char File_Names[12][17] = {"pawn_white.bmp", "pawn_black.bmp", "king_white.bmp", "king_black.bmp", "tower_white.bmp", "tower_black.bmp", "horse_white.bmp", "horse_black.bmp", "bishop_white.bmp", "bishop_black.bmp", "queen_white.bmp", "queen_black.bmp", }; static int Height; static int Width; static SDL_Texture * Board_Texture; static SDL_Rect Rectangle; static int Board_Width; static uint8_t Board_State[12][8] = {{0}}; static uint8_t Current_Binary_Board[12] = {0}; static uint8_t Saved_Binary_Board[12] = {0}; static uint8_t Board_Lights[12][8] = {{0}}; SDL_Surface *bitmapSurface = NULL; SDL_Texture * bitmapTextures[12] = {NULL}; static uint8_t Game_State = GAME_STATE_P1_TURN_BEGINING; static uint8_t Last_Game_State = GAME_STATE_P1_TURN_BEGINING; static bool White_Turn = true; static uint8_t Selected_Peice = SQUARE_EMPTY; static uint8_t Error_Count = 0u; static uint8_t Taken_Peice = SQUARE_EMPTY; static bool Check[2u] = {false, false}; static uint8_t King_Locations[2u][2u] = {{7,4}, {0,4}}; static bool Castling_Allowed[2u][2u] = {{true, true}, {true, true}}; /** * @brief Function for figuring out if the current column is one of the jail columns. * @note Columns 8-12 are in the jail * @param j: The column under question. * @retval True if its a jail column, else false. */ static inline bool square_in_jail(uint8_t j) { return (j > 8u); } /** * @brief Function for clearing all of the lights on the board. Except for error moves. * @retval None */ static void clear_lights(void) { for (size_t i = 0; i < 8; i++) { for (size_t j = 0; j < 8; j++) { if(Board_Lights[i][j] != ERROR_MOVE) { Board_Lights[i][j] = LIGHT_OFF; } } } } /** * @brief Function for determining if the peice is on the white team or on the black team. * @note Peices should be enumerated even if white and odd if black. * @param piece: The peice under question. * @retval Return true if on the white team, else false. */ static bool white_team(uint8_t piece) { return ((piece % 2u) == 0u); } /** * @brief Function for determining if two peices are on the same team or not. * @param piece_one: Peice one ofcoarse. * @param piece_two: Peice two obviously. * @retval True if on opposite teams, else false. */ static bool opposite_teams(uint8_t piece_one, uint8_t piece_two) { return (((piece_one % 2u) == 0u) ^ ((piece_two % 2u) == 0u)); } /** * @brief Function for marking potential moves for pawns. * @param row: row to move to * @param column: column to move to * @retval None */ static void pawn_move(uint8_t row, uint8_t column) { if(Board_State[row][column] == SQUARE_EMPTY) { Board_Lights[row][column] = POTENTIAL_MOVE; } } /** * @brief Function for "casting" a ray in any direction, vertical, horizontal, or diagonal. If the ray hits someone from the other team * or the end of the board the array will be terminated. * @param direction_r: Row direction * @param direction_c: Column direction * @param row: current row location * @param column: current column location * @param piece_one: the peice that is casting the ray. * @retval None */ static void cast_a_ray(int8_t direction_r, int8_t direction_c, uint8_t row, uint8_t column, uint8_t piece_one) { bool loop = true; int8_t x = column; int8_t y = row; while (loop) { x += direction_c; y += direction_r; if((x < 0) || (y < 0) || (x >= 8) || (y >= 8)) { loop = false; } else if (Board_State[x][y] == SQUARE_EMPTY) { Board_Lights[x][y] = POTENTIAL_MOVE; } else if (opposite_teams(piece_one, Board_State[x][y])) { Board_Lights[x][y] = POTENTIAL_TAKE; /* once we take a peice we can no longer take anymore */ loop = false; } else { loop = false; } } } /** * @brief Marking a peice for taking. * @param row: Row ofcoarse * @param column: Column obviously * @retval None */ static void pawn_take(uint8_t row, uint8_t column) { if (Board_State[row][column] < SQUARE_EMPTY) { Board_Lights[row][column] = POTENTIAL_TAKE; } } /** * @brief Check to see if the square is safe from the other team. * @param column: Column of potential move * @param row: Row of the potential move * @retval True if the square is safe, else is false */ bool square_is_safe(uint8_t column, uint8_t row) { bool ret_val = true; int8_t direction = White_Turn ? -1 : 1; /* first check if pawns can take us */ if ((row >= 1u) && ((White_Turn ? PAWN_BLACK : PAWN_WHITE) == Board_State[column + direction][row - 1u])) { //can be eaten by a pawn, not safe. return false; } if ((row <= 6u) && ((White_Turn ? PAWN_BLACK : PAWN_WHITE) == Board_State[column + direction][row + 1u])) { //can be eaten by a pawn, not safe. return false; } /* Other King */ int8_t start_r = (row == 0u) ? 0 : -1; int8_t stop_r = (row == 7u) ? 0 : 1; int8_t start_c = (column == 0u) ? 0 : -1; int8_t stop_c = (column == 7u) ? 0 : 1; for (int8_t up_down = start_r; up_down <= stop_r; up_down++) { for (int8_t left_right = start_c; left_right <= stop_c; left_right++) { int8_t x = column + left_right; int8_t y = row + up_down; if ((White_Turn ? KING_BLACK : KING_WHITE) == Board_State[x][y]) { return false; } } } for (uint8_t direction = 0u; direction < 4u; direction++) { int8_t up_down_step; int8_t left_right_step; if (direction == 0u) { up_down_step = 1; left_right_step = 0; } else if (direction == 1u) { up_down_step = 0; left_right_step = 1; } else if (direction == 2u) { up_down_step = -1; left_right_step = 0; } else { up_down_step = 0; left_right_step = -1; } /* Rooks and queens */ bool loop = true; int8_t x = column; int8_t y = row; while (loop) { x += left_right_step; y += up_down_step; if ((x < 0) || (y < 0) || (x >= 8) || (y >= 8)) { loop = false; } else if (Board_State[x][y] == SQUARE_EMPTY) { /* Do nothing */ } else if (((White_Turn ? ROOK_BLACK : ROOK_WHITE) == Board_State[x][y]) || ((White_Turn ? QUEEN_BLACK : QUEEN_WHITE) == Board_State[x][y])) { return false; } else { loop = false; } } } /* Bishops and queens */ for (uint8_t direction = 0u; direction < 4u; direction++) { int8_t up_down_step; int8_t left_right_step; if (direction == 0u) { up_down_step = 1; left_right_step = 1; } else if (direction == 1u) { up_down_step = -1; left_right_step = 1; } else if (direction == 2u) { up_down_step = -1; left_right_step = -1; } else { up_down_step = 1; left_right_step = -1; } bool loop = true; int8_t x = column; int8_t y = row; while (loop) { x += left_right_step; y += up_down_step; if ((x < 0) || (y < 0) || (x >= 8) || (y >= 8)) { loop = false; } else if (Board_State[x][y] == SQUARE_EMPTY) { /* do nothing */ } else if (((White_Turn ? BISHOP_BLACK : BISHOP_WHITE) == Board_State[x][y]) || ((White_Turn ? QUEEN_BLACK : QUEEN_WHITE) == Board_State[x][y])) { return false; } else { loop = false; } } } /* Knights */ for (uint8_t direction = 0u; direction < 4u; direction++) { int8_t up_down_step; int8_t left_right_step; if (direction == 0u) { up_down_step = 2; left_right_step = 0; } else if (direction == 1u) { up_down_step = 0; left_right_step = 2; } else if (direction == 2u) { up_down_step = -2; left_right_step = 0; } else { up_down_step = 0; left_right_step = -2; } for (uint8_t i = 0u; i < 2u; i++) { if ((direction % 2u) == 0u) { left_right_step = (i == 0u) ? -1 : 1; } else { up_down_step = (i == 0u) ? -1 : 1; } int8_t x = (int8_t)column + left_right_step; int8_t y = (int8_t)row + up_down_step; if ((x >= 0) && (y >= 0) && (x < 8) && (y < 8)) { if ((White_Turn ? KNIGHT_BLACK : KNIGHT_WHITE) == Board_State[x][y]) { return false; } } } } return true; } /** * @brief Function for marking the potential moves. * @param piece: Peice that we are marking the potential moves for. * @param row: Current row location of the peice. * @param column: Current column location of the peice. * @retval None */ static void Mark_Potential_Moves(uint8_t piece, uint8_t row, uint8_t column) { switch (piece) { case PAWN_WHITE : case PAWN_BLACK: { int8_t direction = White_Turn ? -1 : 1; if (column == (White_Turn ? 6u : 1u)) { if(Board_State[column + direction][row] == SQUARE_EMPTY) { pawn_move(column + (direction * 2u), row); } } pawn_move(column + direction, row); if ((row >= 1u) && opposite_teams(piece, Board_State[column + direction][row - 1u])) { pawn_take(column + direction, row - 1u); } if ((row <= 6u) && opposite_teams(piece, Board_State[column + direction][row + 1u])) { pawn_take(column + direction, row + 1u); } break; } case ROOK_WHITE: case ROOK_BLACK: { for (uint8_t direction = 0u; direction < 4u; direction++) { int8_t up_down_step; int8_t left_right_step; if(direction == 0u) { up_down_step = 1; left_right_step = 0; } else if(direction == 1u) { up_down_step = 0; left_right_step = 1; } else if (direction == 2u) { up_down_step = -1; left_right_step = 0; } else { up_down_step = 0; left_right_step = -1; } cast_a_ray(up_down_step, left_right_step, row, column, piece); } break; } case KNIGHT_WHITE: case KNIGHT_BLACK: { for (uint8_t direction = 0u; direction < 4u; direction++) { int8_t up_down_step; int8_t left_right_step; if (direction == 0u) { up_down_step = 2; left_right_step = 0; } else if (direction == 1u) { up_down_step = 0; left_right_step = 2; } else if (direction == 2u) { up_down_step = -2; left_right_step = 0; } else { up_down_step = 0; left_right_step = -2; } for (uint8_t i = 0u; i < 2u; i++) { if((direction % 2u) == 0u) { left_right_step = (i == 0u) ? -1 : 1; } else { up_down_step = (i == 0u) ? -1 : 1; } int8_t x = (int8_t)column + left_right_step; int8_t y = (int8_t)row + up_down_step; if ((x >= 0) && (y >= 0) && (x < 8) && (y < 8)) { if (Board_State[x][y] == SQUARE_EMPTY) { Board_Lights[x][y] = POTENTIAL_MOVE; } else if (opposite_teams(piece, Board_State[x][y])) { Board_Lights[x][y] = POTENTIAL_TAKE; } } } } break; } case BISHOP_WHITE: case BISHOP_BLACK: { for (uint8_t direction = 0u; direction < 4u; direction++) { int8_t up_down_step; int8_t left_right_step; if (direction == 0u) { up_down_step = 1; left_right_step = 1; } else if (direction == 1u) { up_down_step = -1; left_right_step = 1; } else if (direction == 2u) { up_down_step = -1; left_right_step = -1; } else { up_down_step = 1; left_right_step = -1; } cast_a_ray(up_down_step, left_right_step, row, column, piece); } break; } case QUEEN_WHITE: case QUEEN_BLACK: { for (int8_t up_down = -1; up_down < 2; up_down++) { for (int8_t left_rigth = -1; left_rigth < 2; left_rigth++) { cast_a_ray(up_down, left_rigth, row, column, piece); } } break; } case KING_WHITE: case KING_BLACK: { int8_t start_r = (row == 0u) ? 0 : -1; int8_t stop_r = (row == 7u) ? 0 : 1; int8_t start_c = (column == 0u) ? 0 : -1; int8_t stop_c = (column == 7u) ? 0 : 1; for (int8_t up_down = start_r; up_down <= stop_r; up_down++) { for (int8_t left_right = start_c; left_right <= stop_c; left_right++) { int8_t x = column + left_right; int8_t y = row + up_down; if (square_is_safe(x, y)) { if (Board_State[x][y] == SQUARE_EMPTY) { Board_Lights[x][y] = POTENTIAL_MOVE; } else if (opposite_teams(piece, Board_State[x][y])) { Board_Lights[x][y] = POTENTIAL_TAKE; } } } } uint8_t white_black_idx = White_Turn ? 0u : 1u; uint8_t kings_row = White_Turn ? 7u : 0u; //Can only castle if not currently in check if(square_is_safe(column, row)) { // Queen side castle if(Castling_Allowed[white_black_idx][0u] && (Board_State[kings_row][1u] == SQUARE_EMPTY) && (Board_State[kings_row][2u] == SQUARE_EMPTY) && (Board_State[kings_row][3u]) == SQUARE_EMPTY) { Board_Lights[kings_row][2u] = POTENTIAL_MOVE; } // King side castle if (Castling_Allowed[white_black_idx][1u] && (Board_State[kings_row][5u] == SQUARE_EMPTY) && (Board_State[kings_row][6u] == SQUARE_EMPTY)) { Board_Lights[kings_row][6u] = POTENTIAL_MOVE; } } Board_Lights[column][row] = PEICE_ORIGIN; break; } default: break; } } /** * @brief Function for marking the taken peices potention moves to jail. */ void Mark_Taken_Peice_Spots_In_Jail(void) { uint8_t add = (white_team(Taken_Peice) ? 8u : 10u); switch (Taken_Peice) { /* Pawns just send them to jail, we dont care where */ case PAWN_WHITE: case PAWN_BLACK: { for (uint8_t j = 0; j < 2u; j++) { for (uint8_t i = 0; i < 4u; i++) { if(Board_State[add + j][i] != Taken_Peice) { Board_State[add + j][i] = Taken_Peice; Taken_Peice = SQUARE_EMPTY; return; } } } break; } case ROOK_WHITE: case ROOK_BLACK: case KNIGHT_WHITE: case KNIGHT_BLACK: case BISHOP_WHITE: case BISHOP_BLACK: case QUEEN_WHITE: case QUEEN_BLACK: { uint8_t jail_row = (Taken_Peice / 2u) + 2u; if (Board_State[add][jail_row] != Taken_Peice) { Board_Lights[add][jail_row] = PEICE_NEEDS_TO_BE_HERE; } if (Board_State[add + 1u][jail_row] != Taken_Peice) { Board_Lights[add + 1u][jail_row] = PEICE_NEEDS_TO_BE_HERE; } break; } default: { break; } } } /** * @brief Function for switching the players turn. Incharge of handling the state machine reset. */ void Switch_Turns(void) { Game_State = (White_Turn ? GAME_STATE_P2_TURN_BEGINING : GAME_STATE_P1_TURN_BEGINING); White_Turn = !White_Turn; } /** * @brief Function for checking the selected peice to see if we are moving the king. * If we are then we also want to update the new location of the corresponding king. * @param row: Current row location of the peice. * @param column: Current column location of the peice. * @retval None */ void Check_If_Moving_King(uint8_t row, uint8_t column) { uint8_t white_black_idx = White_Turn ? 0u : 1u; if((Selected_Peice == KING_WHITE) || (Selected_Peice == KING_BLACK)) { King_Locations[white_black_idx][0u] = row; King_Locations[white_black_idx][1u] = column; Castling_Allowed[white_black_idx][0u] = false; Castling_Allowed[white_black_idx][1u] = false; } // Disable the castling of the corresponding side if the rook is being moved. else if (((Selected_Peice == ROOK_WHITE) && (row == 7u)) || ((Selected_Peice == ROOK_BLACK) && (row == 0u))) { if (column == 0u) { Castling_Allowed[white_black_idx][0u] = false; } else if (column == 7u) { Castling_Allowed[white_black_idx][1u] = false; } } } /** * @brief Function for toggeling a square's state. * @param j: row location that was toggled. * @param i: column location that was toggled. * @retval None */ void Board_Square_Was_Toggled(uint8_t j, uint8_t i) { switch (Game_State) { case GAME_STATE_ERROR_DETECTED: { if (Board_Lights[j][i] == PEICE_ORIGIN) { Board_State[j][i] = Selected_Peice; Selected_Peice = SQUARE_EMPTY; clear_lights(); Last_Game_State--; } else if (Board_Lights[j][i] == PEICE_NEEDS_TO_BE_HERE) { if (j < 8u) { Board_State[j][i] = Selected_Peice; Selected_Peice = SQUARE_EMPTY; Board_Lights[j][i] = LIGHT_OFF; } else { Board_State[j][i] = Taken_Peice; uint8_t board_column = (j / 2u) * 2u; if(Board_Lights[board_column][i] == PEICE_NEEDS_TO_BE_HERE) { Board_Lights[board_column][i] = LIGHT_OFF; } if(Board_Lights[board_column + 1u][i] == PEICE_NEEDS_TO_BE_HERE) { Board_Lights[board_column + 1u][i] = LIGHT_OFF; } Taken_Peice = SQUARE_EMPTY; } if ((Selected_Peice == SQUARE_EMPTY) && (Taken_Peice == SQUARE_EMPTY)) { Last_Game_State = (White_Turn ? GAME_STATE_P2_TURN_BEGINING : GAME_STATE_P1_TURN_BEGINING); White_Turn = !White_Turn; } } else if (Board_Lights[j][i] == ERROR_MOVE) { Error_Count--; Board_Lights[j][i] = LIGHT_OFF; if(Error_Count == 0u) { Game_State = Last_Game_State; } } else { Error_Count++; Board_Lights[j][i] = ERROR_MOVE; } break; } case GAME_STATE_IDLE: { break; } case GAME_STATE_P2_TURN_BEGINING: case GAME_STATE_P1_TURN_BEGINING: { /* We are waiting till the player who's turn it is picks up a peice that is on their team */ if ((j < 8u) && (Board_State[j][i] != SQUARE_EMPTY) && (white_team(Board_State[j][i]) == White_Turn)) { Mark_Potential_Moves(Board_State[j][i], i, j); Selected_Peice = Board_State[j][i]; Board_State[j][i] = SQUARE_EMPTY; Game_State++; Board_Lights[j][i] = PEICE_ORIGIN; } else { Last_Game_State = Game_State; Game_State = GAME_STATE_ERROR_DETECTED; Board_Lights[j][i] = ERROR_MOVE; Error_Count++; } break; } case GAME_STATE_P2_TURN_IN_PROGRESS: case GAME_STATE_P1_TURN_IN_PROGRESS: { /* We are waiting till the player who's turn it is picks up a peice that is on their team */ if (Board_Lights[j][i] == POTENTIAL_MOVE) { Check_If_Moving_King(j, i); Board_State[j][i] = Selected_Peice; Selected_Peice = SQUARE_EMPTY; clear_lights(); Switch_Turns(); } else if (Board_Lights[j][i] == POTENTIAL_TAKE) { Taken_Peice = Board_State[j][i]; Board_State[j][i] = SQUARE_EMPTY; Game_State = (White_Turn ? GAME_STATE_P1_TURN_TAKING : GAME_STATE_P2_TURN_TAKING); Mark_Taken_Peice_Spots_In_Jail(); clear_lights(); Board_Lights[j][i] = PEICE_NEEDS_TO_BE_HERE; } else if (Board_Lights[j][i] == PEICE_ORIGIN) { Board_State[j][i] = Selected_Peice; Selected_Peice = SQUARE_EMPTY; clear_lights(); Game_State--; } else { Last_Game_State = Game_State; Game_State = GAME_STATE_ERROR_DETECTED; Board_Lights[j][i] = ERROR_MOVE; Error_Count++; } break; } case GAME_STATE_P2_TURN_TAKING: case GAME_STATE_P1_TURN_TAKING: { if (Board_Lights[j][i] == PEICE_NEEDS_TO_BE_HERE) { if(j < 8u) { Check_If_Moving_King(j, i); Board_State[j][i] = Selected_Peice; Selected_Peice = SQUARE_EMPTY; Board_Lights[j][i] = LIGHT_OFF; } else { Board_State[j][i] = Taken_Peice; Board_Lights[(j / 2u) * 2u][i] = LIGHT_OFF; Board_Lights[(j / 2u) * 2u + 1u][i] = LIGHT_OFF; Taken_Peice = SQUARE_EMPTY; } } else { Last_Game_State = Game_State; Game_State = GAME_STATE_ERROR_DETECTED; Board_Lights[j][i] = ERROR_MOVE; Error_Count++; } if ((Selected_Peice == SQUARE_EMPTY) && (Taken_Peice == SQUARE_EMPTY)) { Switch_Turns(); } break; } default: { break; } } } /** * @brief The Board changed so now we have to see what is different and act accordingly. * @note Yes i know the design of this seems really bad but it's important to remember this is supposed to simulate the chess board I'm creating. * so I'm designing it this way because of the hardware that I'm using. * @retval None */ void Board_Changed(void) { for (uint8_t j = 0u; j < 12u; j++) { uint8_t difference = (Current_Binary_Board[j] ^ Saved_Binary_Board[j]); if (difference != 0u) { for (uint8_t i = 0u; i < 8u; i++) { if((difference & (1u << i)) != 0u) { Board_Square_Was_Toggled(j, i); } } } Saved_Binary_Board[j] = Current_Binary_Board[j]; } } /** * @brief Function for registering an incoming click * @param p_renderer: Pointer to the renderer * @param x: x location of the click * @param y: y location of the click * @retval */ void click(SDL_Renderer *p_renderer, int x, int y) { SDL_Point const point = {x, y}; const int square_size = Board_Width / 8; Rectangle.w = Board_Width + (4 * square_size); Rectangle.h = Board_Width; Rectangle.x = ((Width - Board_Width) / 2) - (2 * square_size); Rectangle.y = (Height - Board_Width) / 2; if (SDL_PointInRect(&point, &Rectangle)) { Rectangle.x = (Width - Board_Width) / 2; Rectangle.w = Board_Width; int starting_y = Rectangle.y; const int starting_x = Rectangle.x; Rectangle.w = square_size; Rectangle.h = square_size; for (size_t j = 0; j < 8; j++) { Rectangle.x = starting_x; for (size_t i = 0; i < 8; i++) { if(SDL_PointInRect(&point, &Rectangle)) { Current_Binary_Board[j] ^= (1u << i); Board_Changed(); goto draw_square; } Rectangle.x += square_size; } Rectangle.y += square_size; } Rectangle.x = ((Width - Board_Width) / 2) - (2 * square_size); /* Now we draw the jail */ for (size_t j = 8; j < 12; j++) { Rectangle.y = starting_y; for (size_t i = 0; i < 8; i++) { if (SDL_PointInRect(&point, &Rectangle)) { Current_Binary_Board[j] ^= (1u << i); Board_Changed(); goto draw_square; } Rectangle.y += square_size; } /*If we are at the end of second jail row, jump to the other side */ if (j == 9) { Rectangle.x += (Board_Width + square_size); } else { Rectangle.x += square_size; } } draw_square: SDL_SetRenderTarget(p_renderer, Board_Texture); draw_board(p_renderer); SDL_RenderCopy(p_renderer, Board_Texture, NULL, NULL); SDL_RenderPresent(p_renderer); } } /** * @brief Function for resizing the display of the board * @param p_renderer: pointer to the renderer * @param w: width of the new window * @param h: hight of the new window * @retval None */ void chess_board_resize(SDL_Renderer *p_renderer, int w, int h) { Width = w; Height = h; SDL_DestroyTexture(Board_Texture); Board_Texture = SDL_CreateTexture(p_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, w, h); Board_Width = ((w > h) ? h : w) - MARGIN; // get rid of rounding errors Board_Width -= Board_Width % 8; } /** * @brief Function for initializing the board * @note * @param *p_renderer pointer to the renderer: * @retval None */ void chess_board_init(SDL_Renderer *p_renderer) { for (uint8_t i = 0u; i < 12u; i++) { for (uint8_t j = 0u; j < 8u; j++) { Board_State[i][j] = SQUARE_EMPTY; } } Current_Binary_Board[0] = 0xFF; Current_Binary_Board[1] = 0xFF; Current_Binary_Board[6] = 0xFF; Current_Binary_Board[7] = 0xFF; Saved_Binary_Board[0] = 0xFF; Saved_Binary_Board[1] = 0xFF; Saved_Binary_Board[6] = 0xFF; Saved_Binary_Board[7] = 0xFF; //Place black pieces Board_State[0][0] = ROOK_BLACK; Board_State[0][7] = ROOK_BLACK; Board_State[0][1] = KNIGHT_BLACK; Board_State[0][6] = KNIGHT_BLACK; Board_State[0][2] = BISHOP_BLACK; Board_State[0][5] = BISHOP_BLACK; Board_State[0][3] = QUEEN_BLACK; Board_State[0][4] = KING_BLACK; Board_State[7][0] = ROOK_WHITE; Board_State[7][7] = ROOK_WHITE; Board_State[7][1] = KNIGHT_WHITE; Board_State[7][6] = KNIGHT_WHITE; Board_State[7][2] = BISHOP_WHITE; Board_State[7][5] = BISHOP_WHITE; Board_State[7][3] = QUEEN_WHITE; Board_State[7][4] = KING_WHITE; for (uint8_t i = 0; i < 8; i++) { Board_State[1][i] = PAWN_BLACK; Board_State[6][i] = PAWN_WHITE; } for (uint8_t i = 0; i < 12; i++) { //location of all the sprites plus the size of file names char file[25] = "sprites\\"; memcpy(&file[8], File_Names[i], 16); bitmapSurface = SDL_LoadBMP(file); bitmapTextures[i] = SDL_CreateTextureFromSurface(p_renderer, bitmapSurface); } SDL_FreeSurface(bitmapSurface); } /** * @brief Funtion for that will draw the current state of the board including pecies and colors for suggested and possible moves. * @param *p_renderer pointer to the renderer object: * @retval None */ void draw_board(SDL_Renderer *p_renderer) { SDL_SetRenderTarget(p_renderer, Board_Texture); SDL_SetRenderDrawColor(p_renderer, 0x7f, 0x7f, 0x7f, 0); SDL_RenderClear(p_renderer); SDL_RenderDrawRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0xFF, 0x00); Rectangle.w = Board_Width; Rectangle.h = Board_Width; Rectangle.x = (Width - Board_Width) / 2; Rectangle.y = (Height - Board_Width) / 2; SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); const int square_size = Board_Width / 8; int starting_x = Rectangle.x; Rectangle.w = square_size; Rectangle.h = square_size; for (size_t j = 0; j < 8; j++) { Rectangle.x = starting_x; for (size_t i = 0; i < 8; i++) { if(Board_Lights[j][i] == POTENTIAL_MOVE) { SDL_SetRenderDrawColor(p_renderer, 0x00, 0xFF, 0x00, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); } else if ((Board_Lights[j][i] == POTENTIAL_TAKE) || (Board_Lights[j][i] == PEICE_NEEDS_TO_BE_HERE)) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0x00, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); } else if (Board_Lights[j][i] == PEICE_ORIGIN) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0xFF, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); } else if (Board_Lights[j][i] == ERROR_MOVE) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0x00, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00); } else if (((i % 2) + (j % 2)) == 1) { SDL_RenderFillRect(p_renderer, &Rectangle); } else { /* code */ } if((Board_State[j][i] & 0x0Fu) != SQUARE_EMPTY) { SDL_RenderCopy(p_renderer, bitmapTextures[(Board_State[j][i] & 0x0Fu)], NULL, &Rectangle); } Rectangle.x += square_size; } Rectangle.y += square_size; } Rectangle.x = ((Width - Board_Width) / 2) - (2 * square_size); Rectangle.y = (Height - Board_Width) / 2; int starting_y = Rectangle.y; SDL_SetRenderDrawColor(p_renderer, 0x6F, 0x6f, 0x6f, 0x00); /* Now we draw the jail */ for (size_t j = 8; j < 12; j++) { Rectangle.y = starting_y; for (size_t i = 0; i < 8; i++) { if (Board_Lights[j][i] == PEICE_NEEDS_TO_BE_HERE) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0x00, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x6F, 0x6F, 0x6F, 0x00); } else if (Board_Lights[j][i] == ERROR_MOVE) { SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0x00, 0x00); SDL_RenderFillRect(p_renderer, &Rectangle); SDL_SetRenderDrawColor(p_renderer, 0x6F, 0x6F, 0x6F, 0x00); } else { SDL_RenderFillRect(p_renderer, &Rectangle); } if ((Board_State[j][i] & 0x0Fu) != SQUARE_EMPTY) { SDL_RenderCopy(p_renderer, bitmapTextures[(Board_State[j][i] & 0x0Fu)], NULL, &Rectangle); } Rectangle.y += square_size; } /*If we are at the end of second jail row, jump to the other side */ if(j == 9) { Rectangle.x += (Board_Width + square_size); } else { Rectangle.x += square_size; } } SDL_SetRenderTarget(p_renderer, NULL); SDL_RenderCopy(p_renderer, Board_Texture, NULL, NULL); }