fen_strings (#1)

Co-authored-by: Daniel Weber <djweber12@gmail.com>
Reviewed-on: djweber12/Chess_Board_Sim#1
Co-authored-by: Daniel Weber <djweber12@hotmail.com>
Co-committed-by: Daniel Weber <djweber12@hotmail.com>
This commit is contained in:
Daniel Weber 2024-10-04 21:42:35 -04:00 committed by djweber12
parent bc20e3b1a8
commit b284eea463
17 changed files with 400 additions and 106 deletions

49
.drone.yml Normal file
View File

@ -0,0 +1,49 @@
kind: pipeline
type: docker
name: chessboard
trigger:
branch:
- main
event:
- push
steps:
- name: build
image: git.pipsquire.com/djweber12/Chess_Board_Sim:latest
commands:
- cmake -S . -B build
- cmake --build build
---
kind: pipeline
type: docker
name: chessboard_builder
trigger:
branch:
- main
event:
- push
steps:
- name: docker
image: plugins/docker
settings:
repo: git.pipsquire.com/djweber12/Chess_Board_Sim
registry: git.pipsquire.com
username:
from_secret: docker_username
password:
from_secret: docker_password
#
# - name: test
# image: foo:latest
# commands:
# - cmake -s . -b build
# - cmake --build build
#
# volumes:
# - name: dockersock

View File

@ -1,33 +1,5 @@
cmake_minimum_required(VERSION 3.8)
project(Chess C CXX)
find_package(SDL2 REQUIRED)
file(GLOB_RECURSE cpp_sources
CONFIGURE_DEPENDS
"src/*.cpp")
file(GLOB_RECURSE c_sources
CONFIGURE_DEPENDS
"src/*.c")
file (GLOB_RECURSE headers CONFIGURE_DEPENDS "src/*.h")
set (include_dirs "")
foreach (_headerFile ${headers})
get_filename_component(_dir ${_headerFile} PATH)
list (APPEND include_dirs ${_dir})
endforeach()
add_executable(Chess ${cpp_sources} ${c_sources})
set_target_properties(Chess PROPERTIES CXX_STANDARD 17) # set standard level
target_include_directories(Chess PRIVATE ${include_dirs})
target_compile_options(Chess PRIVATE
-Wall -Wextra -Wredundant-decls -Wcast-align
-Wshadow -Wnon-virtual-dtor
-Wunused -Woverloaded-virtual -Wpedantic -Wconversion
-Wsign-conversion -Wmisleading-indentation
-Wnull-dereference -Wformat=2
)
target_link_libraries(Chess SDL2::SDL2)
cmake_minimum_required(VERSION 3.8)
project(Chess C CXX)
add_subdirectory(src)
add_subdirectory(test)

6
Dockerfile Normal file
View File

@ -0,0 +1,6 @@
FROM ubuntu:22.04
run apt-get update && \
apt-get install -y libsdl2-dev libsdl2-2.0-0 cmake g++ && \
apt-get clean

32
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,32 @@
cmake_minimum_required(VERSION 3.8)
find_package(SDL2 REQUIRED)
file(GLOB_RECURSE cpp_sources
CONFIGURE_DEPENDS
"./*.cpp")
file(GLOB_RECURSE c_sources
CONFIGURE_DEPENDS
"./*.c")
file (GLOB_RECURSE headers CONFIGURE_DEPENDS "./*.h")
set (include_dirs "")
foreach (_headerFile ${headers})
get_filename_component(_dir ${_headerFile} PATH)
list (APPEND include_dirs ${_dir})
endforeach()
add_executable(Chess ${cpp_sources} ${c_sources})
set_target_properties(Chess PROPERTIES CXX_STANDARD 17) # set standard level
target_include_directories(Chess PRIVATE ${include_dirs})
target_compile_options(Chess PRIVATE
-Wall -Wextra -Wredundant-decls -Wcast-align
-Wshadow -Wnon-virtual-dtor
-Wunused -Woverloaded-virtual -Wpedantic -Wconversion
-Wsign-conversion -Wmisleading-indentation
-Wnull-dereference -Wformat=2
)
target_link_libraries(Chess SDL2::SDL2)

View File

@ -0,0 +1,121 @@
#include "fen_strings.h"
#include "game_state.h"
#include "string.h"
#include "assert.h"
char fen_string[200];
int fen_idx = 0;
static void fen_append(char val)
{
assert(fen_idx < (int)sizeof(fen_string));
fen_string[fen_idx] = val;
fen_idx++;
}
char * fen_string_get_state(void)
{
memset(fen_string, (int)' ', sizeof(fen_string));
fen_idx = 0;
Game_State_t * state = Board_get_game_state();
for (int row = 0; row < 8; row++)
{
int consec_empty = 0;
for (int column = 0; column < 8; column++)
{
if((state->board_pieces[row * 8 + column] == SQUARE_EMPTY))
{
consec_empty++;
if (column == 7) {
fen_append((char)('0' + consec_empty));
}
}
else
{
char ret_val;
if (consec_empty != 0)
{
fen_append((char)('0' + consec_empty));
consec_empty = 0;
}
switch (state->board_pieces[row * 8 + column])
{
case PAWN_WHITE:
fen_append('P');
break;
case PAWN_BLACK:
fen_append('p');
break;
case KING_WHITE:
fen_append('K');
break;
case KING_BLACK:
fen_append('k');
break;
case ROOK_WHITE:
fen_append('R');
break;
case ROOK_BLACK:
fen_append('r');
break;
case KNIGHT_WHITE:
fen_append('N');
break;
case KNIGHT_BLACK:
fen_append('n');
break;
case BISHOP_WHITE:
fen_append('B');
break;
case BISHOP_BLACK:
fen_append('b');
break;
case QUEEN_WHITE:
fen_append('Q');
break;
case QUEEN_BLACK:
fen_append('q');
break;
}
}
}
if (row != 7) fen_append('/');
}
fen_append(' ');
if (state->player_turn) {
fen_append('w');
}
else{
fen_append('b');
}
fen_append(' ');
char options[2][2] = {{'K', 'Q'}, {'k', 'q'}};
bool castle = false;
for(int color = 0; color < 2; color++){
for(int k_q = 0; k_q < 2; k_q++){
if(state->castling_allowed[color][k_q])
{
castle = true;
fen_append(options[color][k_q]);
}
}
}
if (!castle) {
fen_append('-');
}
fen_append(' ');
if(state->en_passant < 0)
{
fen_append('-');
}
else
{
fen_append((char)('a'+(state->en_passant % 8)));
fen_append((char)('0'+(state->en_passant / 8)));
}
fen_append('\0');
return fen_string;
}

View File

@ -0,0 +1,10 @@
#ifdef __cplusplus
extern "C" {
#endif
char * fen_string_get_state(void);
void fen_string_set_state(char *);
#ifdef __cplusplus
}
#endif

View File

@ -13,8 +13,9 @@ static Game_State_t Game_State = {
.turn_state = BEGINNING,
.board_state = {0},
.board_pieces = {0},
.selected_peice = SQUARE_EMPTY,
.selected_piece = SQUARE_EMPTY,
.castling_allowed = {{true, true},{true, true}},
.en_passant = -1,
};
static uint8_t Error_Count = 0u;
static bool Check[2u] = {false, false};
@ -90,18 +91,18 @@ static void Board_Square_Was_Toggled(uint8_t row_idx, uint8_t col_idx)
{
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;
Game_State.board_pieces[row_idx*8+col_idx] = Game_State.selected_piece;
Game_State.selected_piece = 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_pieces[row_idx*8+col_idx] = Game_State.selected_piece;
Game_State.selected_piece = SQUARE_EMPTY;
Game_State.board_state[row_idx*8+col_idx] = LIGHT_OFF;
if (Game_State.selected_peice == SQUARE_EMPTY)
if (Game_State.selected_piece == SQUARE_EMPTY)
{
Game_State.turn_state = BEGINNING;
Game_State.player_turn = !Game_State.player_turn;
@ -133,9 +134,10 @@ static void Board_Square_Was_Toggled(uint8_t row_idx, uint8_t col_idx)
{
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.selected_piece = 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);
(void)Mark_Potential_Moves(Game_State.selected_piece, col_idx, row_idx, &Game_State);
Game_State.selected_piece_origin = row_idx*8+col_idx;
Game_State.board_state[row_idx*8+col_idx] = PIECE_ORIGIN;
Game_State.turn_state = IN_PROGRESS;
}
@ -158,8 +160,9 @@ static void Board_Square_Was_Toggled(uint8_t row_idx, uint8_t col_idx)
{
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_pieces[row_idx*8+col_idx] = Game_State.selected_piece;
Game_State.selected_piece = SQUARE_EMPTY;
Mark_En_Passant_Target(row_idx*8+col_idx, &Game_State);
clear_board_state();
Switch_Turns();
}
@ -172,16 +175,16 @@ static void Board_Square_Was_Toggled(uint8_t row_idx, uint8_t col_idx)
}
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;
Game_State.board_pieces[row_idx*8+col_idx] = Game_State.selected_piece;
Game_State.selected_piece = 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;
Game_State.board_pieces[row_idx*8+col_idx] = Game_State.selected_piece;
Game_State.selected_piece = SQUARE_EMPTY;
clear_board_state();
if(col_idx == 2u)
{
@ -199,9 +202,24 @@ static void Board_Square_Was_Toggled(uint8_t row_idx, uint8_t col_idx)
}
}
else if (Game_State.board_state[row_idx*8+col_idx] == EN_PASSANT)
{
Game_State.board_pieces[row_idx*8+col_idx] = Game_State.selected_piece;
Game_State.selected_piece = SQUARE_EMPTY;
clear_board_state();
if(row_idx == 2u)
{
Game_State.board_state[row_idx*8+col_idx+8] = EN_PASSANT_REMOVE;
}
else if(row_idx == 5u)
{
Game_State.board_state[row_idx*8+col_idx-8] = EN_PASSANT_REMOVE;
}
Game_State.turn_state = FINALIZING;
}
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.selected_piece = 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;
@ -221,10 +239,16 @@ static void Board_Square_Was_Toggled(uint8_t row_idx, uint8_t col_idx)
{
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_pieces[row_idx*8+col_idx] = Game_State.selected_piece;
Game_State.selected_piece = SQUARE_EMPTY;
Game_State.board_state[row_idx*8+col_idx] = LIGHT_OFF;
}
else if (Game_State.board_state[row_idx*8+col_idx] == EN_PASSANT_REMOVE)
{
Game_State.board_pieces[row_idx*8+col_idx] = 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))
@ -235,7 +259,7 @@ static void Board_Square_Was_Toggled(uint8_t row_idx, uint8_t col_idx)
}
}
if (Game_State.selected_peice == SQUARE_EMPTY)
if (Game_State.selected_piece == SQUARE_EMPTY)
{
Switch_Turns();
}
@ -327,9 +351,9 @@ void game_state_init(void)
}
}
Game_State_t Board_get_game_state(void)
Game_State_t * Board_get_game_state(void)
{
return Game_State;
return &Game_State;
}

View File

@ -19,6 +19,8 @@ enum Board_States_t {
POTENTIAL_CASTLE,
PIECE_NEEDS_TO_BE_REMOVED,
CONVERTING_PAWN,
EN_PASSANT,
EN_PASSANT_REMOVE,
};
#define PAWN_WHITE 0u
@ -51,16 +53,17 @@ typedef struct {
Turn_State_t turn_state;
uint8_t board_state[8*8];
uint8_t board_pieces[8*8];
uint8_t selected_peice;
uint8_t selected_piece;
uint8_t selected_piece_origin;
bool castling_allowed[2u][2u];
int en_passant;
}Game_State_t;
void game_state_init(void);
void Board_Changed(uint8_t current_binary_board[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
}

View File

@ -1,4 +1,5 @@
#include "king.h"
#include "game_state.h"
#include "piece_logic.h"
static uint8_t King_Locations[2u][2u] = {{7,4}, {0,4}};
@ -32,7 +33,8 @@ bool Check_If_Move_Caused_Check(uint8_t piece, uint8_t row, uint8_t column, Game
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))
uint8_t inverse_idx = game_state->player_turn ? 1u : 0u;
if((game_state->selected_piece == KING_WHITE) || (game_state->selected_piece == KING_BLACK))
{
King_Locations[white_black_idx][0u] = row;
King_Locations[white_black_idx][1u] = column;
@ -40,17 +42,13 @@ void Check_If_Moving_King(uint8_t row, uint8_t column, Game_State_t * game_state
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 (game_state->board_pieces[inverse_idx*7*8+7] == SQUARE_EMPTY)
{
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;
}
game_state->castling_allowed[white_black_idx][0u] = false;
}
if (game_state->board_pieces[inverse_idx*8*7+0] == SQUARE_EMPTY)
{
game_state->castling_allowed[white_black_idx][1u] = false;
}
}

View File

@ -11,12 +11,12 @@ void Check_If_Converting_Pawn(uint8_t row, uint8_t column, Game_State_t * game_s
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((game_state->selected_piece == PAWN_WHITE) || (game_state->selected_piece == 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;
game_state->selected_piece = game_state->player_turn ? QUEEN_WHITE : QUEEN_BLACK;
Pawn_Converted_To = game_state->selected_piece;
Converting_Pawn = true;
Converting_Pawn_Row_Col[0] = row;
Converting_Pawn_Row_Col[1] = column;
@ -89,5 +89,24 @@ bool pawn_take(uint8_t piece, uint8_t row, uint8_t column, Game_State_t * game_s
{
ret_val = Set_Light(piece, row, column, POTENTIAL_TAKE);
}
else if (game_state->en_passant == row*8+column) {
ret_val = Set_Light(piece, row, column, EN_PASSANT);
}
return ret_val;
}
void Mark_En_Passant_Target(uint8_t location, Game_State_t * game_state)
{
if ((game_state->selected_piece_origin / 8 == 1) || (game_state->selected_piece_origin / 8 == 6))
{
if (((game_state->board_pieces[location] == PAWN_BLACK) && ((location / 8) == 3)) ||
((game_state->board_pieces[location] == PAWN_WHITE) && ((location / 8) == 4)))
{
int offset = game_state->player_turn ? 8 : -8;
game_state->en_passant = location + offset;
return;
}
}
game_state->en_passant = -1;
}

View File

@ -5,3 +5,4 @@ void Check_If_Converting_Pawn(uint8_t row, uint8_t column, Game_State_t * game_s
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);
void Mark_En_Passant_Target(uint8_t location, Game_State_t * game_state);

View File

@ -490,7 +490,7 @@ bool Mark_Potential_Moves(uint8_t piece, uint8_t column, uint8_t row, Game_State
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)
if(game_state->castling_allowed[white_black_idx][1u] && (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
@ -503,7 +503,7 @@ bool Mark_Potential_Moves(uint8_t piece, uint8_t column, uint8_t row, Game_State
}
// 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))
if (game_state->castling_allowed[white_black_idx][0u] && (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))

View File

@ -1,3 +1,4 @@
#include <SDL_log.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
@ -7,6 +8,7 @@
#include <SDL2/SDL_video.h>
#include <time.h>
#include "game_state.h"
#include "fen_strings.h"
#include "user_interface_abstraction.h"
static clock_t start_time, end_time;
@ -50,6 +52,8 @@ int begin_game(SDL_Renderer *renderer, SDL_Window *win)
end_time = clock();
clock_t t = end_time - start_time;
char * fen = fen_string_get_state();
SDL_Log(fen);
SDL_Log("No. of clicks %ld clicks (%f seconds) to process the incoming click.\n", t, ((float)t) / CLOCKS_PER_SEC);
}
else
@ -103,7 +107,3 @@ int begin_game(SDL_Renderer *renderer, SDL_Window *win)
}
return 0;
}
//g++ main.cpp -o blah `sdl2-config --cflags --libs`
/*
g++ main.cpp -IC:\Users\Daniel\Documents\Projects\i686-w64-mingw32\include\SDL2 -LC:\Users\Daniel\Documents\Projects\i686-w64-mingw32\lib -w -Wl,-subsystem,windows -lmingw32 -lSDL2main -lSDL2 -o SDLMain
*/

View File

@ -47,7 +47,3 @@ int main( int argc, const char* argv[] )
SDL_DestroyWindow(win);
return 0;
}
//g++ main.cpp -o blah `sdl2-config --cflags --libs`
/*
g++ main.cpp -IC:\Users\Daniel\Documents\Projects\i686-w64-mingw32\include\SDL2 -LC:\Users\Daniel\Documents\Projects\i686-w64-mingw32\lib -w -Wl,-subsystem,windows -lmingw32 -lSDL2main -lSDL2 -o SDLMain
*/

View File

@ -28,10 +28,10 @@ static uint8_t Current_Binary_Board[8] = {0};
* clearly indicating which player won.
*
* @param p_renderer Sdl Renderer
* @param board_state board state
* @param game_state->board_pieces board state
* @param game_state games state
*/
static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t * board_state, Game_State_t game_state)
static void ui_draw_end_game(SDL_Renderer *p_renderer, Game_State_t * game_state)
{
SDL_SetRenderTarget(p_renderer, Board_Texture);
SDL_SetRenderDrawColor(p_renderer, 0x7f, 0x7f, 0x7f, 0);
@ -50,8 +50,8 @@ static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t * board_state, Ga
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.error_detected){
if(game_state.player_turn)
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;
@ -69,10 +69,10 @@ static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t * board_state, Ga
Rectangle.x = starting_x;
for (size_t i = 0; i < 8; i++)
{
if((board_state[j*8+i] & 0x0Fu) != SQUARE_EMPTY)
if((game_state->board_pieces[j*8+i] & 0x0Fu) != SQUARE_EMPTY)
{
uint8_t * render_color;
if((board_state[j*8+i] % 2u) == 0u )
if((game_state->board_pieces[j*8+i] % 2u) == 0u )
{
render_color = white_color;
}
@ -83,7 +83,7 @@ static void ui_draw_end_game(SDL_Renderer *p_renderer, uint8_t * board_state, Ga
SDL_SetRenderDrawColor(p_renderer, render_color[0], render_color[1], render_color[2], render_color[3]);
SDL_RenderFillRect(p_renderer, &Rectangle);
SDL_SetRenderDrawColor(p_renderer, 0x85, 0x5E, 0x42, 0x00);
SDL_RenderCopy(p_renderer, bitmapTextures[(board_state[j*8+i] & 0x0Fu)], NULL, &Rectangle);
SDL_RenderCopy(p_renderer, bitmapTextures[(game_state->board_pieces[j*8+i] & 0x0Fu)], NULL, &Rectangle);
}
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, Ga
* @param *p_renderer pointer to the renderer object:
* @retval None
*/
static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t * board_lights, uint8_t * board_state)
static void ui_draw_board(SDL_Renderer *p_renderer, Game_State_t * game_state)
{
SDL_SetRenderTarget(p_renderer, Board_Texture);
SDL_SetRenderDrawColor(p_renderer, 0x7f, 0x7f, 0x7f, 0);
@ -131,31 +131,35 @@ static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t * board_lights, uint
Rectangle.x = starting_x;
for (size_t i = 0; i < 8; i++)
{
if ((board_lights[j*8+i] == POTENTIAL_MOVE) || (board_lights[j*8+i] == POTENTIAL_CASTLE))
if ((game_state->board_state[j*8+i] == POTENTIAL_MOVE) || (game_state->board_state[j*8+i] == POTENTIAL_CASTLE))
{
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*8+i] == POTENTIAL_TAKE) || (board_lights[j*8+i] == PIECE_NEEDS_TO_BE_HERE) || (board_lights[j*8+i] == PIECE_NEEDS_TO_BE_REMOVED))
else if ((game_state->board_state[j*8+i] == POTENTIAL_TAKE)
|| (game_state->board_state[j*8+i] == PIECE_NEEDS_TO_BE_HERE)
|| (game_state->board_state[j*8+i] == PIECE_NEEDS_TO_BE_REMOVED)
|| (game_state->board_state[j*8+i] == EN_PASSANT_REMOVE)
|| (game_state->board_state[j*8+i] == EN_PASSANT))
{
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*8+i] == PIECE_ORIGIN)
else if (game_state->board_state[j*8+i] == PIECE_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*8+i] == ERROR_MOVE)
else if (game_state->board_state[j*8+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 (board_lights[j*8+i] == CONVERTING_PAWN)
else if (game_state->board_state[j*8+i] == CONVERTING_PAWN)
{
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0x3B, 0x7A, 0x57);
SDL_RenderFillRect(p_renderer, &Rectangle);
@ -170,9 +174,9 @@ static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t * board_lights, uint
/* code */
}
if((board_state[j*8+i] & 0x0Fu) != SQUARE_EMPTY)
if((game_state->board_pieces[j*8+i] & 0x0Fu) != SQUARE_EMPTY)
{
SDL_RenderCopy(p_renderer, bitmapTextures[(board_state[j*8+i] & 0x0Fu)], NULL, &Rectangle);
SDL_RenderCopy(p_renderer, bitmapTextures[(game_state->board_pieces[j*8+i] & 0x0Fu)], NULL, &Rectangle);
}
Rectangle.x += square_size;
@ -191,13 +195,13 @@ static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t * board_lights, uint
Rectangle.y = starting_y;
for (size_t i = 0; i < 8; i++)
{
if (board_lights[j*8+i] == PIECE_NEEDS_TO_BE_HERE)
if (game_state->board_state[j*8+i] == PIECE_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*8+i] == ERROR_MOVE)
else if (game_state->board_state[j*8+i] == ERROR_MOVE)
{
SDL_SetRenderDrawColor(p_renderer, 0xFF, 0xFF, 0x00, 0x00);
SDL_RenderFillRect(p_renderer, &Rectangle);
@ -210,9 +214,9 @@ static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t * board_lights, uint
if ((board_state[j*8+i] & 0x0Fu) != SQUARE_EMPTY)
if ((game_state->board_pieces[j*8+i] & 0x0Fu) != SQUARE_EMPTY)
{
SDL_RenderCopy(p_renderer, bitmapTextures[(board_state[j*8+i] & 0x0Fu)], NULL, &Rectangle);
SDL_RenderCopy(p_renderer, bitmapTextures[(game_state->board_pieces[j*8+i] & 0x0Fu)], NULL, &Rectangle);
}
@ -236,17 +240,14 @@ static void ui_draw_board(SDL_Renderer *p_renderer, uint8_t * board_lights, uint
void ui_redraw_board(SDL_Renderer *p_renderer)
{
uint8_t board_lights[8*8];
uint8_t board_state[8*8];
Game_State_t game_state = Board_get_game_state();
Board_get_lights_and_state(board_lights, board_state);
if(game_state.game_over)
Game_State_t * game_state = Board_get_game_state();
if(game_state->game_over)
{
ui_draw_end_game(p_renderer, board_state, game_state);
ui_draw_end_game(p_renderer, game_state);
}
else
{
ui_draw_board(p_renderer, board_lights, board_state);
ui_draw_board(p_renderer, game_state);
}
}

50
test/CMakeLists.txt Normal file
View File

@ -0,0 +1,50 @@
find_package(SDL2 REQUIRED)
include(FetchContent)
FetchContent_Declare(
googletest
URL https://github.com/google/googletest/archive/refs/tags/v1.15.2.zip
)
FetchContent_MakeAvailable(googletest)
enable_testing()
file(GLOB_RECURSE cpp_sources
CONFIGURE_DEPENDS
"../src/*.cpp")
list(REMOVE_ITEM cpp_sources
"../src/pc_app/main.cpp")
file(GLOB_RECURSE test_sources
CONFIGURE_DEPENDS
"*.cc")
file(GLOB_RECURSE c_sources
CONFIGURE_DEPENDS
"../src/*.c")
file (GLOB_RECURSE headers CONFIGURE_DEPENDS "../src/*.h")
set (include_dirs "")
foreach (_headerFile ${headers})
get_filename_component(_dir ${_headerFile} PATH)
list (APPEND include_dirs ${_dir})
endforeach()
add_executable(
chess_test
# ${cpp_sources}
${test_sources}
${c_sources}
)
target_include_directories(chess_test PRIVATE ${include_dirs})
target_link_libraries(
chess_test
GTest::gtest_main
SDL2::SDL2
)
include(GoogleTest)
gtest_discover_tests(chess_test)

View File

@ -0,0 +1,12 @@
#include <gtest/gtest.h>
#include "game_state.h"
#include "fen_strings.h"
// Demonstrate some basic assertions.
TEST(GameLogic, initialized_state) {
// Expect two strings not to be equal.
game_state_init();
char * test_data = fen_string_get_state();
EXPECT_STREQ(test_data, "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq -");
}