commit 8c7fe707a1b0d03a91ad0790884264217acd3146 Author: Marcus Penate Date: Thu Apr 14 16:03:32 2022 -0400 Initial version, load default FEN, displays for 5 seconds and closes diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7b05f41 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +chess diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100755 index 0000000..11e5c3d --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,34 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "g++ - Build and debug active project", + "type": "cppdbg", + "request": "launch", + "program": "${fileDirname}/chess", + "args": [], + "stopAtEntry": false, + "cwd": "${fileDirname}", + "environment": [], + "externalConsole": false, + "MIMode": "gdb", + "setupCommands": [ + { + "description": "Enable pretty-printing for gdb", + "text": "-enable-pretty-printing", + "ignoreFailures": true + }, + { + "description": "Set Disassembly Flavor to Intel", + "text": "-gdb-set disassembly-flavor intel", + "ignoreFailures": true + } + ], + "preLaunchTask": "C/C++: g++ build project", + "miDebuggerPath": "/usr/bin/gdb" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100755 index 0000000..1a7ab04 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,30 @@ +{ + "tasks": [ + { + "type": "cppbuild", + "label": "C/C++: g++ build project", + "command": "/usr/bin/g++", + "args": [ + "*.cpp", + "-std=c++1z", + "-fdiagnostics-color=always", + "-g", + "-lSDL2", + "-o", + "./chess" + ], + "options": { + "cwd": "${fileDirname}" + }, + "problemMatcher": [ + "$gcc" + ], + "group": { + "kind": "build", + "isDefault": true + }, + "detail": "Task generated by Debugger." + } + ], + "version": "2.0.0" +} \ No newline at end of file diff --git a/Chess_Pieces_Sprite.bmp b/Chess_Pieces_Sprite.bmp new file mode 100755 index 0000000..ea8071c Binary files /dev/null and b/Chess_Pieces_Sprite.bmp differ diff --git a/app_consts.hpp b/app_consts.hpp new file mode 100755 index 0000000..6cc3253 --- /dev/null +++ b/app_consts.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include + +inline constexpr int SPRITE_SIZE{45}; +inline constexpr int SCREEN_WIDTH{SPRITE_SIZE*8}; +inline constexpr int SCREEN_HEIGHT{SPRITE_SIZE*8}; + +inline constexpr int BOARD_SIZE{8}; + +enum Type +{ + NO_TYPE=-1, + KING=0, + QUEEN=1, + BISHOP=2, + KNIGHT=3, + ROOK=4, + PAWN=5, + UNKNOWN=6, +}; + +enum Team +{ + NO_TEAM=-1, + WHITE=0, + BLACK=1, +}; + +enum Visibility +{ + VIS_NONE=-1, + SHOWN=0, + HIDDEN=1, +}; diff --git a/board.cpp b/board.cpp new file mode 100755 index 0000000..1ceb98b --- /dev/null +++ b/board.cpp @@ -0,0 +1,171 @@ +#include "board.hpp" + +#include + +#include "sprites.hpp" + +Board::Board() +{ + load_FEN(std::string("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/SOCQKCOS w KQkq - 0 1")); +} + +Board::Board(std::string board_fen) +{ + load_FEN(board_fen); +} + +void Board::load_FEN(std::string board_fen) +{ + active_color = WHITE; + able_to_castle[0][0] = false; + able_to_castle[0][1] = false; + able_to_castle[1][0] = false; + able_to_castle[1][1] = false; + half_turn_count = 0; + full_turn_count = 0; + + int x=0,y=0; + std::string black_team("kqbnrpcos"); + std::string white_team("KQBNRPCOS"); + for(int i = 0; i < board_fen.size() && !(x==BOARD_SIZE && y==BOARD_SIZE); i++) + { + if (board_fen[i] == '/') + { + x++; + y=0; + } + else if (std::isdigit(board_fen[i])) + { + y += board_fen[i]-'0'; + } + else + { + size_t loc = black_team.find(board_fen[i],0); + if (std::string::npos != loc) + { + Visibility vis = SHOWN; + if (loc >= UNKNOWN) + { + vis = HIDDEN; + loc -= UNKNOWN; + loc += BISHOP; + } + Type type = (Type)loc; + Team team = BLACK; + + game_board[x][y] = Piece(type, team, vis); + } + else + { + loc = white_team.find(board_fen[i],0); + + if (std::string::npos != loc) + { + Visibility vis = SHOWN; + if (loc >= UNKNOWN) + { + vis = HIDDEN; + loc -= UNKNOWN; + loc += BISHOP; + } + Type type = (Type)loc; + Team team = WHITE; + + game_board[x][y] = Piece(type, team, vis); + } + } + y++; + } + } + + size_t active_color_loc = board_fen.find(' ', 0); + if (std::string::npos == active_color_loc || active_color_loc+1 >= board_fen.size()) + { + return; + } + else + { + active_color_loc = active_color_loc+1; + } + active_color = ('w'==board_fen[active_color_loc])?WHITE:BLACK; + size_t able_to_castle_loc = active_color_loc+2; + while(board_fen[able_to_castle_loc] != ' ') + { + switch(board_fen[able_to_castle_loc]) + { + case 'K': + able_to_castle[WHITE][KING] = true; + break; + case 'Q': + able_to_castle[WHITE][QUEEN] = true; + break; + case 'k': + able_to_castle[BLACK][KING] = true; + break; + case 'q': + able_to_castle[BLACK][QUEEN] = true; + break; + } + able_to_castle_loc++; + } + + size_t en_passant_loc = able_to_castle_loc+1; + while(board_fen[en_passant_loc] != ' ') + { + if (board_fen[en_passant_loc == '-']) + { + en_passant_loc++; + break; + } + + x = board_fen[en_passant_loc]-'a'; + y = board_fen[en_passant_loc]-'0'; + + en_passant.push_back(x+y*BOARD_SIZE); + + en_passant_loc+=2; + } + + size_t half_turn_count_loc = en_passant_loc+1; + const char* board_fen_cstr = board_fen.c_str(); + char* full_turn_count_loc; + half_turn_count = strtol(board_fen_cstr+half_turn_count_loc, &full_turn_count_loc, 10); + full_turn_count = strtol(full_turn_count_loc, nullptr, 10); +} + +void Board::draw_board(SDL_Surface* dest_surface) +{ + bool light_tile = true; + for (int y = 0; y < BOARD_SIZE; y++) + { + for (int x = 0; x < BOARD_SIZE; x++) + { + SDL_Rect dest_rect({SPRITE_SIZE*y,SPRITE_SIZE*x,SPRITE_SIZE,SPRITE_SIZE}); + + uint32_t color = 0; + if (light_tile) + { + color = SDL_MapRGB(dest_surface->format, 235, 236, 208); + } + else + { + color = SDL_MapRGB(dest_surface->format, 119, 149, 86); + } + + SDL_FillRect(dest_surface, &dest_rect, color); + SDL_Surface* piece_surface = SDL_CreateRGBSurfaceWithFormat(0, SPRITE_SIZE, SPRITE_SIZE, 32, dest_surface->format->format); + SDL_FillRect(piece_surface, nullptr, SDL_MapRGB(piece_surface->format, 0xFF, 0x00, 0xFF)); + SDL_SetColorKey(piece_surface, SDL_TRUE, SDL_MapRGB(piece_surface->format, 0xFF, 0x00, 0xFF)); + + if (0 == Sprite::get(game_board[x][y], piece_surface)) + { + SDL_BlitSurface(piece_surface, nullptr, dest_surface, &dest_rect); + } + + SDL_FreeSurface(piece_surface); + + light_tile = !light_tile; + } + light_tile = !light_tile; + } +} \ No newline at end of file diff --git a/board.hpp b/board.hpp new file mode 100755 index 0000000..b2ddc96 --- /dev/null +++ b/board.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +#include "app_consts.hpp" +#include "piece.hpp" + +class Board +{ +public: + Board(); + Board(std::string board_fen); + + void load_FEN(std::string board_fen); + + void draw_board(SDL_Surface* dest_surface); + +private: + Piece game_board[BOARD_SIZE][BOARD_SIZE]; + Team active_color; + bool able_to_castle[2][2]; + std::vector en_passant; + int half_turn_count, full_turn_count; +}; diff --git a/main.cpp b/main.cpp new file mode 100755 index 0000000..c9f06ef --- /dev/null +++ b/main.cpp @@ -0,0 +1,58 @@ +#include + +#include "app_consts.hpp" +#include "board.hpp" +#include "sprites.hpp" + +int main(int argc, char** argv) +{ + //Sourced from lazyfoo's SDL2 tutorials, not really any special code here, just standard init process for the window + //The window we'll be rendering to + SDL_Window* window = NULL; + + //The surface contained by the window + SDL_Surface* screenSurface = NULL; + + //Initialize SDL + if(SDL_Init(SDL_INIT_VIDEO) < 0) + { + printf("SDL could not initialize! SDL_Error: %s\n", SDL_GetError()); + } + else + { + //Create window + window = SDL_CreateWindow("SDL Tutorial", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCREEN_WIDTH, SCREEN_HEIGHT, SDL_WINDOW_SHOWN); + if(window == NULL) + { + printf("Window could not be created! SDL_Error: %s\n", SDL_GetError()); + } + else + { + //Get window surface + screenSurface = SDL_GetWindowSurface(window); + + //Fill the surface white + SDL_FillRect(screenSurface, NULL, SDL_MapRGB(screenSurface->format, 0x00, 0x00, 0x00)); + + Board board; + + board.draw_board(screenSurface); + + //Update the surface + SDL_UpdateWindowSurface(window); + + //Wait two seconds + SDL_Delay(5000); + } + } + + Sprite::close(); + + //Destroy window + SDL_DestroyWindow(window); + + //Quit SDL subsystems + SDL_Quit(); + + return 0; +} \ No newline at end of file diff --git a/piece.cpp b/piece.cpp new file mode 100644 index 0000000..033d611 --- /dev/null +++ b/piece.cpp @@ -0,0 +1,30 @@ +#include "piece.hpp" + +Piece::Piece() +{ + type = NO_TYPE; + team = NO_TEAM; + vis = VIS_NONE; +} + +Piece::Piece(Type type, Team team, Visibility vis) +{ + this->type = type; + this->team = team; + this->vis = vis; +} + +Team Piece::get_team() +{ + return team; +} + +Type Piece::get_type() +{ + return type; +} + +Visibility Piece::get_vis() +{ + return vis; +} \ No newline at end of file diff --git a/piece.hpp b/piece.hpp new file mode 100644 index 0000000..f888b15 --- /dev/null +++ b/piece.hpp @@ -0,0 +1,20 @@ +#pragma once + +#include + +#include "app_consts.hpp" + +class Piece +{ +public: + Piece(); + Piece(Type type, Team team, Visibility vis); + + Team get_team(); + Type get_type(); + Visibility get_vis(); +private: + Type type; + Team team; + Visibility vis; +}; diff --git a/sprites.cpp b/sprites.cpp new file mode 100644 index 0000000..91029bd --- /dev/null +++ b/sprites.cpp @@ -0,0 +1,43 @@ +#include "sprites.hpp" + +SDL_Surface* Sprite::sheet = nullptr; + +int Sprite::get(Piece piece, SDL_Surface* dest_surface) +{ + return get(piece.get_team(), piece.get_type(), piece.get_vis(), dest_surface); +} + +int Sprite::get(Team team, Type type, Visibility vis, SDL_Surface* dest_surface) +{ + if (nullptr == sheet) + { + load(); + } + + if (NO_TYPE == type || NO_TEAM == team || VIS_NONE == vis) + { + return -1; + } + + SDL_Rect dest_rect{0,0,45,45}; + SDL_Rect src_rect{type*45,team*45+vis*90,45,45}; + SDL_BlitSurface(sheet, &src_rect, dest_surface, &dest_rect); + + return 0; +} + +void Sprite::close() +{ + if (nullptr != sheet) + { + SDL_FreeSurface(sheet); + sheet = nullptr; + } +} + +void Sprite::load() +{ + close(); + sheet = SDL_LoadBMP("Chess_Pieces_Sprite.bmp"); + SDL_SetColorKey(sheet, SDL_TRUE, SDL_MapRGB(sheet->format, 0xFF, 0, 0xFF)); +} \ No newline at end of file diff --git a/sprites.hpp b/sprites.hpp new file mode 100644 index 0000000..09e79f6 --- /dev/null +++ b/sprites.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "piece.hpp" + +class Sprite +{ +public: + static int get(Piece piece, SDL_Surface* dest_surface); + static int get(Team team, Type type, Visibility vis, SDL_Surface* dest_surface); + + static void close(); +private: + static void load(); + + static SDL_Surface* sheet; + +}; \ No newline at end of file