From ec04c82d9b5484add625fad85ef5c80083751e91 Mon Sep 17 00:00:00 2001 From: Daniel Weber Date: Sat, 14 Sep 2024 15:41:15 -0400 Subject: [PATCH] Refactoring the Game State --- .gitignore | 3 +- src/game_logic/chess_board.cpp | 517 +++++++++++----------- src/game_logic/chess_board.h | 57 ++- src/pc_app/user_interface_abstraction.cpp | 33 +- 4 files changed, 314 insertions(+), 296 deletions(-) diff --git a/.gitignore b/.gitignore index fdeca65..6579e7c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build/ .rscons* -.vscode/ \ No newline at end of file +.vscode/ +compile_commands.json diff --git a/src/game_logic/chess_board.cpp b/src/game_logic/chess_board.cpp index 464dbf1..541c8a4 100644 --- a/src/game_logic/chess_board.cpp +++ b/src/game_logic/chess_board.cpp @@ -3,13 +3,11 @@ #include - -static uint8_t Board_State[8][8] = {{0}}; +static uint8_t Board_Pieces[8][8] = {{0}}; static uint8_t Saved_Binary_Board[8] = {0}; -static uint8_t Board_Lights[8][8] = {{0}}; -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 Board_States[8][8] = {{0}}; +static Game_State_t Game_State; +static Game_State_t Last_Game_State; static uint8_t Selected_Piece = SQUARE_EMPTY; static uint8_t Error_Count = 0u; static uint8_t Taken_Piece = SQUARE_EMPTY; @@ -28,15 +26,15 @@ static uint8_t Pawn_Converted_To = QUEEN_WHITE; * @brief Function for clearing all of the lights on the board. Except for error moves. * @retval None */ -static void clear_lights(void) +static void clear_board_state(void) { for (size_t i = 0; i < 8; i++) { for (size_t j = 0; j < 8; j++) { - if(Board_Lights[i][j] != ERROR_MOVE) + if(Board_States[i][j] != ERROR_MOVE) { - Board_Lights[i][j] = LIGHT_OFF; + Board_States[i][j] = LIGHT_OFF; } } } @@ -73,15 +71,15 @@ static bool opposite_teams(uint8_t piece_one, uint8_t piece_two) */ bool square_is_safe(uint8_t row, uint8_t column) { - int8_t temp = row + (White_Turn ? -1 : 1); + int8_t temp = row + (Game_State.player_turn ? -1 : 1); /* first check if pawns can take us */ - if ((column > 0) && ((White_Turn ? PAWN_BLACK : PAWN_WHITE) == Board_State[temp][column - 1u])) + if ((column > 0) && ((Game_State.player_turn ? PAWN_BLACK : PAWN_WHITE) == Board_Pieces[temp][column - 1u])) { //can be eaten by a pawn, not safe. return false; } - if ((column < 7) && ((White_Turn ? PAWN_BLACK : PAWN_WHITE) == Board_State[temp][column + 1u])) + if ((column < 7) && ((Game_State.player_turn ? PAWN_BLACK : PAWN_WHITE) == Board_Pieces[temp][column + 1u])) { //can be eaten by a pawn, not safe. return false; @@ -98,7 +96,7 @@ bool square_is_safe(uint8_t row, uint8_t column) { int8_t x = row + left_right; int8_t y = column + up_down; - if ((White_Turn ? KING_BLACK : KING_WHITE) == Board_State[x][y]) + if ((Game_State.player_turn ? KING_BLACK : KING_WHITE) == Board_Pieces[x][y]) { return false; } @@ -141,11 +139,11 @@ bool square_is_safe(uint8_t row, uint8_t column) { loop = false; } - else if (Board_State[x][y] == SQUARE_EMPTY) + else if (Board_Pieces[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])) + else if (((Game_State.player_turn ? ROOK_BLACK : ROOK_WHITE) == Board_Pieces[x][y]) || ((Game_State.player_turn ? QUEEN_BLACK : QUEEN_WHITE) == Board_Pieces[x][y])) { return false; } @@ -185,19 +183,19 @@ bool square_is_safe(uint8_t row, uint8_t column) int8_t y = column; while (loop) { - uint8_t bish = (White_Turn ? BISHOP_BLACK : BISHOP_WHITE); - uint8_t queen = (White_Turn ? QUEEN_BLACK : QUEEN_WHITE); + uint8_t bish = (Game_State.player_turn ? BISHOP_BLACK : BISHOP_WHITE); + uint8_t queen = (Game_State.player_turn ? QUEEN_BLACK : QUEEN_WHITE); 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) + else if (Board_Pieces[x][y] == SQUARE_EMPTY) { /* do nothing */ } - else if ((bish == Board_State[x][y]) || (queen == Board_State[x][y])) + else if ((bish == Board_Pieces[x][y]) || (queen == Board_Pieces[x][y])) { return false; } @@ -248,7 +246,7 @@ bool square_is_safe(uint8_t row, uint8_t column) int8_t y = (int8_t)column + up_down_step; if ((x >= 0) && (y >= 0) && (x < 8) && (y < 8)) { - if ((White_Turn ? KNIGHT_BLACK : KNIGHT_WHITE) == Board_State[x][y]) + if ((Game_State.player_turn ? KNIGHT_BLACK : KNIGHT_WHITE) == Board_Pieces[x][y]) { return false; } @@ -261,23 +259,23 @@ bool square_is_safe(uint8_t row, uint8_t column) bool Check_If_Move_Caused_Check(uint8_t piece, uint8_t row, uint8_t column) { bool ret_val; - uint8_t store_current_piece = Board_State[row][column]; - Board_State[row][column] = piece; + uint8_t store_current_piece = Board_Pieces[row][column]; + Board_Pieces[row][column] = piece; //If its the white's turn we want to see if the white king is still safe. - uint8_t white_black_idx = White_Turn ? 0u : 1u; + uint8_t white_black_idx = Game_State.player_turn ? 0u : 1u; ret_val = !square_is_safe(King_Locations[white_black_idx][0u], King_Locations[white_black_idx][1u]); - Board_State[row][column] = store_current_piece; + Board_Pieces[row][column] = store_current_piece; return ret_val; } void Check_If_Could_Cause_Check(uint8_t row, uint8_t column) { - uint8_t temp_storage = Board_State[row][column]; - Board_State[row][column] = SQUARE_EMPTY; + uint8_t temp_storage = Board_Pieces[row][column]; + Board_Pieces[row][column] = SQUARE_EMPTY; //If its the white's turn we want to see if the white king is still safe. - uint8_t white_black_idx = White_Turn ? 0u : 1u; + uint8_t white_black_idx = Game_State.player_turn ? 0u : 1u; High_Alert = !square_is_safe(King_Locations[white_black_idx][0u], King_Locations[white_black_idx][1u]); - Board_State[row][column] = temp_storage; + Board_Pieces[row][column] = temp_storage; } static bool Set_Light(uint8_t piece, uint8_t row, uint8_t column, uint8_t state) @@ -285,7 +283,7 @@ static bool Set_Light(uint8_t piece, uint8_t row, uint8_t column, uint8_t state) bool ret_val = false; if (!Check_If_Move_Caused_Check(piece, row, column)) { - Board_Lights[row][column] = state; + Board_States[row][column] = state; ret_val = true; } return ret_val; @@ -300,7 +298,7 @@ static bool Set_Light(uint8_t piece, uint8_t row, uint8_t column, uint8_t state) static bool pawn_move(uint8_t piece, uint8_t row, uint8_t column) { bool ret_val = false; - if (Board_State[row][column] == SQUARE_EMPTY) + if (Board_Pieces[row][column] == SQUARE_EMPTY) { ret_val = Set_Light(piece, row, column, POTENTIAL_MOVE); } @@ -331,11 +329,11 @@ static bool cast_a_ray(uint8_t piece, int8_t direction_r, int8_t direction_c, ui { loop = false; } - else if (Board_State[x][y] == SQUARE_EMPTY) + else if (Board_Pieces[x][y] == SQUARE_EMPTY) { ret_val = Set_Light(piece, x, y, POTENTIAL_MOVE) || ret_val; } - else if (opposite_teams(piece, Board_State[x][y])) + else if (opposite_teams(piece, Board_Pieces[x][y])) { ret_val = Set_Light(piece, x, y, POTENTIAL_TAKE) || ret_val; /* once we take a piece we can no longer take anymore */ @@ -358,7 +356,7 @@ static bool cast_a_ray(uint8_t piece, int8_t direction_r, int8_t direction_c, ui static bool pawn_take(uint8_t piece, uint8_t row, uint8_t column) { bool ret_val = false; - if ((Board_State[row][column] < SQUARE_EMPTY) && opposite_teams(piece, Board_State[row][column])) + if ((Board_Pieces[row][column] < SQUARE_EMPTY) && opposite_teams(piece, Board_Pieces[row][column])) { ret_val = Set_Light(piece, row, column, POTENTIAL_TAKE); } @@ -384,7 +382,7 @@ static bool Mark_Potential_Moves(uint8_t piece, uint8_t column, uint8_t row) uint8_t temp_row = row + direction; if (row == (white_team(piece) ? 6u : 1u)) { - if(Board_State[temp_row][column] == SQUARE_EMPTY) + if(Board_Pieces[temp_row][column] == SQUARE_EMPTY) { ret_val = pawn_move(piece, row + (direction * 2u), column) || ret_val; } @@ -477,11 +475,11 @@ static bool Mark_Potential_Moves(uint8_t piece, uint8_t column, uint8_t row) int8_t y = (int8_t)column + up_down_step; if ((x >= 0) && (y >= 0) && (x < 8) && (y < 8)) { - if (Board_State[x][y] == SQUARE_EMPTY) + if (Board_Pieces[x][y] == SQUARE_EMPTY) { ret_val = Set_Light(piece, x, y, POTENTIAL_MOVE) || ret_val; } - else if (opposite_teams(piece, Board_State[x][y])) + else if (opposite_teams(piece, Board_Pieces[x][y])) { ret_val = Set_Light(piece, x, y, POTENTIAL_TAKE) || ret_val; } @@ -545,14 +543,14 @@ static bool Mark_Potential_Moves(uint8_t piece, uint8_t column, uint8_t row) int8_t y = column + up_down; if (square_is_safe(x, y)) { - if (Board_State[x][y] == SQUARE_EMPTY) + if (Board_Pieces[x][y] == SQUARE_EMPTY) { - Board_Lights[x][y] = POTENTIAL_MOVE; + Board_States[x][y] = POTENTIAL_MOVE; ret_val = true; } - else if (opposite_teams(piece, Board_State[x][y])) + else if (opposite_teams(piece, Board_Pieces[x][y])) { - Board_Lights[x][y] = POTENTIAL_TAKE; + Board_States[x][y] = POTENTIAL_TAKE; ret_val = true; } } @@ -565,26 +563,26 @@ static bool Mark_Potential_Moves(uint8_t piece, uint8_t column, uint8_t row) if (square_is_safe(row, column)) { // 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) + if(Castling_Allowed[white_black_idx][0u] && (Board_Pieces[kings_row][1u] == SQUARE_EMPTY) + && (Board_Pieces[kings_row][2u] == SQUARE_EMPTY) && (Board_Pieces[kings_row][3u]) == SQUARE_EMPTY) { //First Check to see if the king will pass through check if(square_is_safe(kings_row, 3u) && square_is_safe(kings_row, 2u)) { // Yay we can castle queen side! - Board_Lights[kings_row][2u] = POTENTIAL_CASTLE; + Board_States[kings_row][2u] = POTENTIAL_CASTLE; ret_val = true; } } // King side castle - if (Castling_Allowed[white_black_idx][1u] && (Board_State[kings_row][5u] == SQUARE_EMPTY) && (Board_State[kings_row][6u] == SQUARE_EMPTY)) + if (Castling_Allowed[white_black_idx][1u] && (Board_Pieces[kings_row][5u] == SQUARE_EMPTY) && (Board_Pieces[kings_row][6u] == SQUARE_EMPTY)) { //First Check to see if the king will pass through check if(square_is_safe(kings_row, 5u) && square_is_safe(kings_row, 6u)) { // Yay we can castle king side! - Board_Lights[kings_row][6u] = POTENTIAL_CASTLE; + Board_States[kings_row][6u] = POTENTIAL_CASTLE; ret_val = true; } } @@ -605,21 +603,21 @@ bool Check_If_Player_Can_Move(bool white) { for (uint8_t column = 0; column < 8u; column++) { - if((white_team(Board_State[row][column]) == white)) + if((white_team(Board_Pieces[row][column]) == white)) { // SDL_Log("move: Row:%d, Col:%d", row, column); - if(Mark_Potential_Moves(Board_State[row][column], column, row)) + if(Mark_Potential_Moves(Board_Pieces[row][column], column, row)) { // SDL_Log("Player Can still move: Row:%d, Col:%d", row, column); - clear_lights(); + clear_board_state(); return true; } } } } - clear_lights(); + clear_board_state(); // SDL_Log("Player cant move"); return false; } @@ -629,26 +627,21 @@ bool Check_If_Player_Can_Move(bool white) */ static void Switch_Turns(void) { - Game_State = (White_Turn ? GAME_STATE_P2_TURN_BEGINING : GAME_STATE_P1_TURN_BEGINING); - White_Turn = !White_Turn; + Game_State.turn_state = BEGINNING; + Game_State.player_turn = !Game_State.player_turn; // Square is safe assumes the other team is trying to attack the square so for example at the end of // White's turn we want to see if the black king is now in check, so we will switch teams and then // Check if the current kings locations is safe. If it is safe then check is false, if it isnt safe then check is true. - uint8_t white_black_idx = White_Turn ? 0u : 1u; + uint8_t white_black_idx = Game_State.player_turn ? 0u : 1u; Check[white_black_idx] = !square_is_safe(King_Locations[white_black_idx][0u], King_Locations[white_black_idx][1u]); - //Last thing we need to check before sitching turns is to check if the game is over. - bool player_can_play = Check_If_Player_Can_Move(White_Turn); + //Last thing we need to check before switching turns is to check if the game is over. + bool player_can_play = Check_If_Player_Can_Move(Game_State.player_turn); if(!player_can_play) { - if(Check[white_black_idx]) - { - Game_State = White_Turn ? GAME_STATE_OVER_BLACK_WIN : GAME_STATE_OVER_WHITE_WIN; - } - else - { - Game_State = GAME_STATE_OVER_STALE_MATE; - } + Game_State.game_over = true; + Game_State.player_turn = !Game_State.player_turn; + Game_State.error_detected = !Check[white_black_idx]; } } @@ -662,7 +655,7 @@ static void Switch_Turns(void) */ static void Check_If_Moving_King(uint8_t row, uint8_t column) { - uint8_t white_black_idx = White_Turn ? 0u : 1u; + uint8_t white_black_idx = Game_State.player_turn ? 0u : 1u; if((Selected_Piece == KING_WHITE) || (Selected_Piece == KING_BLACK)) { King_Locations[white_black_idx][0u] = row; @@ -687,14 +680,14 @@ static void Check_If_Moving_King(uint8_t row, uint8_t column) static void Check_If_Converting_Pawn(uint8_t row, uint8_t column) { - uint8_t white_black_idx = White_Turn ? 0u : 1u; + uint8_t white_black_idx = Game_State.player_turn ? 0u : 1u; Converting_Pawn = false; if((Selected_Piece == PAWN_WHITE) || (Selected_Piece == PAWN_BLACK)) { if((row == 0u) || (row == 7u)) { - Selected_Piece = White_Turn ? QUEEN_WHITE : QUEEN_BLACK; + Selected_Piece = Game_State.player_turn ? QUEEN_WHITE : QUEEN_BLACK; Pawn_Converted_To = Selected_Piece; Converting_Pawn = true; Converting_Pawn_Row_Col[0] = row; @@ -712,16 +705,16 @@ static bool Converting_Pawn_If_Applicable(uint8_t row, uint8_t column) (Converting_Pawn_Row_Col[1] == column)) { //Putting the piece down on the board - if(Board_State[row][column] == SQUARE_EMPTY) + if(Board_Pieces[row][column] == SQUARE_EMPTY) { - Board_State[row][column] = Pawn_Converted_To; - Board_Lights[row][column] = LIGHT_OFF; + Board_Pieces[row][column] = Pawn_Converted_To; + Board_States[row][column] = LIGHT_OFF; } //Picking the piece back up to toggle through the options else { - Board_State[row][column] = SQUARE_EMPTY; - Board_Lights[row][column] = CONVERTING_PAWN; + Board_Pieces[row][column] = SQUARE_EMPTY; + Board_States[row][column] = CONVERTING_PAWN; Pawn_Converted_To = Pawn_Converted_To - 2; if (Pawn_Converted_To < ROOK_WHITE) { @@ -746,204 +739,196 @@ static bool Converting_Pawn_If_Applicable(uint8_t row, uint8_t column) */ static void Board_Square_Was_Toggled(uint8_t j, uint8_t i) { - switch (Game_State) + if (Game_State.error_detected) { - /* Something unexpected happened, game cannot progress until the board is returned to the known state */ - case GAME_STATE_ERROR_DETECTED: + if (Board_States[j][i] == PIECE_ORIGIN) { - if (Board_Lights[j][i] == PIECE_ORIGIN) + Board_Pieces[j][i] = Selected_Piece; + Selected_Piece = SQUARE_EMPTY; + clear_board_state(); + Game_State.turn_state = BEGINNING; + } + else if (Board_States[j][i] == PIECE_NEEDS_TO_BE_HERE) + { + if (j < 8u) { - Board_State[j][i] = Selected_Piece; + Board_Pieces[j][i] = Selected_Piece; Selected_Piece = SQUARE_EMPTY; - clear_lights(); - Last_Game_State--; - } - else if (Board_Lights[j][i] == PIECE_NEEDS_TO_BE_HERE) - { - if (j < 8u) - { - Board_State[j][i] = Selected_Piece; - Selected_Piece = SQUARE_EMPTY; - Board_Lights[j][i] = LIGHT_OFF; - } - else - { - Board_State[j][i] = Taken_Piece; - uint8_t board_column = (j / 2u) * 2u; - if(Board_Lights[board_column][i] == PIECE_NEEDS_TO_BE_HERE) - { - Board_Lights[board_column][i] = LIGHT_OFF; - } - if(Board_Lights[board_column + 1u][i] == PIECE_NEEDS_TO_BE_HERE) - { - Board_Lights[board_column + 1u][i] = LIGHT_OFF; - } - Taken_Piece = SQUARE_EMPTY; - } - - if ((Selected_Piece == SQUARE_EMPTY) && (Taken_Piece == 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; - /* All Errors have been rectified so we can go back to where we were.*/ - if(Error_Count == 0u) - { - Game_State = Last_Game_State; - } + Board_States[j][i] = LIGHT_OFF; } else { - Error_Count++; - Board_Lights[j][i] = ERROR_MOVE; - } - break; - } - case GAME_STATE_IDLE: - { - break; - } - /* We are waiting till the player who's turn it is picks up a piece that is on their team */ - case GAME_STATE_P2_TURN_BEGINING: - case GAME_STATE_P1_TURN_BEGINING: - { - if ((j < 8u) && (Board_State[j][i] != SQUARE_EMPTY) && (white_team(Board_State[j][i]) == White_Turn)) - { - if((Board_State[j][i] != KING_BLACK) && (Board_State[j][i] != KING_WHITE)) + Board_Pieces[j][i] = Taken_Piece; + uint8_t board_column = (j / 2u) * 2u; + if(Board_States[board_column][i] == PIECE_NEEDS_TO_BE_HERE) { - Check_If_Could_Cause_Check(j, i); + Board_States[board_column][i] = LIGHT_OFF; } - Selected_Piece = Board_State[j][i]; - Board_State[j][i] = SQUARE_EMPTY; - (void)Mark_Potential_Moves(Selected_Piece, i, j); - Board_Lights[j][i] = PIECE_ORIGIN; - Game_State++; - } - else - { - if(!Converting_Pawn_If_Applicable(j, i)) + if(Board_States[board_column + 1u][i] == PIECE_NEEDS_TO_BE_HERE) { - Last_Game_State = Game_State; - Game_State = GAME_STATE_ERROR_DETECTED; - Board_Lights[j][i] = ERROR_MOVE; - Error_Count++; - } - } - - break; - } - /* Person is in the middle of taking a turn for example they might already have a piece in the hand*/ - case GAME_STATE_P2_TURN_IN_PROGRESS: - case GAME_STATE_P1_TURN_IN_PROGRESS: - { - if (Board_Lights[j][i] == POTENTIAL_MOVE) - { - Check_If_Moving_King(j, i); - Check_If_Converting_Pawn(j, i); - Board_State[j][i] = Selected_Piece; - Selected_Piece = SQUARE_EMPTY; - clear_lights(); - Switch_Turns(); - } - else if (Board_Lights[j][i] == POTENTIAL_TAKE) - { - // Taken_Piece = Board_State[j][i]; - Board_State[j][i] = SQUARE_EMPTY; - Game_State = (White_Turn ? GAME_STATE_P1_TURN_TAKING : GAME_STATE_P2_TURN_TAKING); - clear_lights(); - Board_Lights[j][i] = PIECE_NEEDS_TO_BE_HERE; - } - else if (Board_Lights[j][i] == PIECE_ORIGIN) - { - Board_State[j][i] = Selected_Piece; - Selected_Piece = SQUARE_EMPTY; - clear_lights(); - Game_State--; - } - else if (Board_Lights[j][i] == POTENTIAL_CASTLE) - { - Check_If_Moving_King(j, i); - Board_State[j][i] = Selected_Piece; - Selected_Piece = SQUARE_EMPTY; - clear_lights(); - if(i == 2u) - { - Board_Lights[j][3u] = PIECE_NEEDS_TO_BE_HERE; - Board_Lights[j][0u] = PIECE_NEEDS_TO_BE_REMOVED; - } - else if(i == 6u) - { - Board_Lights[j][5u] = PIECE_NEEDS_TO_BE_HERE; - Board_Lights[j][7u] = PIECE_NEEDS_TO_BE_REMOVED; - } - else - { - /* Do nothing. */ - } - - } - else if (Board_Lights[j][i] == PIECE_NEEDS_TO_BE_REMOVED) - { - Selected_Piece = Board_State[j][i]; - Board_State[j][i] = SQUARE_EMPTY; - Board_Lights[j][i] = LIGHT_OFF; - Game_State = (White_Turn ? GAME_STATE_P1_TURN_TAKING : GAME_STATE_P2_TURN_TAKING); - } - else - { - Last_Game_State = Game_State; - Game_State = GAME_STATE_ERROR_DETECTED; - Board_Lights[j][i] = ERROR_MOVE; - Error_Count++; - } - break; - } - /* Player still needs to do something to complete their turn, like complete castle, en pessant, or converting a pawn*/ - case GAME_STATE_P2_TURN_TAKING: - case GAME_STATE_P1_TURN_TAKING: - { - if (Board_Lights[j][i] == PIECE_NEEDS_TO_BE_HERE) - { - Check_If_Moving_King(j, i); - Check_If_Converting_Pawn(j, i); - Board_State[j][i] = Selected_Piece; - Selected_Piece = SQUARE_EMPTY; - Board_Lights[j][i] = LIGHT_OFF; - } - else - { - if(!Converting_Pawn_If_Applicable(j, i)) - { - Last_Game_State = Game_State; - Game_State = GAME_STATE_ERROR_DETECTED; - Board_Lights[j][i] = ERROR_MOVE; - Error_Count++; + Board_States[board_column + 1u][i] = LIGHT_OFF; } + Taken_Piece = SQUARE_EMPTY; } if ((Selected_Piece == SQUARE_EMPTY) && (Taken_Piece == SQUARE_EMPTY)) { - Switch_Turns(); + Game_State.turn_state = BEGINNING; + Game_State.player_turn = !Game_State.player_turn; } - - break; } - default: + else if (Board_States[j][i] == ERROR_MOVE) { - break; + Error_Count--; + Board_States[j][i] = LIGHT_OFF; + /* All Errors have been rectified so we can go back to where we were.*/ + if(Error_Count == 0u) + { + Game_State.error_detected = false; + } + } + else + { + Error_Count++; + Board_States[j][i] = ERROR_MOVE; + } + + } + else + { + switch (Game_State.turn_state) + { + /* We are waiting till the player who's turn it is picks up a piece that is on their team */ + case BEGINNING: + { + if ((j < 8u) && (Board_Pieces[j][i] != SQUARE_EMPTY) && (white_team(Board_Pieces[j][i]) == Game_State.player_turn)) + { + if((Board_Pieces[j][i] != KING_BLACK) && (Board_Pieces[j][i] != KING_WHITE)) + { + Check_If_Could_Cause_Check(j, i); + } + Selected_Piece = Board_Pieces[j][i]; + Board_Pieces[j][i] = SQUARE_EMPTY; + (void)Mark_Potential_Moves(Selected_Piece, i, j); + Board_States[j][i] = PIECE_ORIGIN; + Game_State.turn_state = IN_PROGRESS; + } + else + { + if(!Converting_Pawn_If_Applicable(j, i)) + { + Game_State.error_detected = true; + Board_States[j][i] = ERROR_MOVE; + Error_Count++; + } + } + + break; + } + /* Person is in the middle of taking a turn for example they might already have a piece in the hand*/ + case IN_PROGRESS: + { + if (Board_States[j][i] == POTENTIAL_MOVE) + { + Check_If_Moving_King(j, i); + Check_If_Converting_Pawn(j, i); + Board_Pieces[j][i] = Selected_Piece; + Selected_Piece = SQUARE_EMPTY; + clear_board_state(); + Switch_Turns(); + } + else if (Board_States[j][i] == POTENTIAL_TAKE) + { + // Taken_Piece = Board_State[j][i]; + Board_Pieces[j][i] = SQUARE_EMPTY; + Game_State.turn_state = FINALIZING; + clear_board_state(); + Board_States[j][i] = PIECE_NEEDS_TO_BE_HERE; + } + else if (Board_States[j][i] == PIECE_ORIGIN) + { + Board_Pieces[j][i] = Selected_Piece; + Selected_Piece = SQUARE_EMPTY; + clear_board_state(); + Game_State.turn_state = BEGINNING; + } + else if (Board_States[j][i] == POTENTIAL_CASTLE) + { + Check_If_Moving_King(j, i); + Board_Pieces[j][i] = Selected_Piece; + Selected_Piece = SQUARE_EMPTY; + clear_board_state(); + if(i == 2u) + { + Board_States[j][3u] = PIECE_NEEDS_TO_BE_HERE; + Board_States[j][0u] = PIECE_NEEDS_TO_BE_REMOVED; + } + else if(i == 6u) + { + Board_States[j][5u] = PIECE_NEEDS_TO_BE_HERE; + Board_States[j][7u] = PIECE_NEEDS_TO_BE_REMOVED; + } + else + { + /* Do nothing. */ + } + + } + else if (Board_States[j][i] == PIECE_NEEDS_TO_BE_REMOVED) + { + Selected_Piece = Board_Pieces[j][i]; + Board_Pieces[j][i] = SQUARE_EMPTY; + Board_States[j][i] = LIGHT_OFF; + Game_State.turn_state = FINALIZING; + } + else + { + Game_State.error_detected = true; + Board_States[j][i] = ERROR_MOVE; + Error_Count++; + } + break; + } + /* Player still needs to do something to complete their turn, like complete castle, en pessant, or converting a pawn*/ + case FINALIZING: + { + if (Board_States[j][i] == PIECE_NEEDS_TO_BE_HERE) + { + Check_If_Moving_King(j, i); + Check_If_Converting_Pawn(j, i); + Board_Pieces[j][i] = Selected_Piece; + Selected_Piece = SQUARE_EMPTY; + Board_States[j][i] = LIGHT_OFF; + } + else + { + if(!Converting_Pawn_If_Applicable(j, i)) + { + Game_State.error_detected = true; + Board_States[j][i] = ERROR_MOVE; + Error_Count++; + } + } + + if ((Selected_Piece == SQUARE_EMPTY) && (Taken_Piece == SQUARE_EMPTY)) + { + Switch_Turns(); + } + + break; + } + default: + { + break; + } } } } -void Board_get_lights_and_state(uint8_t board_lights[8][8], uint8_t board_state[8][8]) +void Board_get_lights_and_state(uint8_t board_state[8][8], uint8_t board_pieces[8][8]) { - memcpy(&board_lights[0][0], &Board_Lights[0][0], sizeof(Board_Lights)); - memcpy(&board_state[0][0], &Board_State[0][0], sizeof(Board_State)); + memcpy(&board_state[0][0], &Board_States[0][0], sizeof(Board_States)); + memcpy(&board_pieces[0][0], &Board_Pieces[0][0], sizeof(Board_Pieces)); } @@ -984,7 +969,7 @@ void chess_board_init(void) { for (uint8_t j = 0u; j < 8u; j++) { - Board_State[i][j] = SQUARE_EMPTY; + Board_Pieces[i][j] = SQUARE_EMPTY; } } Saved_Binary_Board[0] = 0xFF; @@ -993,31 +978,31 @@ void chess_board_init(void) 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; + Board_Pieces[0][0] = ROOK_BLACK; + Board_Pieces[0][7] = ROOK_BLACK; + Board_Pieces[0][1] = KNIGHT_BLACK; + Board_Pieces[0][6] = KNIGHT_BLACK; + Board_Pieces[0][2] = BISHOP_BLACK; + Board_Pieces[0][5] = BISHOP_BLACK; + Board_Pieces[0][3] = QUEEN_BLACK; + Board_Pieces[0][4] = KING_BLACK; + Board_Pieces[7][0] = ROOK_WHITE; + Board_Pieces[7][7] = ROOK_WHITE; + Board_Pieces[7][1] = KNIGHT_WHITE; + Board_Pieces[7][6] = KNIGHT_WHITE; + Board_Pieces[7][2] = BISHOP_WHITE; + Board_Pieces[7][5] = BISHOP_WHITE; + Board_Pieces[7][3] = QUEEN_WHITE; + Board_Pieces[7][4] = KING_WHITE; for (uint8_t i = 0; i < 8; i++) { - Board_State[1][i] = PAWN_BLACK; - Board_State[6][i] = PAWN_WHITE; + Board_Pieces[1][i] = PAWN_BLACK; + Board_Pieces[6][i] = PAWN_WHITE; } } -void Board_get_game_state(uint8_t * game_state) +Game_State_t Board_get_game_state(void) { - *game_state = Game_State; + return Game_State; } diff --git a/src/game_logic/chess_board.h b/src/game_logic/chess_board.h index 052ac0f..a9b776c 100644 --- a/src/game_logic/chess_board.h +++ b/src/game_logic/chess_board.h @@ -1,15 +1,17 @@ #include "stdint.h" -#define LIGHT_OFF 0u -#define POTENTIAL_MOVE 1u -#define POTENTIAL_TAKE 2u -#define SUGGESTED_MOVE 3u -#define ERROR_MOVE 4u -#define PIECE_ORIGIN 5u -#define PIECE_NEEDS_TO_BE_HERE 6u -#define POTENTIAL_CASTLE 7u -#define PIECE_NEEDS_TO_BE_REMOVED 8u -#define CONVERTING_PAWN 9u +enum Board_States_t { + LIGHT_OFF = 0u, + POTENTIAL_MOVE, + POTENTIAL_TAKE, + SUGGESTED_MOVE, + ERROR_MOVE, + PIECE_ORIGIN, + PIECE_NEEDS_TO_BE_HERE, + POTENTIAL_CASTLE, + PIECE_NEEDS_TO_BE_REMOVED, + CONVERTING_PAWN, +}; #define PAWN_WHITE 0u #define PAWN_BLACK 1u @@ -26,7 +28,20 @@ #define SQUARE_EMPTY 12u - +// enum Game_State_t { +// GAME_STATE_P1_TURN_BEGINING = 0u, +// GAME_STATE_P1_TURN_IN_PROGRESS, +// GAME_STATE_P1_TURN_TAKING, +// GAME_STATE_P2_TURN_BEGINING, +// GAME_STATE_P2_TURN_IN_PROGRESS, +// GAME_STATE_P2_TURN_TAKING, +// GAME_STATE_ERROR_DETECTED, +// //All games states from over on, correspond to states of the game being over +// GAME_STATE_OVER, +// GAME_STATE_OVER_WHITE_WIN, +// GAME_STATE_OVER_BLACK_WIN, +// GAME_STATE_OVER_STALE_MATE, +// }; #define GAME_STATE_IDLE 0u #define GAME_STATE_P1_TURN_BEGINING 1u #define GAME_STATE_P1_TURN_IN_PROGRESS 2u @@ -35,13 +50,29 @@ #define GAME_STATE_P2_TURN_IN_PROGRESS 5u #define GAME_STATE_P2_TURN_TAKING 6u #define GAME_STATE_ERROR_DETECTED 7u - +//All games states from over on, correspond to states of the game being over #define GAME_STATE_OVER 8u #define GAME_STATE_OVER_WHITE_WIN 8u #define GAME_STATE_OVER_BLACK_WIN 9u #define GAME_STATE_OVER_STALE_MATE 10u +#define WHITE_TURN true +#define BLACK_TURN false + +enum Turn_State_t { + BEGINNING = 0, + IN_PROGRESS, + FINALIZING, +}; + +struct Game_State_t { + bool game_over = false; + bool error_detected = false; + bool player_turn = WHITE_TURN; + Turn_State_t turn_state = BEGINNING; +}; + void chess_board_init(void); void Board_Changed(uint8_t current_binary_board[12]); void Board_get_lights_and_state(uint8_t board_lights[12][8], uint8_t board_state[12][8]); -void Board_get_game_state(uint8_t * game_state); +Game_State_t Board_get_game_state(void); diff --git a/src/pc_app/user_interface_abstraction.cpp b/src/pc_app/user_interface_abstraction.cpp index b09568e..000b1c9 100644 --- a/src/pc_app/user_interface_abstraction.cpp +++ b/src/pc_app/user_interface_abstraction.cpp @@ -31,7 +31,7 @@ static uint8_t Current_Binary_Board[8] = {0}; * @param board_state board state * @param game_state games state */ -static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t board_state[8][8], uint8_t game_state) +static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t board_state[8][8], Game_State_t game_state) { SDL_SetRenderTarget(p_renderer, Board_Texture); SDL_SetRenderDrawColor(p_renderer, 0x7f, 0x7f, 0x7f, 0); @@ -50,15 +50,17 @@ static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t board_state[8][8] Rectangle.h = square_size; uint8_t white_color[4] = {0xFF, 0xFF, 0x00, 0x00}; uint8_t black_color[4] = {0xFF, 0xFF, 0x00, 0x00}; - if(game_state == GAME_STATE_OVER_WHITE_WIN) - { - white_color[0] = 0x00; white_color[1] = 0xFF; white_color[2] = 0x00; white_color[3] = 0x00; - black_color[0] = 0xFF; black_color[1] = 0x00; black_color[2] = 0x00; black_color[3] = 0x00; - } - else if (game_state == GAME_STATE_OVER_BLACK_WIN) - { - black_color[0] = 0x00; black_color[1] = 0xFF; black_color[2] = 0x00; black_color[3] = 0x00; - white_color[0] = 0xFF; white_color[1] = 0x00; white_color[2] = 0x00; white_color[3] = 0x00; + if (!game_state.error_detected){ + if(game_state.player_turn) + { + white_color[0] = 0x00; white_color[1] = 0xFF; white_color[2] = 0x00; white_color[3] = 0x00; + black_color[0] = 0xFF; black_color[1] = 0x00; black_color[2] = 0x00; black_color[3] = 0x00; + } + else + { + black_color[0] = 0x00; black_color[1] = 0xFF; black_color[2] = 0x00; black_color[3] = 0x00; + white_color[0] = 0xFF; white_color[1] = 0x00; white_color[2] = 0x00; white_color[3] = 0x00; + } } @@ -103,7 +105,7 @@ static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t board_state[8][8] } /** - * @brief Funtion for that will draw the current state of the board including pecies and colors for suggested and possible moves. + * @brief Funtion for that will draw the current state of the board including pieces and colors for suggested and possible moves. * @param *p_renderer pointer to the renderer object: * @retval None */ @@ -236,16 +238,15 @@ void ui_redraw_board(SDL_Renderer *p_renderer) { uint8_t board_lights[8][8]; uint8_t board_state[8][8]; - uint8_t game_state; - Board_get_game_state(&game_state); + Game_State_t game_state = Board_get_game_state(); Board_get_lights_and_state(board_lights, board_state); - if(game_state < GAME_STATE_OVER) + if(game_state.game_over) { - ui_draw_board(p_renderer, board_lights, board_state); + ui_draw_end_game(p_renderer, board_state, game_state); } else { - ui_draw_end_game(p_renderer, board_state, game_state); + ui_draw_board(p_renderer, board_lights, board_state); } }