Major refactor in an effort to be a little bit more organized. Emphasis
on effort.
This commit is contained in:
parent
fe8e46b88c
commit
bc20e3b1a8
@ -4,10 +4,14 @@ project(Chess C CXX)
|
|||||||
|
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
|
|
||||||
file(GLOB_RECURSE sources
|
file(GLOB_RECURSE cpp_sources
|
||||||
CONFIGURE_DEPENDS
|
CONFIGURE_DEPENDS
|
||||||
"src/*.cpp")
|
"src/*.cpp")
|
||||||
|
|
||||||
|
file(GLOB_RECURSE c_sources
|
||||||
|
CONFIGURE_DEPENDS
|
||||||
|
"src/*.c")
|
||||||
|
|
||||||
file (GLOB_RECURSE headers CONFIGURE_DEPENDS "src/*.h")
|
file (GLOB_RECURSE headers CONFIGURE_DEPENDS "src/*.h")
|
||||||
|
|
||||||
set (include_dirs "")
|
set (include_dirs "")
|
||||||
@ -16,7 +20,7 @@ foreach (_headerFile ${headers})
|
|||||||
list (APPEND include_dirs ${_dir})
|
list (APPEND include_dirs ${_dir})
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
add_executable(Chess ${sources})
|
add_executable(Chess ${cpp_sources} ${c_sources})
|
||||||
set_target_properties(Chess PROPERTIES CXX_STANDARD 17) # set standard level
|
set_target_properties(Chess PROPERTIES CXX_STANDARD 17) # set standard level
|
||||||
target_include_directories(Chess PRIVATE ${include_dirs})
|
target_include_directories(Chess PRIVATE ${include_dirs})
|
||||||
target_compile_options(Chess PRIVATE
|
target_compile_options(Chess PRIVATE
|
||||||
|
File diff suppressed because it is too large
Load Diff
335
src/game_logic/game_state.c
Normal file
335
src/game_logic/game_state.c
Normal file
@ -0,0 +1,335 @@
|
|||||||
|
#include "game_state.h"
|
||||||
|
#include "stdio.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "pawn.h"
|
||||||
|
#include "king.h"
|
||||||
|
#include "piece_logic.h"
|
||||||
|
|
||||||
|
static uint8_t Saved_Binary_Board[8] = {0};
|
||||||
|
static Game_State_t Game_State = {
|
||||||
|
.game_over = false,
|
||||||
|
.error_detected = false,
|
||||||
|
.player_turn = WHITE_TURN,
|
||||||
|
.turn_state = BEGINNING,
|
||||||
|
.board_state = {0},
|
||||||
|
.board_pieces = {0},
|
||||||
|
.selected_peice = SQUARE_EMPTY,
|
||||||
|
.castling_allowed = {{true, true},{true, true}},
|
||||||
|
};
|
||||||
|
static uint8_t Error_Count = 0u;
|
||||||
|
static bool Check[2u] = {false, false};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function for clearing all of the lights on the board. Except for error moves.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void clear_board_state(void)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j < 8; j++)
|
||||||
|
{
|
||||||
|
if(Game_State.board_state[i*8+j] != ERROR_MOVE)
|
||||||
|
{
|
||||||
|
Game_State.board_state[i*8+j] = LIGHT_OFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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, &Game_State))
|
||||||
|
{
|
||||||
|
Game_State.board_state[row*8+column] = state;
|
||||||
|
ret_val = true;
|
||||||
|
}
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function for switching the players turn. Incharge of handling the state machine reset.
|
||||||
|
*/
|
||||||
|
static void Switch_Turns(void)
|
||||||
|
{
|
||||||
|
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 = Game_State.player_turn ? 0u : 1u;
|
||||||
|
|
||||||
|
Check[white_black_idx] = Check_Current_Players_Check_Status(&Game_State);
|
||||||
|
|
||||||
|
//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, &Game_State);
|
||||||
|
if(!player_can_play)
|
||||||
|
{
|
||||||
|
Game_State.game_over = true;
|
||||||
|
Game_State.player_turn = !Game_State.player_turn;
|
||||||
|
Game_State.error_detected = !Check[white_black_idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function for toggeling a square's state.
|
||||||
|
* @param row_idx: row location that was toggled.
|
||||||
|
* @param column_idx: column location that was toggled.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
static void Board_Square_Was_Toggled(uint8_t row_idx, uint8_t col_idx)
|
||||||
|
{
|
||||||
|
if (Game_State.error_detected)
|
||||||
|
{
|
||||||
|
if (Game_State.board_state[row_idx*8+col_idx] == PIECE_ORIGIN)
|
||||||
|
{
|
||||||
|
Game_State.board_pieces[row_idx*8+col_idx] = Game_State.selected_peice;
|
||||||
|
Game_State.selected_peice = SQUARE_EMPTY;
|
||||||
|
clear_board_state();
|
||||||
|
Game_State.turn_state = BEGINNING;
|
||||||
|
}
|
||||||
|
else if (Game_State.board_state[row_idx*8+col_idx] == PIECE_NEEDS_TO_BE_HERE)
|
||||||
|
{
|
||||||
|
Game_State.board_pieces[row_idx*8+col_idx] = Game_State.selected_peice;
|
||||||
|
Game_State.selected_peice = SQUARE_EMPTY;
|
||||||
|
Game_State.board_state[row_idx*8+col_idx] = LIGHT_OFF;
|
||||||
|
|
||||||
|
if (Game_State.selected_peice == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
Game_State.turn_state = BEGINNING;
|
||||||
|
Game_State.player_turn = !Game_State.player_turn;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Game_State.board_state[row_idx*8+col_idx] == ERROR_MOVE)
|
||||||
|
{
|
||||||
|
Error_Count--;
|
||||||
|
Game_State.board_state[row_idx*8+col_idx] = 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++;
|
||||||
|
Game_State.board_state[row_idx*8+col_idx] = 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 ((Game_State.board_pieces[row_idx*8+col_idx] != SQUARE_EMPTY) && (white_team(Game_State.board_pieces[row_idx*8+col_idx]) == Game_State.player_turn))
|
||||||
|
{
|
||||||
|
Game_State.selected_peice = Game_State.board_pieces[row_idx*8+col_idx];
|
||||||
|
Game_State.board_pieces[row_idx*8+col_idx] = SQUARE_EMPTY;
|
||||||
|
(void)Mark_Potential_Moves(Game_State.selected_peice, col_idx, row_idx, &Game_State);
|
||||||
|
Game_State.board_state[row_idx*8+col_idx] = PIECE_ORIGIN;
|
||||||
|
Game_State.turn_state = IN_PROGRESS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!Converting_Pawn_If_Applicable(row_idx, col_idx, &Game_State))
|
||||||
|
{
|
||||||
|
Game_State.error_detected = true;
|
||||||
|
Game_State.board_state[row_idx*8+col_idx] = 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 (Game_State.board_state[row_idx*8+col_idx] == POTENTIAL_MOVE)
|
||||||
|
{
|
||||||
|
Check_If_Moving_King(row_idx, col_idx, &Game_State);
|
||||||
|
Check_If_Converting_Pawn(row_idx, col_idx, &Game_State);
|
||||||
|
Game_State.board_pieces[row_idx*8+col_idx] = Game_State.selected_peice;
|
||||||
|
Game_State.selected_peice = SQUARE_EMPTY;
|
||||||
|
clear_board_state();
|
||||||
|
Switch_Turns();
|
||||||
|
}
|
||||||
|
else if (Game_State.board_state[row_idx*8+col_idx] == POTENTIAL_TAKE)
|
||||||
|
{
|
||||||
|
Game_State.board_pieces[row_idx*8+col_idx] = SQUARE_EMPTY;
|
||||||
|
Game_State.turn_state = FINALIZING;
|
||||||
|
clear_board_state();
|
||||||
|
Game_State.board_state[row_idx*8+col_idx] = PIECE_NEEDS_TO_BE_HERE;
|
||||||
|
}
|
||||||
|
else if (Game_State.board_state[row_idx*8+col_idx] == PIECE_ORIGIN)
|
||||||
|
{
|
||||||
|
Game_State.board_pieces[row_idx*8+col_idx] = Game_State.selected_peice;
|
||||||
|
Game_State.selected_peice = SQUARE_EMPTY;
|
||||||
|
clear_board_state();
|
||||||
|
Game_State.turn_state = BEGINNING;
|
||||||
|
}
|
||||||
|
else if (Game_State.board_state[row_idx*8+col_idx] == POTENTIAL_CASTLE)
|
||||||
|
{
|
||||||
|
Check_If_Moving_King(row_idx, col_idx, &Game_State);
|
||||||
|
Game_State.board_pieces[row_idx*8+col_idx] = Game_State.selected_peice;
|
||||||
|
Game_State.selected_peice = SQUARE_EMPTY;
|
||||||
|
clear_board_state();
|
||||||
|
if(col_idx == 2u)
|
||||||
|
{
|
||||||
|
Game_State.board_state[row_idx*8+3u] = PIECE_NEEDS_TO_BE_HERE;
|
||||||
|
Game_State.board_state[row_idx*8+0u] = PIECE_NEEDS_TO_BE_REMOVED;
|
||||||
|
}
|
||||||
|
else if(col_idx == 6u)
|
||||||
|
{
|
||||||
|
Game_State.board_state[row_idx*8+5u] = PIECE_NEEDS_TO_BE_HERE;
|
||||||
|
Game_State.board_state[row_idx*8+7u] = PIECE_NEEDS_TO_BE_REMOVED;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Do nothing. */
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
else if (Game_State.board_state[row_idx*8+col_idx] == PIECE_NEEDS_TO_BE_REMOVED)
|
||||||
|
{
|
||||||
|
Game_State.selected_peice = Game_State.board_pieces[row_idx*8+col_idx];
|
||||||
|
Game_State.board_pieces[row_idx*8+col_idx] = SQUARE_EMPTY;
|
||||||
|
Game_State.board_state[row_idx*8+col_idx] = LIGHT_OFF;
|
||||||
|
Game_State.turn_state = FINALIZING;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Game_State.error_detected = true;
|
||||||
|
Game_State.board_state[row_idx*8+col_idx] = 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 (Game_State.board_state[row_idx*8+col_idx] == PIECE_NEEDS_TO_BE_HERE)
|
||||||
|
{
|
||||||
|
Check_If_Moving_King(row_idx, col_idx, &Game_State);
|
||||||
|
Check_If_Converting_Pawn(row_idx, col_idx, &Game_State);
|
||||||
|
Game_State.board_pieces[row_idx*8+col_idx] = Game_State.selected_peice;
|
||||||
|
Game_State.selected_peice = SQUARE_EMPTY;
|
||||||
|
Game_State.board_state[row_idx*8+col_idx] = LIGHT_OFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(!Converting_Pawn_If_Applicable(row_idx, col_idx, &Game_State))
|
||||||
|
{
|
||||||
|
Game_State.error_detected = true;
|
||||||
|
Game_State.board_state[row_idx*8+col_idx] = ERROR_MOVE;
|
||||||
|
Error_Count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Game_State.selected_peice == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
Switch_Turns();
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Board_get_lights_and_state(uint8_t * board_state, uint8_t * board_pieces)
|
||||||
|
{
|
||||||
|
memcpy(board_state, Game_State.board_state, sizeof(Game_State.board_state));
|
||||||
|
memcpy(board_pieces, Game_State.board_pieces, sizeof(Game_State.board_pieces));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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(uint8_t current_binary_board[8])
|
||||||
|
{
|
||||||
|
for (uint8_t j = 0u; j < 8u; 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 initializing the board
|
||||||
|
* @note
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void game_state_init(void)
|
||||||
|
{
|
||||||
|
for (uint8_t i = 0u; i < 8u; i++)
|
||||||
|
{
|
||||||
|
for (uint8_t j = 0u; j < 8u; j++)
|
||||||
|
{
|
||||||
|
Game_State.board_pieces[i*8+j] = SQUARE_EMPTY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Saved_Binary_Board[0] = 0xFF;
|
||||||
|
Saved_Binary_Board[1] = 0xFF;
|
||||||
|
Saved_Binary_Board[6] = 0xFF;
|
||||||
|
Saved_Binary_Board[7] = 0xFF;
|
||||||
|
|
||||||
|
//Place black pieces
|
||||||
|
Game_State.board_pieces[0*8+0] = ROOK_BLACK;
|
||||||
|
Game_State.board_pieces[0*8+7] = ROOK_BLACK;
|
||||||
|
Game_State.board_pieces[0*8+1] = KNIGHT_BLACK;
|
||||||
|
Game_State.board_pieces[0*8+6] = KNIGHT_BLACK;
|
||||||
|
Game_State.board_pieces[0*8+2] = BISHOP_BLACK;
|
||||||
|
Game_State.board_pieces[0*8+5] = BISHOP_BLACK;
|
||||||
|
Game_State.board_pieces[0*8+3] = QUEEN_BLACK;
|
||||||
|
Game_State.board_pieces[0*8+4] = KING_BLACK;
|
||||||
|
Game_State.board_pieces[7*8+0] = ROOK_WHITE;
|
||||||
|
Game_State.board_pieces[7*8+7] = ROOK_WHITE;
|
||||||
|
Game_State.board_pieces[7*8+1] = KNIGHT_WHITE;
|
||||||
|
Game_State.board_pieces[7*8+6] = KNIGHT_WHITE;
|
||||||
|
Game_State.board_pieces[7*8+2] = BISHOP_WHITE;
|
||||||
|
Game_State.board_pieces[7*8+5] = BISHOP_WHITE;
|
||||||
|
Game_State.board_pieces[7*8+3] = QUEEN_WHITE;
|
||||||
|
Game_State.board_pieces[7*8+4] = KING_WHITE;
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
Game_State.board_pieces[1*8+i] = PAWN_BLACK;
|
||||||
|
Game_State.board_pieces[6*8+i] = PAWN_WHITE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Game_State_t Board_get_game_state(void)
|
||||||
|
{
|
||||||
|
return Game_State;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,4 +1,12 @@
|
|||||||
|
#ifndef GAME_STATE_H
|
||||||
|
#define GAME_STATE_H
|
||||||
|
|
||||||
#include "stdint.h"
|
#include "stdint.h"
|
||||||
|
#include "stdbool.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
enum Board_States_t {
|
enum Board_States_t {
|
||||||
LIGHT_OFF = 0u,
|
LIGHT_OFF = 0u,
|
||||||
@ -30,20 +38,31 @@ enum Board_States_t {
|
|||||||
#define WHITE_TURN true
|
#define WHITE_TURN true
|
||||||
#define BLACK_TURN false
|
#define BLACK_TURN false
|
||||||
|
|
||||||
enum Turn_State_t {
|
typedef enum {
|
||||||
BEGINNING = 0,
|
BEGINNING = 0,
|
||||||
IN_PROGRESS,
|
IN_PROGRESS,
|
||||||
FINALIZING,
|
FINALIZING,
|
||||||
};
|
}Turn_State_t;
|
||||||
|
|
||||||
struct Game_State_t {
|
typedef struct {
|
||||||
bool game_over = false;
|
bool game_over;
|
||||||
bool error_detected = false;
|
bool error_detected;
|
||||||
bool player_turn = WHITE_TURN;
|
bool player_turn;
|
||||||
Turn_State_t turn_state = BEGINNING;
|
Turn_State_t turn_state;
|
||||||
};
|
uint8_t board_state[8*8];
|
||||||
|
uint8_t board_pieces[8*8];
|
||||||
|
uint8_t selected_peice;
|
||||||
|
bool castling_allowed[2u][2u];
|
||||||
|
}Game_State_t;
|
||||||
|
|
||||||
void chess_board_init(void);
|
void game_state_init(void);
|
||||||
void Board_Changed(uint8_t current_binary_board[12]);
|
void Board_Changed(uint8_t current_binary_board[8]);
|
||||||
void Board_get_lights_and_state(uint8_t board_lights[12][8], uint8_t board_state[12][8]);
|
bool Set_Light(uint8_t piece, uint8_t row, uint8_t column, uint8_t state);
|
||||||
|
void clear_board_state(void);
|
||||||
|
void Board_get_lights_and_state(uint8_t * board_lights, uint8_t * board_state);
|
||||||
Game_State_t Board_get_game_state(void);
|
Game_State_t Board_get_game_state(void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
56
src/game_logic/piece_logic/king.c
Normal file
56
src/game_logic/piece_logic/king.c
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#include "king.h"
|
||||||
|
#include "piece_logic.h"
|
||||||
|
|
||||||
|
static uint8_t King_Locations[2u][2u] = {{7,4}, {0,4}};
|
||||||
|
|
||||||
|
bool Check_Current_Players_Check_Status(Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
bool ret_val;
|
||||||
|
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], game_state);
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Check_If_Move_Caused_Check(uint8_t piece, uint8_t row, uint8_t column, Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
bool ret_val;
|
||||||
|
uint8_t store_current_piece = game_state->board_pieces[row*8+column];
|
||||||
|
game_state->board_pieces[row*8+column] = piece;
|
||||||
|
//If its the white's turn we want to see if the white king is still safe.
|
||||||
|
ret_val = Check_Current_Players_Check_Status(game_state);
|
||||||
|
game_state->board_pieces[row*8+column] = store_current_piece;
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function for checking the selected piece 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 piece.
|
||||||
|
* @param column: Current column location of the piece.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
void Check_If_Moving_King(uint8_t row, uint8_t column, Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
uint8_t white_black_idx = game_state->player_turn ? 0u : 1u;
|
||||||
|
if((game_state->selected_peice == KING_WHITE) || (game_state->selected_peice == KING_BLACK))
|
||||||
|
{
|
||||||
|
King_Locations[white_black_idx][0u] = row;
|
||||||
|
King_Locations[white_black_idx][1u] = column;
|
||||||
|
game_state->castling_allowed[white_black_idx][0u] = false;
|
||||||
|
game_state->castling_allowed[white_black_idx][1u] = false;
|
||||||
|
}
|
||||||
|
// Disable the castling of the corresponding side if the rook is being moved.
|
||||||
|
else if (((game_state->selected_peice == ROOK_WHITE) && (row == 7u))
|
||||||
|
|| ((game_state->selected_peice == ROOK_BLACK) && (row == 0u)))
|
||||||
|
{
|
||||||
|
if (column == 0u)
|
||||||
|
{
|
||||||
|
game_state->castling_allowed[white_black_idx][0u] = false;
|
||||||
|
}
|
||||||
|
else if (column == 7u)
|
||||||
|
{
|
||||||
|
game_state->castling_allowed[white_black_idx][1u] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
6
src/game_logic/piece_logic/king.h
Normal file
6
src/game_logic/piece_logic/king.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#include "game_state.h"
|
||||||
|
|
||||||
|
bool Check_Current_Players_Check_Status(Game_State_t * game_state);
|
||||||
|
bool Check_If_Move_Caused_Check(uint8_t piece, uint8_t row, uint8_t column, Game_State_t * game_state);
|
||||||
|
void Check_If_Moving_King(uint8_t row, uint8_t column, Game_State_t * game_state);
|
||||||
|
|
93
src/game_logic/piece_logic/pawn.c
Normal file
93
src/game_logic/piece_logic/pawn.c
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
#include "pawn.h"
|
||||||
|
#include "game_state.h"
|
||||||
|
#include "piece_logic.h"
|
||||||
|
|
||||||
|
static bool Converting_Pawn = false;
|
||||||
|
static uint8_t Converting_Pawn_Row_Col[2];
|
||||||
|
static uint8_t Pawn_Converted_To = QUEEN_WHITE;
|
||||||
|
|
||||||
|
void Check_If_Converting_Pawn(uint8_t row, uint8_t column, Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
uint8_t white_black_idx = game_state->player_turn ? 0u : 1u;
|
||||||
|
Converting_Pawn = false;
|
||||||
|
|
||||||
|
if((game_state->selected_peice == PAWN_WHITE) || (game_state->selected_peice == PAWN_BLACK))
|
||||||
|
{
|
||||||
|
if((row == 0u) || (row == 7u))
|
||||||
|
{
|
||||||
|
game_state->selected_peice = game_state->player_turn ? QUEEN_WHITE : QUEEN_BLACK;
|
||||||
|
Pawn_Converted_To = game_state->selected_peice;
|
||||||
|
Converting_Pawn = true;
|
||||||
|
Converting_Pawn_Row_Col[0] = row;
|
||||||
|
Converting_Pawn_Row_Col[1] = column;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Converting_Pawn_If_Applicable(uint8_t row, uint8_t column, Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
bool ret_val = false;
|
||||||
|
if(Converting_Pawn)
|
||||||
|
{
|
||||||
|
if((row == Converting_Pawn_Row_Col[0]) &&
|
||||||
|
(Converting_Pawn_Row_Col[1] == column))
|
||||||
|
{
|
||||||
|
//Putting the piece down on the board
|
||||||
|
if(game_state->board_pieces[row*8+column] == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
game_state->board_pieces[row*8+column] = Pawn_Converted_To;
|
||||||
|
game_state->board_state[row*8+column] = LIGHT_OFF;
|
||||||
|
}
|
||||||
|
//Picking the piece back up to toggle through the options
|
||||||
|
else
|
||||||
|
{
|
||||||
|
game_state->board_pieces[row*8+column] = SQUARE_EMPTY;
|
||||||
|
game_state->board_state[row*8+column] = CONVERTING_PAWN;
|
||||||
|
Pawn_Converted_To = Pawn_Converted_To - 2;
|
||||||
|
if (Pawn_Converted_To < ROOK_WHITE)
|
||||||
|
{
|
||||||
|
Pawn_Converted_To += 8u;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
ret_val = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function for marking potential moves for pawns.
|
||||||
|
* @param row: row to move to
|
||||||
|
* @param column: column to move to
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
bool pawn_move(uint8_t piece, uint8_t row, uint8_t column, Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
bool ret_val = false;
|
||||||
|
if (game_state->board_pieces[row*8+column] == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
ret_val = Set_Light(piece, row, column, POTENTIAL_MOVE);
|
||||||
|
}
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Marking a piece for taking.
|
||||||
|
* @param row: Row ofcoarse
|
||||||
|
* @param column: Column obviously
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
bool pawn_take(uint8_t piece, uint8_t row, uint8_t column, Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
bool ret_val = false;
|
||||||
|
if ((game_state->board_pieces[row*8+column] < SQUARE_EMPTY) && opposite_teams(piece, game_state->board_pieces[row*8+column]))
|
||||||
|
{
|
||||||
|
ret_val = Set_Light(piece, row, column, POTENTIAL_TAKE);
|
||||||
|
}
|
||||||
|
return ret_val;
|
||||||
|
}
|
7
src/game_logic/piece_logic/pawn.h
Normal file
7
src/game_logic/piece_logic/pawn.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#include "game_state.h"
|
||||||
|
|
||||||
|
|
||||||
|
void Check_If_Converting_Pawn(uint8_t row, uint8_t column, Game_State_t * game_state);
|
||||||
|
bool Converting_Pawn_If_Applicable(uint8_t row, uint8_t column, Game_State_t * game_state);
|
||||||
|
bool pawn_move(uint8_t piece, uint8_t row, uint8_t column, Game_State_t * game_state);
|
||||||
|
bool pawn_take(uint8_t piece, uint8_t row, uint8_t column, Game_State_t * game_state);
|
526
src/game_logic/piece_logic/piece_logic.c
Normal file
526
src/game_logic/piece_logic/piece_logic.c
Normal file
@ -0,0 +1,526 @@
|
|||||||
|
#include "piece_logic.h"
|
||||||
|
#include "king.h"
|
||||||
|
#include "pawn.h"
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function for determining if the piece is on the white team or on the black team.
|
||||||
|
* @note Pieces should be enumerated even if white and odd if black.
|
||||||
|
* @param piece: The piece under question.
|
||||||
|
* @retval Return true if on the white team, else false.
|
||||||
|
*/
|
||||||
|
bool white_team(uint8_t piece)
|
||||||
|
{
|
||||||
|
return ((piece % 2u) == 0u);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function for determining if two pieces are on the same team or not.
|
||||||
|
* @param piece_one: Piece one ofcoarse.
|
||||||
|
* @param piece_two: Piece two obviously.
|
||||||
|
* @retval True if on opposite teams, else false.
|
||||||
|
*/
|
||||||
|
bool opposite_teams(uint8_t piece_one, uint8_t piece_two)
|
||||||
|
{
|
||||||
|
return (((piece_one % 2u) == 0u) ^ ((piece_two % 2u) == 0u));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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 row, uint8_t column, Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
int temp = (int)row + (game_state->player_turn ? -1 : 1);
|
||||||
|
|
||||||
|
/* first check if pawns can take us */
|
||||||
|
if ((column > 0) && ((game_state->player_turn ? PAWN_BLACK : PAWN_WHITE) == game_state->board_pieces[temp*8+(int)column - 1]))
|
||||||
|
{
|
||||||
|
//can be eaten by a pawn, not safe.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if ((column < 7) && ((game_state->player_turn ? PAWN_BLACK : PAWN_WHITE) == game_state->board_pieces[temp*8+(int)column + 1]))
|
||||||
|
{
|
||||||
|
//can be eaten by a pawn, not safe.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Other King */
|
||||||
|
int start_r = (row == 0u) ? 0 : -1;
|
||||||
|
int stop_r = (row == 7u) ? 0 : 1;
|
||||||
|
int start_c = (column == 0u) ? 0 : -1;
|
||||||
|
int stop_c = (column == 7u) ? 0 : 1;
|
||||||
|
for (int up_down = start_r; up_down <= stop_r; up_down++)
|
||||||
|
{
|
||||||
|
for (int left_right = start_c; left_right <= stop_c; left_right++)
|
||||||
|
{
|
||||||
|
int x = row + left_right;
|
||||||
|
int y = column + up_down;
|
||||||
|
if ((game_state->player_turn ? KING_BLACK : KING_WHITE) == game_state->board_pieces[x*8+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;
|
||||||
|
int x = (int)row;
|
||||||
|
int y = (int)column;
|
||||||
|
while (loop)
|
||||||
|
{
|
||||||
|
x += left_right_step;
|
||||||
|
y += up_down_step;
|
||||||
|
if ((x < 0) || (y < 0) || (x >= 8) || (y >= 8))
|
||||||
|
{
|
||||||
|
loop = false;
|
||||||
|
}
|
||||||
|
else if (game_state->board_pieces[x*8+y] == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
else if (((game_state->player_turn ? ROOK_BLACK : ROOK_WHITE) == game_state->board_pieces[x*8+y]) || ((game_state->player_turn ? QUEEN_BLACK : QUEEN_WHITE) == game_state->board_pieces[x*8+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;
|
||||||
|
int x = (int)row;
|
||||||
|
int y = (int)column;
|
||||||
|
while (loop)
|
||||||
|
{
|
||||||
|
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 (game_state->board_pieces[x*8+y] == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
/* do nothing */
|
||||||
|
}
|
||||||
|
else if ((bish == game_state->board_pieces[x*8+y]) || (queen == game_state->board_pieces[x*8+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)row + left_right_step;
|
||||||
|
int8_t y = (int8_t)column + up_down_step;
|
||||||
|
if ((x >= 0) && (y >= 0) && (x < 8) && (y < 8))
|
||||||
|
{
|
||||||
|
if ((game_state->player_turn ? KNIGHT_BLACK : KNIGHT_WHITE) == game_state->board_pieces[x*8+y])
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @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: the piece that is casting the ray.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
bool cast_a_ray(uint8_t piece, int8_t direction_r, int8_t direction_c, uint8_t column, uint8_t row, Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
bool ret_val = false;
|
||||||
|
bool loop = true;
|
||||||
|
int x = row;
|
||||||
|
int y = column;
|
||||||
|
while (loop)
|
||||||
|
{
|
||||||
|
x += direction_c;
|
||||||
|
y += direction_r;
|
||||||
|
if((x < 0) || (y < 0) || (x >= 8) || (y >= 8))
|
||||||
|
{
|
||||||
|
loop = false;
|
||||||
|
}
|
||||||
|
else if (game_state->board_pieces[x*8+y] == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
ret_val = Set_Light(piece, (uint8_t)x, (uint8_t)y, POTENTIAL_MOVE) || ret_val;
|
||||||
|
}
|
||||||
|
else if (opposite_teams(piece, game_state->board_pieces[x*8+y]))
|
||||||
|
{
|
||||||
|
ret_val = Set_Light(piece, (uint8_t)x, (uint8_t)y, POTENTIAL_TAKE) || ret_val;
|
||||||
|
/* once we take a piece we can no longer take anymore */
|
||||||
|
loop = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loop = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Check_If_Player_Can_Move(bool white, Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
for (uint8_t row = 0; row < 8u; row++)
|
||||||
|
{
|
||||||
|
for (uint8_t column = 0; column < 8u; column++)
|
||||||
|
{
|
||||||
|
if((white_team(game_state->board_pieces[row*8+column]) == white))
|
||||||
|
{
|
||||||
|
// SDL_Log("move: Row:%d, Col:%d", row, column);
|
||||||
|
|
||||||
|
if(Mark_Potential_Moves(game_state->board_pieces[row*8+column], column, row, game_state))
|
||||||
|
{
|
||||||
|
// SDL_Log("Player Can still move: Row:%d, Col:%d", row, column);
|
||||||
|
clear_board_state();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
clear_board_state();
|
||||||
|
// SDL_Log("Player cant move");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Function for marking the potential moves.
|
||||||
|
* @param piece: Piece that we are marking the potential moves for.
|
||||||
|
* @param row: Current row location of the piece.
|
||||||
|
* @param column: Current column location of the piece.
|
||||||
|
* @retval None
|
||||||
|
*/
|
||||||
|
bool Mark_Potential_Moves(uint8_t piece, uint8_t column, uint8_t row, Game_State_t * game_state)
|
||||||
|
{
|
||||||
|
bool ret_val = false;
|
||||||
|
switch (piece)
|
||||||
|
{
|
||||||
|
case PAWN_WHITE :
|
||||||
|
case PAWN_BLACK:
|
||||||
|
{
|
||||||
|
int direction = white_team(piece) ? -1 : 1;
|
||||||
|
uint8_t temp_row = (uint8_t)((int)row + direction);
|
||||||
|
if (row == (white_team(piece) ? 6u : 1u))
|
||||||
|
{
|
||||||
|
if(game_state->board_pieces[temp_row*8u+column] == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
ret_val = pawn_move(piece, (uint8_t)((int)row + (direction * 2)), column, game_state) || ret_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret_val = pawn_move(piece, temp_row, column, game_state) || ret_val;
|
||||||
|
if(column != 0)
|
||||||
|
{
|
||||||
|
ret_val = pawn_take(piece, temp_row, column - 1u, game_state) || ret_val;
|
||||||
|
}
|
||||||
|
if(column != 7u)
|
||||||
|
{
|
||||||
|
ret_val = pawn_take(piece, temp_row, column + 1u, game_state) || ret_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
ret_val = cast_a_ray(piece, up_down_step, left_right_step, column, row, game_state) || ret_val;
|
||||||
|
}
|
||||||
|
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)row + left_right_step;
|
||||||
|
int8_t y = (int8_t)column + up_down_step;
|
||||||
|
if ((x >= 0) && (y >= 0) && (x < 8) && (y < 8))
|
||||||
|
{
|
||||||
|
if (game_state->board_pieces[x*8+y] == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
ret_val = Set_Light(piece, (uint8_t)x, (uint8_t)y, POTENTIAL_MOVE) || ret_val;
|
||||||
|
}
|
||||||
|
else if (opposite_teams(piece, game_state->board_pieces[x*8+y]))
|
||||||
|
{
|
||||||
|
ret_val = Set_Light(piece, (uint8_t)x, (uint8_t)y, POTENTIAL_TAKE) || ret_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
ret_val = cast_a_ray(piece, up_down_step, left_right_step, column, row, game_state) || ret_val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case QUEEN_WHITE:
|
||||||
|
case QUEEN_BLACK:
|
||||||
|
{
|
||||||
|
//Mark bishop moves
|
||||||
|
ret_val = Mark_Potential_Moves((piece - 2u), column, row, game_state) || ret_val;
|
||||||
|
//Mark rook moves
|
||||||
|
ret_val = Mark_Potential_Moves((piece - 6u), column, row, game_state) || ret_val;
|
||||||
|
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 left_right = start_r; left_right <= stop_r; left_right++)
|
||||||
|
{
|
||||||
|
for (int8_t up_down = start_c; up_down <= stop_c; up_down++)
|
||||||
|
{
|
||||||
|
int8_t x = row + left_right;
|
||||||
|
int8_t y = column + up_down;
|
||||||
|
if (square_is_safe(x, y, game_state))
|
||||||
|
{
|
||||||
|
if (game_state->board_pieces[x*8+y] == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
game_state->board_state[x*8+y] = POTENTIAL_MOVE;
|
||||||
|
ret_val = true;
|
||||||
|
}
|
||||||
|
else if (opposite_teams(piece, game_state->board_pieces[x*8+y]))
|
||||||
|
{
|
||||||
|
game_state->board_state[x*8+y] = POTENTIAL_TAKE;
|
||||||
|
ret_val = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
uint8_t white_black_idx = white_team(piece) ? 0u : 1u;
|
||||||
|
uint8_t kings_row = white_team(piece) ? 7u : 0u;
|
||||||
|
|
||||||
|
//Can only castle if not currently in check
|
||||||
|
if (square_is_safe(row, column, game_state))
|
||||||
|
{
|
||||||
|
// Queen side castle
|
||||||
|
if(game_state->castling_allowed[white_black_idx][0u] && (game_state->board_pieces[kings_row*8+1u] == SQUARE_EMPTY)
|
||||||
|
&& (game_state->board_pieces[kings_row*8+2u] == SQUARE_EMPTY) && (game_state->board_pieces[kings_row*8+3u]) == SQUARE_EMPTY)
|
||||||
|
{
|
||||||
|
//First Check to see if the king will pass through check
|
||||||
|
if(square_is_safe(kings_row, 3u, game_state) && square_is_safe(kings_row, 2u, game_state))
|
||||||
|
{
|
||||||
|
// Yay we can castle queen side!
|
||||||
|
game_state->board_state[kings_row*8+2u] = POTENTIAL_CASTLE;
|
||||||
|
ret_val = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// King side castle
|
||||||
|
if (game_state->castling_allowed[white_black_idx][1u] && (game_state->board_pieces[kings_row*8+5u] == SQUARE_EMPTY) && (game_state->board_pieces[kings_row*8+6u] == SQUARE_EMPTY))
|
||||||
|
{
|
||||||
|
//First Check to see if the king will pass through check
|
||||||
|
if(square_is_safe(kings_row, 5u, game_state) && square_is_safe(kings_row, 6u, game_state))
|
||||||
|
{
|
||||||
|
// Yay we can castle king side!
|
||||||
|
game_state->board_state[kings_row*8+6u] = POTENTIAL_CASTLE;
|
||||||
|
ret_val = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret_val;
|
||||||
|
}
|
||||||
|
|
13
src/game_logic/piece_logic/piece_logic.h
Normal file
13
src/game_logic/piece_logic/piece_logic.h
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
#ifndef PIECE_LOGIC_H
|
||||||
|
#define PIECE_LOGIC_H
|
||||||
|
|
||||||
|
#include "game_state.h"
|
||||||
|
|
||||||
|
bool white_team(uint8_t piece);
|
||||||
|
bool opposite_teams(uint8_t piece_one, uint8_t piece_two);
|
||||||
|
bool square_is_safe(uint8_t row, uint8_t column, Game_State_t * game_state);
|
||||||
|
bool cast_a_ray(uint8_t piece, int8_t direction_r, int8_t direction_c, uint8_t column, uint8_t row, Game_State_t * game_state);
|
||||||
|
bool Check_If_Player_Can_Move(bool white, Game_State_t * game_state);
|
||||||
|
bool Mark_Potential_Moves(uint8_t piece, uint8_t column, uint8_t row, Game_State_t * game_state);
|
||||||
|
|
||||||
|
#endif
|
@ -6,7 +6,7 @@
|
|||||||
#include <SDL2/SDL.h>
|
#include <SDL2/SDL.h>
|
||||||
#include <SDL2/SDL_video.h>
|
#include <SDL2/SDL_video.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include "chess_board.h"
|
#include "game_state.h"
|
||||||
#include "user_interface_abstraction.h"
|
#include "user_interface_abstraction.h"
|
||||||
|
|
||||||
static clock_t start_time, end_time;
|
static clock_t start_time, end_time;
|
||||||
@ -19,7 +19,7 @@ int begin_game(SDL_Renderer *renderer, SDL_Window *win)
|
|||||||
srcR.w = 800;
|
srcR.w = 800;
|
||||||
destR.h = 800;
|
destR.h = 800;
|
||||||
destR.w = 800;
|
destR.w = 800;
|
||||||
chess_board_init();
|
game_state_init();
|
||||||
ui_resize(renderer, 800, 800);
|
ui_resize(renderer, 800, 800);
|
||||||
ui_init(renderer);
|
ui_init(renderer);
|
||||||
srcR.x = 0;
|
srcR.x = 0;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#include "user_interface_abstraction.h"
|
#include "user_interface_abstraction.h"
|
||||||
#include "chess_board.h"
|
#include "game_state.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#define MARGIN 300
|
#define MARGIN 300
|
||||||
@ -31,7 +31,7 @@ static uint8_t Current_Binary_Board[8] = {0};
|
|||||||
* @param board_state board state
|
* @param board_state board state
|
||||||
* @param game_state games state
|
* @param game_state games state
|
||||||
*/
|
*/
|
||||||
static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t board_state[8][8], Game_State_t game_state)
|
static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t * board_state, Game_State_t game_state)
|
||||||
{
|
{
|
||||||
SDL_SetRenderTarget(p_renderer, Board_Texture);
|
SDL_SetRenderTarget(p_renderer, Board_Texture);
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0x7f, 0x7f, 0x7f, 0);
|
SDL_SetRenderDrawColor(p_renderer, 0x7f, 0x7f, 0x7f, 0);
|
||||||
@ -69,10 +69,10 @@ static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t board_state[8][8]
|
|||||||
Rectangle.x = starting_x;
|
Rectangle.x = starting_x;
|
||||||
for (size_t i = 0; i < 8; i++)
|
for (size_t i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if((board_state[j][i] & 0x0Fu) != SQUARE_EMPTY)
|
if((board_state[j*8+i] & 0x0Fu) != SQUARE_EMPTY)
|
||||||
{
|
{
|
||||||
uint8_t * render_color;
|
uint8_t * render_color;
|
||||||
if((board_state[j][i] % 2u) == 0u )
|
if((board_state[j*8+i] % 2u) == 0u )
|
||||||
{
|
{
|
||||||
render_color = white_color;
|
render_color = white_color;
|
||||||
}
|
}
|
||||||
@ -83,7 +83,7 @@ static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t board_state[8][8]
|
|||||||
SDL_SetRenderDrawColor(p_renderer, render_color[0], render_color[1], render_color[2], render_color[3]);
|
SDL_SetRenderDrawColor(p_renderer, render_color[0], render_color[1], render_color[2], render_color[3]);
|
||||||
SDL_RenderFillRect(p_renderer, &Rectangle);
|
SDL_RenderFillRect(p_renderer, &Rectangle);
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
|
||||||
SDL_RenderCopy(p_renderer, bitmapTextures[(board_state[j][i] & 0x0Fu)], NULL, &Rectangle);
|
SDL_RenderCopy(p_renderer, bitmapTextures[(board_state[j*8+i] & 0x0Fu)], NULL, &Rectangle);
|
||||||
}
|
}
|
||||||
else if (((i % 2) + (j % 2)) == 1)
|
else if (((i % 2) + (j % 2)) == 1)
|
||||||
{
|
{
|
||||||
@ -109,7 +109,7 @@ static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t board_state[8][8]
|
|||||||
* @param *p_renderer pointer to the renderer object:
|
* @param *p_renderer pointer to the renderer object:
|
||||||
* @retval None
|
* @retval None
|
||||||
*/
|
*/
|
||||||
static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t board_lights[12][8], uint8_t board_state[12][8])
|
static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t * board_lights, uint8_t * board_state)
|
||||||
{
|
{
|
||||||
SDL_SetRenderTarget(p_renderer, Board_Texture);
|
SDL_SetRenderTarget(p_renderer, Board_Texture);
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0x7f, 0x7f, 0x7f, 0);
|
SDL_SetRenderDrawColor(p_renderer, 0x7f, 0x7f, 0x7f, 0);
|
||||||
@ -131,31 +131,31 @@ static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t board_lights[12][8],
|
|||||||
Rectangle.x = starting_x;
|
Rectangle.x = starting_x;
|
||||||
for (size_t i = 0; i < 8; i++)
|
for (size_t i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if ((board_lights[j][i] == POTENTIAL_MOVE) || (board_lights[j][i] == POTENTIAL_CASTLE))
|
if ((board_lights[j*8+i] == POTENTIAL_MOVE) || (board_lights[j*8+i] == POTENTIAL_CASTLE))
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0x00, 0xFF, 0x00, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0x00, 0xFF, 0x00, 0x00);
|
||||||
SDL_RenderFillRect(p_renderer, &Rectangle);
|
SDL_RenderFillRect(p_renderer, &Rectangle);
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
|
||||||
}
|
}
|
||||||
else if ((board_lights[j][i] == POTENTIAL_TAKE) || (board_lights[j][i] == PIECE_NEEDS_TO_BE_HERE) || (board_lights[j][i] == PIECE_NEEDS_TO_BE_REMOVED))
|
else if ((board_lights[j*8+i] == POTENTIAL_TAKE) || (board_lights[j*8+i] == PIECE_NEEDS_TO_BE_HERE) || (board_lights[j*8+i] == PIECE_NEEDS_TO_BE_REMOVED))
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0x00, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0x00, 0x00);
|
||||||
SDL_RenderFillRect(p_renderer, &Rectangle);
|
SDL_RenderFillRect(p_renderer, &Rectangle);
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
|
||||||
}
|
}
|
||||||
else if (board_lights[j][i] == PIECE_ORIGIN)
|
else if (board_lights[j*8+i] == PIECE_ORIGIN)
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0xFF, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0xFF, 0x00);
|
||||||
SDL_RenderFillRect(p_renderer, &Rectangle);
|
SDL_RenderFillRect(p_renderer, &Rectangle);
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
|
||||||
}
|
}
|
||||||
else if (board_lights[j][i] == ERROR_MOVE)
|
else if (board_lights[j*8+i] == ERROR_MOVE)
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0x00, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0x00, 0x00);
|
||||||
SDL_RenderFillRect(p_renderer, &Rectangle);
|
SDL_RenderFillRect(p_renderer, &Rectangle);
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
|
||||||
}
|
}
|
||||||
else if (board_lights[j][i] == CONVERTING_PAWN)
|
else if (board_lights[j*8+i] == CONVERTING_PAWN)
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x3B, 0x7A, 0x57);
|
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x3B, 0x7A, 0x57);
|
||||||
SDL_RenderFillRect(p_renderer, &Rectangle);
|
SDL_RenderFillRect(p_renderer, &Rectangle);
|
||||||
@ -170,9 +170,9 @@ static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t board_lights[12][8],
|
|||||||
/* code */
|
/* code */
|
||||||
}
|
}
|
||||||
|
|
||||||
if((board_state[j][i] & 0x0Fu) != SQUARE_EMPTY)
|
if((board_state[j*8+i] & 0x0Fu) != SQUARE_EMPTY)
|
||||||
{
|
{
|
||||||
SDL_RenderCopy(p_renderer, bitmapTextures[(board_state[j][i] & 0x0Fu)], NULL, &Rectangle);
|
SDL_RenderCopy(p_renderer, bitmapTextures[(board_state[j*8+i] & 0x0Fu)], NULL, &Rectangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle.x += square_size;
|
Rectangle.x += square_size;
|
||||||
@ -191,13 +191,13 @@ static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t board_lights[12][8],
|
|||||||
Rectangle.y = starting_y;
|
Rectangle.y = starting_y;
|
||||||
for (size_t i = 0; i < 8; i++)
|
for (size_t i = 0; i < 8; i++)
|
||||||
{
|
{
|
||||||
if (board_lights[j][i] == PIECE_NEEDS_TO_BE_HERE)
|
if (board_lights[j*8+i] == PIECE_NEEDS_TO_BE_HERE)
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0x00, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x00, 0x00, 0x00);
|
||||||
SDL_RenderFillRect(p_renderer, &Rectangle);
|
SDL_RenderFillRect(p_renderer, &Rectangle);
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0x6F, 0x6F, 0x6F, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0x6F, 0x6F, 0x6F, 0x00);
|
||||||
}
|
}
|
||||||
else if (board_lights[j][i] == ERROR_MOVE)
|
else if (board_lights[j*8+i] == ERROR_MOVE)
|
||||||
{
|
{
|
||||||
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0x00, 0x00);
|
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0x00, 0x00);
|
||||||
SDL_RenderFillRect(p_renderer, &Rectangle);
|
SDL_RenderFillRect(p_renderer, &Rectangle);
|
||||||
@ -210,9 +210,9 @@ static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t board_lights[12][8],
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ((board_state[j][i] & 0x0Fu) != SQUARE_EMPTY)
|
if ((board_state[j*8+i] & 0x0Fu) != SQUARE_EMPTY)
|
||||||
{
|
{
|
||||||
SDL_RenderCopy(p_renderer, bitmapTextures[(board_state[j][i] & 0x0Fu)], NULL, &Rectangle);
|
SDL_RenderCopy(p_renderer, bitmapTextures[(board_state[j*8+i] & 0x0Fu)], NULL, &Rectangle);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -236,8 +236,8 @@ static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t board_lights[12][8],
|
|||||||
|
|
||||||
void ui_redraw_board(SDL_Renderer *p_renderer)
|
void ui_redraw_board(SDL_Renderer *p_renderer)
|
||||||
{
|
{
|
||||||
uint8_t board_lights[8][8];
|
uint8_t board_lights[8*8];
|
||||||
uint8_t board_state[8][8];
|
uint8_t board_state[8*8];
|
||||||
Game_State_t game_state = Board_get_game_state();
|
Game_State_t game_state = Board_get_game_state();
|
||||||
Board_get_lights_and_state(board_lights, board_state);
|
Board_get_lights_and_state(board_lights, board_state);
|
||||||
if(game_state.game_over)
|
if(game_state.game_over)
|
||||||
|
Loading…
Reference in New Issue
Block a user