From 7332afaa1eb2af75c75e5e4c555c0400c71ce883 Mon Sep 17 00:00:00 2001 From: Wojciech Matusiak <62173407+WojtekMs@users.noreply.github.com> Date: Thu, 14 Nov 2024 18:43:46 +0100 Subject: [PATCH 01/11] Move all units to a dedicated module Add hierarchical CMakeLists --- CMakeLists.txt | 23 ++------------ include/AttackInfoBox.hpp | 2 +- include/Board.hpp | 18 ++--------- include/CMakeLists.txt | 1 + include/GameController.hpp | 14 ++++----- include/GameView.hpp | 16 +++++----- include/Player.hpp | 14 ++++----- include/Tile.hpp | 24 +++++++++++++++ include/{ => unit}/BombUnit.hpp | 2 +- include/{ => unit}/FlagUnit.hpp | 2 +- include/{ => unit}/MinerUnit.hpp | 4 +-- include/{ => unit}/Movable.hpp | 6 ++-- include/{ => unit}/RegularUnit.hpp | 4 +-- include/{ => unit}/ScoutUnit.hpp | 4 +-- include/{ => unit}/SpyUnit.hpp | 4 +-- include/{ => unit}/Unit.hpp | 2 +- src/Board.cpp | 48 +++++++++++++++--------------- src/CMakeLists.txt | 19 ++++++++++++ src/GameController.cpp | 16 +++++----- src/GameView.cpp | 22 +++++++------- src/Movable.cpp | 5 ++-- src/Player.cpp | 18 +++++------ src/main.cpp | 2 +- 23 files changed, 143 insertions(+), 127 deletions(-) create mode 100644 include/CMakeLists.txt create mode 100644 include/Tile.hpp rename include/{ => unit}/BombUnit.hpp (87%) rename include/{ => unit}/FlagUnit.hpp (87%) rename include/{ => unit}/MinerUnit.hpp (91%) rename include/{ => unit}/Movable.hpp (75%) rename include/{ => unit}/RegularUnit.hpp (90%) rename include/{ => unit}/ScoutUnit.hpp (91%) rename include/{ => unit}/SpyUnit.hpp (91%) rename include/{ => unit}/Unit.hpp (95%) create mode 100644 src/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 62fc3cc..25d0881 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,29 +5,10 @@ project(stratego LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) -add_library( - stratego-src - src/AttackInfoBox.cpp - src/BigButton.cpp - src/Board.cpp - src/Box.cpp - src/Button.cpp - src/ButtonInterface.cpp - src/Game.cpp - src/GameController.cpp - src/GameView.cpp - src/MainMenu.cpp - src/Movable.cpp - src/Player.cpp) - -target_include_directories(stratego-src PUBLIC include) - -add_executable(${PROJECT_NAME} src/main.cpp) - find_package(SFML 2.6.1 REQUIRED system window graphics CONFIG) -target_link_libraries(stratego-src PUBLIC sfml-system sfml-window sfml-graphics) -target_link_libraries(${PROJECT_NAME} stratego-src) +add_subdirectory(src) +add_subdirectory(include) install(DIRECTORY font DESTINATION ${CMAKE_BINARY_DIR}) install(DIRECTORY images DESTINATION ${CMAKE_BINARY_DIR}) diff --git a/include/AttackInfoBox.hpp b/include/AttackInfoBox.hpp index c2725df..523292e 100644 --- a/include/AttackInfoBox.hpp +++ b/include/AttackInfoBox.hpp @@ -3,7 +3,7 @@ #include #include -#include "Unit.hpp" +#include "unit/Unit.hpp" class AttackInfoBox { diff --git a/include/Board.hpp b/include/Board.hpp index 3329656..1ddb1e9 100644 --- a/include/Board.hpp +++ b/include/Board.hpp @@ -1,4 +1,5 @@ #pragma once + #include #include #include @@ -6,6 +7,7 @@ #include #include "Array2D.h" +#include "Tile.hpp" enum class TURN { PLAYER_A, @@ -22,20 +24,6 @@ constexpr int MAX_UNIT_COUNT = 40; class Unit; class Board { -public: - class Tile { - public: - int x; - int y; - explicit Tile(int col = 0, int row = 0) { - x = col; - y = row; - }; - bool operator==(const Tile& rhs) const { return x == rhs.x && y == rhs.y; }; - void set_cords(const Board::Tile& rhs) { x = rhs.x; y = rhs.y; }; - void set_cords(int Ax, int Ay) { x = Ax; y = Ay; }; - }; - private: int height; int width; @@ -61,7 +49,7 @@ class Board { int get_height() const { return height; }; int get_width() const { return width; }; std::shared_ptr get_unit(int col, int row) const; - std::shared_ptr get_unit(const Board::Tile& chosen_unit) const; + std::shared_ptr get_unit(const Tile& chosen_unit) const; bool can_move(const Tile& from, const Tile& to) const; bool move_unit(const Tile& from, const Tile& to); void reverse_move_unit(const Tile& from, const Tile& to); diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt new file mode 100644 index 0000000..77bb3a7 --- /dev/null +++ b/include/CMakeLists.txt @@ -0,0 +1 @@ +target_include_directories(stratego-src PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) \ No newline at end of file diff --git a/include/GameController.hpp b/include/GameController.hpp index 39fc77a..54581b5 100644 --- a/include/GameController.hpp +++ b/include/GameController.hpp @@ -47,14 +47,14 @@ class GameController { bool game_finished; bool clock_started; - Board::Tile active_unit; - Board::Tile attacking_unit; - Board::Tile attacked_unit; + Tile active_unit; + Tile attacking_unit; + Tile attacked_unit; void TEST_SET_RANDOM_UNITS(); sf::Vector2f return_pixels(int col, int row) const; - Board::Tile return_tile(const sf::Vector2f& coords) const; - Board::Tile return_tile(int x, int y) const; + Tile return_tile(const sf::Vector2f& coords) const; + Tile return_tile(int x, int y) const; void drag_red_player(sf::Event& event); void drag_blue_player(sf::Event& event); @@ -67,7 +67,7 @@ class GameController { void move_active_unit(sf::Event& event); bool is_out_of_the_board(int x, int y); void set_buttons_pressed(); - void resolve_unit_conflict(const Board::Tile& attacked_unit); + void resolve_unit_conflict(const Tile& attacked_unit); public: GameController(Player& pA, Player& pB, GameView& g_view); @@ -88,7 +88,7 @@ class GameController { std::shared_ptr get_attacker() const { return attacker; }; std::shared_ptr get_attacked() const { return attacked; }; std::string get_victorious_player_name() const { return victorious_player_name; }; - const Board::Tile& get_active_unit() const { return active_unit; }; + const Tile& get_active_unit() const { return active_unit; }; int get_selected_init_unit_idx() const { return selected_unit_idx; }; const mouse_data& get_mouse_data() const { return m_data; }; Player* get_current_player() const { return current_player; }; diff --git a/include/GameView.hpp b/include/GameView.hpp index dbea522..c032817 100644 --- a/include/GameView.hpp +++ b/include/GameView.hpp @@ -80,13 +80,13 @@ class GameView { void set_highlight_sprites(); sf::Vector2f return_pixels(int col, int row) const; - Board::Tile return_tile(const sf::Vector2f& coords) const; - Board::Tile return_tile(int x, int y) const; + Tile return_tile(const sf::Vector2f& coords) const; + Tile return_tile(int x, int y) const; - bool check_if_viable(Board::Tile from, int to_x, int to_y); - void highlight_regular_moves(sf::RenderWindow& win, const Board::Tile& active_unit); - void highlight_scout_moves(sf::RenderWindow& win, const Board::Tile& active_unit); - bool highlight_tile(sf::RenderWindow& win, const Board::Tile& active_unit, int to_x, int to_y); + bool check_if_viable(Tile from, int to_x, int to_y); + void highlight_regular_moves(sf::RenderWindow& win, const Tile& active_unit); + void highlight_scout_moves(sf::RenderWindow& win, const Tile& active_unit); + bool highlight_tile(sf::RenderWindow& win, const Tile& active_unit, int to_x, int to_y); void draw_red_init_units(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data); void draw_blue_init_units(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data); @@ -115,10 +115,10 @@ class GameView { void draw_randomize_button(sf::RenderWindow& win); void draw_remove_button(sf::RenderWindow& win); void draw_end_turn_button(sf::RenderWindow& win); - void draw_possible_moves_for_active_unit(sf::RenderWindow& win, const Board::Tile& active_unit); + void draw_possible_moves_for_active_unit(sf::RenderWindow& win, const Tile& active_unit); void draw_info_box(sf::RenderWindow& win); void draw_attack_info_box(sf::RenderWindow& win, const std::shared_ptr& attacker, const std::shared_ptr& attacked); void draw_units(sf::RenderWindow& win); - void draw_unit_highlight(sf::RenderWindow& win, const Board::Tile& active_unit); + void draw_unit_highlight(sf::RenderWindow& win, const Tile& active_unit); void draw_end_game_screen(sf::RenderWindow& win, const std::string& victorious_name); }; \ No newline at end of file diff --git a/include/Player.hpp b/include/Player.hpp index 1524d07..9b51470 100644 --- a/include/Player.hpp +++ b/include/Player.hpp @@ -22,15 +22,15 @@ class Player std::string get_player_name() { return name; }; void set_unit(int col, int row, int choice); void remove_unit(int col, int row); - void remove_unit(Board::Tile chosen_unit); - void reverse_remove_unit(Board::Tile unit); - bool move_unit(Board::Tile from, Board::Tile to); - RESULT attack(Board::Tile attacker, Board::Tile attacked); - void reverse_move_unit(Board::Tile from, Board::Tile to); + void remove_unit(Tile chosen_unit); + void reverse_remove_unit(Tile unit); + bool move_unit(Tile from, Tile to); + RESULT attack(Tile attacker, Tile attacked); + void reverse_move_unit(Tile from, Tile to); void update_board(const Board& other_player_board); const Board& get_board() { return board; }; std::string get_tile_info(int col, int row) const; - std::string get_tile_info(Board::Tile tile) const; - bool can_move(Board::Tile from, Board::Tile to); + std::string get_tile_info(Tile tile) const; + bool can_move(Tile from, Tile to); void set_name(const std::string& n) { name = n; }; }; \ No newline at end of file diff --git a/include/Tile.hpp b/include/Tile.hpp new file mode 100644 index 0000000..f09f889 --- /dev/null +++ b/include/Tile.hpp @@ -0,0 +1,24 @@ +#pragma once + +class Tile +{ +public: + int x; + int y; + explicit Tile(int col = 0, int row = 0) + { + x = col; + y = row; + }; + bool operator==(const Tile &rhs) const { return x == rhs.x && y == rhs.y; }; + void set_cords(const Tile &rhs) + { + x = rhs.x; + y = rhs.y; + }; + void set_cords(int Ax, int Ay) + { + x = Ax; + y = Ay; + }; +}; \ No newline at end of file diff --git a/include/BombUnit.hpp b/include/unit/BombUnit.hpp similarity index 87% rename from include/BombUnit.hpp rename to include/unit/BombUnit.hpp index c3722bb..52e0e4a 100644 --- a/include/BombUnit.hpp +++ b/include/unit/BombUnit.hpp @@ -1,6 +1,6 @@ #pragma once -#include "Unit.hpp" +#include "unit/Unit.hpp" enum class TURN; class BombUnit : public Unit { diff --git a/include/FlagUnit.hpp b/include/unit/FlagUnit.hpp similarity index 87% rename from include/FlagUnit.hpp rename to include/unit/FlagUnit.hpp index 9bcaa37..86f9767 100644 --- a/include/FlagUnit.hpp +++ b/include/unit/FlagUnit.hpp @@ -1,6 +1,6 @@ #pragma once -#include "Unit.hpp" +#include "unit/Unit.hpp" enum class TURN; class FlagUnit : public Unit { diff --git a/include/MinerUnit.hpp b/include/unit/MinerUnit.hpp similarity index 91% rename from include/MinerUnit.hpp rename to include/unit/MinerUnit.hpp index 9d0b1e7..85da3eb 100644 --- a/include/MinerUnit.hpp +++ b/include/unit/MinerUnit.hpp @@ -1,7 +1,7 @@ #pragma once -#include "Movable.hpp" -#include "Unit.hpp" +#include "unit/Movable.hpp" +#include "unit/Unit.hpp" enum class TURN; class MinerUnit : public Unit, public Movable { diff --git a/include/Movable.hpp b/include/unit/Movable.hpp similarity index 75% rename from include/Movable.hpp rename to include/unit/Movable.hpp index 2755343..a3e8919 100644 --- a/include/Movable.hpp +++ b/include/unit/Movable.hpp @@ -1,12 +1,14 @@ #pragma once -#include "Board.hpp" +#include +#include "Tile.hpp" enum class RESULT { LOST, DRAW, WON, }; + class Unit; class Movable { @@ -23,7 +25,7 @@ class Movable { public: explicit Movable(Delegate* del); virtual bool can_move(int from_x, int from_y, int to_x, int to_y) const = 0; - virtual bool can_move(const Board::Tile& from, const Board::Tile& to) const { return can_move(from.x, from.y, to.x, to.y); }; + virtual bool can_move(const Tile& from, const Tile& to) const { return can_move(from.x, from.y, to.x, to.y); }; virtual RESULT attack(const std::shared_ptr& rhs) const = 0; virtual ~Movable(){}; diff --git a/include/RegularUnit.hpp b/include/unit/RegularUnit.hpp similarity index 90% rename from include/RegularUnit.hpp rename to include/unit/RegularUnit.hpp index 8f74a44..c322142 100644 --- a/include/RegularUnit.hpp +++ b/include/unit/RegularUnit.hpp @@ -1,7 +1,7 @@ #pragma once -#include "Movable.hpp" -#include "Unit.hpp" +#include "unit/Movable.hpp" +#include "unit/Unit.hpp" enum class TURN; enum class RESULT; diff --git a/include/ScoutUnit.hpp b/include/unit/ScoutUnit.hpp similarity index 91% rename from include/ScoutUnit.hpp rename to include/unit/ScoutUnit.hpp index 50b6df9..f9292ab 100644 --- a/include/ScoutUnit.hpp +++ b/include/unit/ScoutUnit.hpp @@ -1,7 +1,7 @@ #pragma once -#include "Unit.hpp" -#include "Movable.hpp" +#include "unit/Unit.hpp" +#include "unit/Movable.hpp" enum class TURN; class ScoutUnit : public Unit, public Movable { diff --git a/include/SpyUnit.hpp b/include/unit/SpyUnit.hpp similarity index 91% rename from include/SpyUnit.hpp rename to include/unit/SpyUnit.hpp index dc09935..c6d37df 100644 --- a/include/SpyUnit.hpp +++ b/include/unit/SpyUnit.hpp @@ -1,7 +1,7 @@ #pragma once -#include "Unit.hpp" -#include "Movable.hpp" +#include "unit/Unit.hpp" +#include "unit/Movable.hpp" enum class TURN; class SpyUnit : public Unit, public Movable { diff --git a/include/Unit.hpp b/include/unit/Unit.hpp similarity index 95% rename from include/Unit.hpp rename to include/unit/Unit.hpp index 7ef5428..e444ce3 100644 --- a/include/Unit.hpp +++ b/include/unit/Unit.hpp @@ -3,7 +3,7 @@ #include #include -#include "Movable.hpp" +#include "unit/Movable.hpp" class Board; enum class TURN; diff --git a/src/Board.cpp b/src/Board.cpp index 164dddc..da343f9 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -5,12 +5,12 @@ #include #include -#include "BombUnit.hpp" -#include "FlagUnit.hpp" -#include "MinerUnit.hpp" -#include "RegularUnit.hpp" -#include "ScoutUnit.hpp" -#include "SpyUnit.hpp" +#include "unit/BombUnit.hpp" +#include "unit/FlagUnit.hpp" +#include "unit/MinerUnit.hpp" +#include "unit/RegularUnit.hpp" +#include "unit/ScoutUnit.hpp" +#include "unit/SpyUnit.hpp" Board::Board() : height(12), @@ -86,7 +86,7 @@ std::string Board::get_tile_info(int col, int row, TURN player) const { if (out_of_range(col, row)) { return "#"; } - if (std::find_if(obstacles.begin(), obstacles.end(), [col, row](const Board::Tile& tile) { + if (std::find_if(obstacles.begin(), obstacles.end(), [col, row](const Tile& tile) { return tile.x == col && tile.y == row; }) != obstacles.end()) { return "O"; @@ -192,7 +192,7 @@ void Board::remove_unit(int col, int row) { } void Board::reverse_remove_unit(int col, int row) { - Board::Tile unit = point_reflection(col, row); + Tile unit = point_reflection(col, row); units[unit.y][unit.x].reset(); } @@ -226,32 +226,32 @@ void Board::reverse_move_unit(const Tile& from, const Tile& to) { // units[rev_from.y][rev_from.y].swap(units[rev_to.y][rev_to.x]); <---- this doesnt work! } -Board::Tile Board::point_reflection(int col, int row) { - Board::Tile distance; - Board::Tile distance_point; - Board::Tile reflection; - Board::Tile reflection_point; +Tile Board::point_reflection(int col, int row) { + Tile distance; + Tile distance_point; + Tile reflection; + Tile reflection_point; if (col >= 5 && row <= 5) { //first quarter of the board - distance_point = Board::Tile(4, 6); - reflection_point = Board::Tile(5, 5); + distance_point = Tile(4, 6); + reflection_point = Tile(5, 5); } if (col <= 4 && row <= 5) { //second quarter of the board - distance_point = Board::Tile(5, 6); - reflection_point = Board::Tile(4, 5); + distance_point = Tile(5, 6); + reflection_point = Tile(4, 5); } if (col <= 4 && row >= 6) { //third quarter of the board - distance_point = Board::Tile(5, 5); - reflection_point = Board::Tile(4, 6); + distance_point = Tile(5, 5); + reflection_point = Tile(4, 6); } if (col >= 5 && row >= 6) { //fourth quarter of the board - distance_point = Board::Tile(4, 5); - reflection_point = Board::Tile(5, 6); + distance_point = Tile(4, 5); + reflection_point = Tile(5, 6); } distance.x = col - distance_point.x; distance.y = row - distance_point.y; reflection.x = -distance.x; reflection.y = -distance.y; - return Board::Tile(reflection_point.x + reflection.x, reflection_point.y + reflection.y); + return Tile(reflection_point.x + reflection.x, reflection_point.y + reflection.y); } Board& Board::operator=(const Board& rhs) { @@ -272,7 +272,7 @@ Board& Board::operator=(const Board& rhs) { } void Board::update(const Board& other_board) { - Board::Tile other_unit; + Tile other_unit; *this = other_board; for (int row = 0; row < height / 2; ++row) { for (int col = 0; col < width; ++col) { @@ -289,7 +289,7 @@ std::shared_ptr Board::get_unit(int col, int row) const { return units[row][col]; } -std::shared_ptr Board::get_unit(const Board::Tile& chosen_unit) const { +std::shared_ptr Board::get_unit(const Tile& chosen_unit) const { if (out_of_range(chosen_unit.x, chosen_unit.y)) { return std::shared_ptr{}; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt new file mode 100644 index 0000000..b1533ff --- /dev/null +++ b/src/CMakeLists.txt @@ -0,0 +1,19 @@ +add_library( + stratego-src + AttackInfoBox.cpp + BigButton.cpp + Board.cpp + Box.cpp + Button.cpp + ButtonInterface.cpp + Game.cpp + GameController.cpp + GameView.cpp + MainMenu.cpp + Movable.cpp + Player.cpp) + +add_executable(${PROJECT_NAME} main.cpp) + +target_link_libraries(stratego-src PUBLIC sfml-system sfml-window sfml-graphics) +target_link_libraries(${PROJECT_NAME} stratego-src) diff --git a/src/GameController.cpp b/src/GameController.cpp index b669106..21c7a87 100644 --- a/src/GameController.cpp +++ b/src/GameController.cpp @@ -114,14 +114,14 @@ void GameController::change_init_turn(sf::Event& event) { void GameController::set_unit(sf::Event& event) { dragging = false; - Board::Tile tile(return_tile(event.mouseButton.x, event.mouseButton.y)); + Tile tile(return_tile(event.mouseButton.x, event.mouseButton.y)); if (current_player->get_units_count(selected_unit_idx) < current_player->get_board().get_max_unit_count(selected_unit_idx)) { current_player->set_unit(tile.x, tile.y, selected_unit_idx); } } void GameController::set_active_unit(sf::Event& event) { - Board::Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); + Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); if (!current_player->get_board().get_unit(chosen_tile)) { return; } @@ -147,7 +147,7 @@ void GameController::remove_unit() { } } -void GameController::resolve_unit_conflict(const Board::Tile& attacked_unit) { +void GameController::resolve_unit_conflict(const Tile& attacked_unit) { switch (current_player->attack(active_unit, attacked_unit)) { case RESULT::WON: current_player->remove_unit(attacked_unit); @@ -170,7 +170,7 @@ void GameController::resolve_unit_conflict(const Board::Tile& attacked_unit) { } void GameController::move_active_unit(sf::Event& event) { - Board::Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); + Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); if (!is_active_unit) { return; } @@ -285,13 +285,13 @@ sf::Vector2f GameController::return_pixels(int col, int row) const { return sf::Vector2f(TILE_SIZE * (col + 1), TILE_SIZE * (row + 1)); } -Board::Tile GameController::return_tile(const sf::Vector2f& coords) const { - return Board::Tile((coords.x - TILE_SIZE) / TILE_SIZE, (coords.y - TILE_SIZE) / TILE_SIZE); +Tile GameController::return_tile(const sf::Vector2f& coords) const { + return Tile((coords.x - TILE_SIZE) / TILE_SIZE, (coords.y - TILE_SIZE) / TILE_SIZE); } -Board::Tile GameController::return_tile(int x, int y) const { +Tile GameController::return_tile(int x, int y) const { if (x < 0 && y < 0) { - return Board::Tile{-1, -1}; + return Tile{-1, -1}; } return return_tile(sf::Vector2f(x, y)); } diff --git a/src/GameView.cpp b/src/GameView.cpp index 585f080..7c14f9c 100644 --- a/src/GameView.cpp +++ b/src/GameView.cpp @@ -355,7 +355,7 @@ void GameView::draw_units(sf::RenderWindow& win) { } } -void GameView::draw_unit_highlight(sf::RenderWindow& win, const Board::Tile& active_unit) { +void GameView::draw_unit_highlight(sf::RenderWindow& win, const Tile& active_unit) { yellow_highlight_sprite.setPosition(return_pixels(active_unit.x, active_unit.y)); win.draw(yellow_highlight_sprite); } @@ -384,7 +384,7 @@ void GameView::draw_sprite(sf::RenderWindow& win, int idx, int sprite_pos_x, int } } -void GameView::draw_possible_moves_for_active_unit(sf::RenderWindow& win, const Board::Tile& active_unit) { +void GameView::draw_possible_moves_for_active_unit(sf::RenderWindow& win, const Tile& active_unit) { if (!current_player->get_board().get_unit(active_unit.x, active_unit.y)) { return; } @@ -395,14 +395,14 @@ void GameView::draw_possible_moves_for_active_unit(sf::RenderWindow& win, const } } -void GameView::highlight_regular_moves(sf::RenderWindow& win, const Board::Tile& active_unit) { +void GameView::highlight_regular_moves(sf::RenderWindow& win, const Tile& active_unit) { highlight_tile(win, active_unit, active_unit.x - 1, active_unit.y); highlight_tile(win, active_unit, active_unit.x + 1, active_unit.y); highlight_tile(win, active_unit, active_unit.x, active_unit.y + 1); highlight_tile(win, active_unit, active_unit.x, active_unit.y - 1); } -void GameView::highlight_scout_moves(sf::RenderWindow& win, const Board::Tile& active_unit) { +void GameView::highlight_scout_moves(sf::RenderWindow& win, const Tile& active_unit) { for (int col = active_unit.x + 1; col < current_player->get_board().get_width(); ++col) { if (!highlight_tile(win, active_unit, col, active_unit.y)) { break; @@ -425,7 +425,7 @@ void GameView::highlight_scout_moves(sf::RenderWindow& win, const Board::Tile& a } } -bool GameView::highlight_tile(sf::RenderWindow& win, const Board::Tile& active_unit, int to_x, int to_y) { +bool GameView::highlight_tile(sf::RenderWindow& win, const Tile& active_unit, int to_x, int to_y) { if (check_if_viable(active_unit, to_x, to_y)) { if (current_player->get_tile_info(to_x, to_y) == "enemy") { red_highlight_sprite.setPosition(return_pixels(to_x, to_y)); @@ -440,8 +440,8 @@ bool GameView::highlight_tile(sf::RenderWindow& win, const Board::Tile& active_u return false; } -bool GameView::check_if_viable(Board::Tile from, int to_x, int to_y) { - return current_player->can_move(from, Board::Tile(to_x, to_y)); +bool GameView::check_if_viable(Tile from, int to_x, int to_y) { + return current_player->can_move(from, Tile(to_x, to_y)); } void GameView::draw_end_game_screen(sf::RenderWindow& win, const std::string& victorious_name) { @@ -461,13 +461,13 @@ sf::Vector2f GameView::return_pixels(int col, int row) const { return sf::Vector2f(TILE_SIZE * (col + 1), TILE_SIZE * (row + 1)); } -Board::Tile GameView::return_tile(const sf::Vector2f& coords) const { - return Board::Tile((coords.x - TILE_SIZE) / TILE_SIZE, (coords.y - TILE_SIZE) / TILE_SIZE); +Tile GameView::return_tile(const sf::Vector2f& coords) const { + return Tile((coords.x - TILE_SIZE) / TILE_SIZE, (coords.y - TILE_SIZE) / TILE_SIZE); } -Board::Tile GameView::return_tile(int x, int y) const { +Tile GameView::return_tile(int x, int y) const { if (x < 0 && y < 0) { - return Board::Tile{-1, -1}; + return Tile{-1, -1}; } return return_tile(sf::Vector2f(x, y)); } diff --git a/src/Movable.cpp b/src/Movable.cpp index 96a6f87..8d932db 100644 --- a/src/Movable.cpp +++ b/src/Movable.cpp @@ -1,6 +1,7 @@ -#include "Movable.hpp" +#include "unit/Movable.hpp" -#include "Unit.hpp" +#include "unit/Unit.hpp" +#include "Tile.hpp" Movable::Movable(Movable::Delegate* del) : delegate(del) {} diff --git a/src/Player.cpp b/src/Player.cpp index f134318..f2d61a2 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -1,5 +1,5 @@ -#include "Movable.hpp" -#include "Unit.hpp" +#include "unit/Movable.hpp" +#include "unit/Unit.hpp" #include "Player.hpp" #include @@ -40,19 +40,19 @@ void Player::remove_unit(int col, int row) { } } -void Player::remove_unit(Board::Tile chosen_unit) { +void Player::remove_unit(Tile chosen_unit) { remove_unit(chosen_unit.x, chosen_unit.y); } -void Player::reverse_remove_unit(Board::Tile unit) { +void Player::reverse_remove_unit(Tile unit) { board.reverse_remove_unit(unit.x, unit.y); } -bool Player::move_unit(Board::Tile from, Board::Tile to) { +bool Player::move_unit(Tile from, Tile to) { return board.move_unit(from, to); } -RESULT Player::attack(Board::Tile attacker, Board::Tile attacked) { +RESULT Player::attack(Tile attacker, Tile attacked) { const Movable* movable = dynamic_cast(board.get_unit(attacker).get()); if (!movable) { throw std::logic_error("Player.cpp:58 - unit you wish to attack with cannot move"); @@ -60,11 +60,11 @@ RESULT Player::attack(Board::Tile attacker, Board::Tile attacked) { return movable->attack(board.get_unit(attacked)); } -void Player::reverse_move_unit(Board::Tile from, Board::Tile to) { +void Player::reverse_move_unit(Tile from, Tile to) { board.reverse_move_unit(from, to); } -bool Player::can_move(Board::Tile from, Board::Tile to) { +bool Player::can_move(Tile from, Tile to) { if (board.get_tile_info(to.x, to.y, player) == "#") { return false; } @@ -91,7 +91,7 @@ std::string Player::get_tile_info(int col, int row) const { return board.get_tile_info(col, row, player); } -std::string Player::get_tile_info(Board::Tile tile) const { +std::string Player::get_tile_info(Tile tile) const { return board.get_tile_info(tile, player); } diff --git a/src/main.cpp b/src/main.cpp index 249cdaa..afa84fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -5,7 +5,7 @@ #include "Game.hpp" #include "MainMenu.hpp" #include "Player.hpp" -#include "RegularUnit.hpp" +#include "unit/RegularUnit.hpp" int main() { Board board; From e507f7ffd2181cc28acc40d26643d1c9d15471aa Mon Sep 17 00:00:00 2001 From: Wojciech Matusiak <62173407+WojtekMs@users.noreply.github.com> Date: Thu, 14 Nov 2024 18:54:37 +0100 Subject: [PATCH 02/11] Rename enums to CamelCase notation --- include/Board.hpp | 26 +++++++++++++------------- include/GameController.hpp | 4 ++-- include/GameView.hpp | 4 ++-- include/Player.hpp | 12 ++++++------ include/unit/BombUnit.hpp | 4 ++-- include/unit/FlagUnit.hpp | 4 ++-- include/unit/MinerUnit.hpp | 8 ++++---- include/unit/Movable.hpp | 12 ++++++------ include/unit/RegularUnit.hpp | 8 ++++---- include/unit/ScoutUnit.hpp | 6 +++--- include/unit/SpyUnit.hpp | 8 ++++---- include/unit/Unit.hpp | 23 +++++++++-------------- src/AttackInfoBox.cpp | 8 ++++---- src/Board.cpp | 18 +++++++++--------- src/GameController.cpp | 28 ++++++++++++++-------------- src/GameView.cpp | 8 ++++---- src/Movable.cpp | 10 +++++----- src/Player.cpp | 2 +- src/main.cpp | 4 ++-- 19 files changed, 96 insertions(+), 101 deletions(-) diff --git a/include/Board.hpp b/include/Board.hpp index 1ddb1e9..d7c41ab 100644 --- a/include/Board.hpp +++ b/include/Board.hpp @@ -9,15 +9,15 @@ #include "Array2D.h" #include "Tile.hpp" -enum class TURN { - PLAYER_A, - PLAYER_B +enum class Turn { + PlayerA, + PlayerB }; -enum class STATE { - UNINITIALIZED, - INITIALIZED, - FULL, +enum class State { + Uninitialized, + Initialized, + Full, }; constexpr int MAX_UNIT_COUNT = 40; @@ -27,7 +27,7 @@ class Board { private: int height; int width; - STATE current_state; + State current_state; int unit_count; Array2D> units; std::array obstacles; @@ -37,15 +37,15 @@ class Board { void set_obstacles(); Tile point_reflection(int col, int row); bool out_of_range(int col, int row) const; - void set_state(STATE state); + void set_state(State state); public: Board(); - bool set_unit(int col, int row, TURN player, int choice); + bool set_unit(int col, int row, Turn player, int choice); void remove_unit(int col, int row); void reverse_remove_unit(int col, int row); - std::string get_tile_info(int col, int row, TURN player) const; - std::string get_tile_info(const Tile& tile, TURN player) const; + std::string get_tile_info(int col, int row, Turn player) const; + std::string get_tile_info(const Tile& tile, Turn player) const; int get_height() const { return height; }; int get_width() const { return width; }; std::shared_ptr get_unit(int col, int row) const; @@ -55,7 +55,7 @@ class Board { void reverse_move_unit(const Tile& from, const Tile& to); void update(const Board& other_board); Board& operator=(const Board& rhs); - STATE get_state() const { return current_state; }; + State get_state() const { return current_state; }; int get_max_unit_count(const std::string& unit_type) const { return max_count_of_each_unit.at(unit_type); }; int get_max_unit_count(int idx) const; diff --git a/include/GameController.hpp b/include/GameController.hpp index 54581b5..f8fec7d 100644 --- a/include/GameController.hpp +++ b/include/GameController.hpp @@ -11,7 +11,7 @@ struct mouse_data { float mouse_object_offset_y; }; -enum class TURN; +enum class Turn; class Player; class GameView; @@ -27,7 +27,7 @@ class GameController { sf::Time total_time_unit_attacked; std::string victorious_player_name; - TURN current_player_turn; + Turn current_player_turn; mouse_data m_data; size_t TILE_SIZE; size_t selected_unit_idx; diff --git a/include/GameView.hpp b/include/GameView.hpp index c032817..da9a68e 100644 --- a/include/GameView.hpp +++ b/include/GameView.hpp @@ -11,14 +11,14 @@ #include "GameController.hpp" class Player; -enum class TURN; +enum class Turn; class GameView { Player& playerA; Player& playerB; Player* current_player; Player* other_player; - TURN current_player_turn; + Turn current_player_turn; const std::string board_textures_path; const std::string pieces_textures_path; diff --git a/include/Player.hpp b/include/Player.hpp index 9b51470..9686091 100644 --- a/include/Player.hpp +++ b/include/Player.hpp @@ -4,28 +4,28 @@ #include "Board.hpp" -enum class TURN; -enum class RESULT; +enum class Turn; +enum class Result; class Player { std::string name; - TURN player; + Turn player; std::unordered_map units_count; Board board; void set_units_count(); public: - Player(std::string n, TURN p): name(n), player(p), units_count(), board() { set_units_count(); }; + Player(std::string n, Turn p): name(n), player(p), units_count(), board() { set_units_count(); }; int get_units_count(const std::string& type) const { return units_count.at(type); }; int get_units_count(int idx); - TURN get_player_number() { return player; }; + Turn get_player_number() { return player; }; std::string get_player_name() { return name; }; void set_unit(int col, int row, int choice); void remove_unit(int col, int row); void remove_unit(Tile chosen_unit); void reverse_remove_unit(Tile unit); bool move_unit(Tile from, Tile to); - RESULT attack(Tile attacker, Tile attacked); + Result attack(Tile attacker, Tile attacked); void reverse_move_unit(Tile from, Tile to); void update_board(const Board& other_player_board); const Board& get_board() { return board; }; diff --git a/include/unit/BombUnit.hpp b/include/unit/BombUnit.hpp index 52e0e4a..c68cb71 100644 --- a/include/unit/BombUnit.hpp +++ b/include/unit/BombUnit.hpp @@ -2,10 +2,10 @@ #include "unit/Unit.hpp" -enum class TURN; +enum class Turn; class BombUnit : public Unit { public: - BombUnit(TURN player) + BombUnit(Turn player) : Unit(0, "bomb", player, false){}; virtual ~BombUnit(){}; }; diff --git a/include/unit/FlagUnit.hpp b/include/unit/FlagUnit.hpp index 86f9767..2f4d598 100644 --- a/include/unit/FlagUnit.hpp +++ b/include/unit/FlagUnit.hpp @@ -2,10 +2,10 @@ #include "unit/Unit.hpp" -enum class TURN; +enum class Turn; class FlagUnit : public Unit { public: - FlagUnit(TURN player) + FlagUnit(Turn player) : Unit(-1, "flag", player, false){}; virtual ~FlagUnit(){}; }; \ No newline at end of file diff --git a/include/unit/MinerUnit.hpp b/include/unit/MinerUnit.hpp index 85da3eb..eff6899 100644 --- a/include/unit/MinerUnit.hpp +++ b/include/unit/MinerUnit.hpp @@ -3,15 +3,15 @@ #include "unit/Movable.hpp" #include "unit/Unit.hpp" -enum class TURN; +enum class Turn; class MinerUnit : public Unit, public Movable { public: - MinerUnit(TURN player) + MinerUnit(Turn player) : Unit(3, "miner", player, true), Movable(this){}; virtual ~MinerUnit(){}; - virtual RESULT attack(const std::shared_ptr& rhs) const override { + virtual Result attack(const std::shared_ptr& rhs) const override { if (rhs->get_type() == "bomb") { - return RESULT::WON; + return Result::Won; } return Movable::attack(rhs); }; diff --git a/include/unit/Movable.hpp b/include/unit/Movable.hpp index a3e8919..0c51ed4 100644 --- a/include/unit/Movable.hpp +++ b/include/unit/Movable.hpp @@ -3,10 +3,10 @@ #include #include "Tile.hpp" -enum class RESULT { - LOST, - DRAW, - WON, +enum class Result { + Lost, + Draw, + Won, }; class Unit; @@ -16,7 +16,7 @@ class Movable { class Delegate { public: virtual int get_value() const = 0; - ~Delegate(){}; + virtual ~Delegate() = default; }; private: @@ -26,7 +26,7 @@ class Movable { explicit Movable(Delegate* del); virtual bool can_move(int from_x, int from_y, int to_x, int to_y) const = 0; virtual bool can_move(const Tile& from, const Tile& to) const { return can_move(from.x, from.y, to.x, to.y); }; - virtual RESULT attack(const std::shared_ptr& rhs) const = 0; + virtual Result attack(const std::shared_ptr& rhs) const = 0; virtual ~Movable(){}; }; diff --git a/include/unit/RegularUnit.hpp b/include/unit/RegularUnit.hpp index c322142..2e664e7 100644 --- a/include/unit/RegularUnit.hpp +++ b/include/unit/RegularUnit.hpp @@ -3,14 +3,14 @@ #include "unit/Movable.hpp" #include "unit/Unit.hpp" -enum class TURN; -enum class RESULT; +enum class Turn; +enum class Result; class RegularUnit : public Unit, public Movable { public: - RegularUnit(int v, TURN player) + RegularUnit(int v, Turn player) : Unit(v, "regular", player, true), Movable(this) {}; virtual ~RegularUnit() {}; - virtual RESULT attack(const std::shared_ptr& rhs) const override { + virtual Result attack(const std::shared_ptr& rhs) const override { return Movable::attack(rhs); }; bool can_move(int from_x, int from_y, int to_x, int to_y) const override { diff --git a/include/unit/ScoutUnit.hpp b/include/unit/ScoutUnit.hpp index f9292ab..3271649 100644 --- a/include/unit/ScoutUnit.hpp +++ b/include/unit/ScoutUnit.hpp @@ -3,13 +3,13 @@ #include "unit/Unit.hpp" #include "unit/Movable.hpp" -enum class TURN; +enum class Turn; class ScoutUnit : public Unit, public Movable { public: - ScoutUnit(TURN player) + ScoutUnit(Turn player) : Unit(2, "scout", player, true), Movable(this) {}; virtual ~ScoutUnit() {}; - virtual RESULT attack(const std::shared_ptr& rhs) const override { + virtual Result attack(const std::shared_ptr& rhs) const override { return Movable::attack(rhs); }; bool can_move(int from_x, int from_y, int to_x, int to_y) const override { diff --git a/include/unit/SpyUnit.hpp b/include/unit/SpyUnit.hpp index c6d37df..965d4a2 100644 --- a/include/unit/SpyUnit.hpp +++ b/include/unit/SpyUnit.hpp @@ -3,15 +3,15 @@ #include "unit/Unit.hpp" #include "unit/Movable.hpp" -enum class TURN; +enum class Turn; class SpyUnit : public Unit, public Movable { public: - SpyUnit(TURN player) + SpyUnit(Turn player) : Unit(-1, "spy", player, true), Movable(this) {}; virtual ~SpyUnit() {}; - RESULT attack(const std::shared_ptr& rhs) const override { + Result attack(const std::shared_ptr& rhs) const override { if (rhs->get_value() == 10) { - return RESULT::WON; + return Result::Won; } return Movable::attack(rhs); }; diff --git a/include/unit/Unit.hpp b/include/unit/Unit.hpp index e444ce3..d53873c 100644 --- a/include/unit/Unit.hpp +++ b/include/unit/Unit.hpp @@ -6,27 +6,22 @@ #include "unit/Movable.hpp" class Board; -enum class TURN; +enum class Turn; class Unit : public Movable::Delegate { - int value; - std::string type; - TURN owner; + int value{}; + std::string type{}; + Turn owner{}; public: - Unit(){}; - Unit(int v, const std::string& t, TURN player, bool m) + Unit() = default; + Unit(int v, const std::string& t, Turn player, bool m) : value(v), type(t), owner(player) { }; - inline Unit(const Unit& rhs); int get_value() const override { return value; }; std::string get_type() const { return type; }; - TURN get_owner() const { return owner; }; - virtual ~Unit(){}; + Turn get_owner() const { return owner; }; + virtual ~Unit() = default; }; -Unit::Unit(const Unit& rhs) { - value = rhs.value; - type = rhs.type; - owner = rhs.owner; -} + diff --git a/src/AttackInfoBox.cpp b/src/AttackInfoBox.cpp index d143771..b07ed80 100644 --- a/src/AttackInfoBox.cpp +++ b/src/AttackInfoBox.cpp @@ -93,7 +93,7 @@ void AttackInfoBox::set_attacking_unit(const std::shared_ptr& attacker) { if (!attacker) { return; } - if (attacker->get_owner() == TURN::PLAYER_A) { + if (attacker->get_owner() == Turn::PlayerA) { attacking_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(attacker)]; } else { attacking_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(attacker)]; @@ -107,7 +107,7 @@ void AttackInfoBox::set_attacked_unit(const std::shared_ptr& victim) { if (!victim) { return; } - if (victim->get_owner() == TURN::PLAYER_A) { + if (victim->get_owner() == Turn::PlayerA) { attacked_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(victim)]; } else { attacked_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(victim)]; @@ -142,10 +142,10 @@ std::shared_ptr AttackInfoBox::get_winner() { return std::shared_ptr{}; } if (const Movable* movable = dynamic_cast(attacker_ptr.get())) { - if (movable->attack(attacked_ptr) == RESULT::WON) { + if (movable->attack(attacked_ptr) == Result::Won) { return attacker_ptr; } - if (movable->attack(attacked_ptr) == RESULT::LOST) { + if (movable->attack(attacked_ptr) == Result::Lost) { return attacked_ptr; } } diff --git a/src/Board.cpp b/src/Board.cpp index da343f9..8232703 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -15,7 +15,7 @@ Board::Board() : height(12), width(10), - current_state(STATE::UNINITIALIZED), + current_state(State::Uninitialized), unit_count(0), units(width, height), max_count_of_each_unit({{"flag", 1}, @@ -82,7 +82,7 @@ bool Board::out_of_range(int col, int row) const { return false; } -std::string Board::get_tile_info(int col, int row, TURN player) const { +std::string Board::get_tile_info(int col, int row, Turn player) const { if (out_of_range(col, row)) { return "#"; } @@ -101,7 +101,7 @@ std::string Board::get_tile_info(int col, int row, TURN player) const { return " "; } -std::string Board::get_tile_info(const Tile& tile, TURN player) const { +std::string Board::get_tile_info(const Tile& tile, Turn player) const { return get_tile_info(tile.x, tile.y, player); } @@ -135,11 +135,11 @@ int Board::get_max_unit_count(int idx) const { return -1; } -void Board::set_state(STATE state) { +void Board::set_state(State state) { current_state = state; } -bool Board::set_unit(int col, int row, TURN player, int choice) { +bool Board::set_unit(int col, int row, Turn player, int choice) { if (col < 0 || col >= width) { return false; } @@ -152,7 +152,7 @@ bool Board::set_unit(int col, int row, TURN player, int choice) { if (get_tile_info(col, row, player) != " ") { return false; } - if (current_state == STATE::FULL) { + if (current_state == State::Full) { return false; } @@ -178,7 +178,7 @@ bool Board::set_unit(int col, int row, TURN player, int choice) { } unit_count++; if (unit_count == MAX_UNIT_COUNT) { - current_state = STATE::FULL; + current_state = State::Full; } return true; } @@ -186,8 +186,8 @@ bool Board::set_unit(int col, int row, TURN player, int choice) { void Board::remove_unit(int col, int row) { units[row][col].reset(); unit_count--; - if (current_state == STATE::FULL) { - current_state = STATE::UNINITIALIZED; + if (current_state == State::Full) { + current_state = State::Uninitialized; } } diff --git a/src/GameController.cpp b/src/GameController.cpp index 21c7a87..6104c34 100644 --- a/src/GameController.cpp +++ b/src/GameController.cpp @@ -14,7 +14,7 @@ GameController::GameController(Player& pA, Player& pB, GameView& g_view) attacker{}, attacked{}, victorious_player_name("none"), - current_player_turn(TURN::PLAYER_A), + current_player_turn(Turn::PlayerA), TILE_SIZE(64), selected_unit_idx(0), dragging(false), @@ -73,12 +73,12 @@ void GameController::drag_blue_player(sf::Event& event) { void GameController::change_player_turn() { if (unit_moved_this_round && turn_approved) { - if (current_player_turn == TURN::PLAYER_A) { - current_player_turn = TURN::PLAYER_B; + if (current_player_turn == Turn::PlayerA) { + current_player_turn = Turn::PlayerB; current_player = &playerB; other_player = &playerA; } else { - current_player_turn = TURN::PLAYER_A; + current_player_turn = Turn::PlayerA; current_player = &playerA; other_player = &playerB; } @@ -90,18 +90,18 @@ void GameController::change_player_turn() { void GameController::change_init_turn(sf::Event& event) { if (done_button_pressed) { - if (current_player_turn == TURN::PLAYER_A) { - if (playerA.get_board().get_state() == STATE::FULL) { + if (current_player_turn == Turn::PlayerA) { + if (playerA.get_board().get_state() == State::Full) { board_a_initialized = true; - current_player_turn = TURN::PLAYER_B; + current_player_turn = Turn::PlayerB; current_player = &playerB; other_player = &playerA; playerB.update_board(playerA.get_board()); } } else { - if (playerB.get_board().get_state() == STATE::FULL) { + if (playerB.get_board().get_state() == State::Full) { board_b_initialized = true; - current_player_turn = TURN::PLAYER_A; + current_player_turn = Turn::PlayerA; current_player = &playerA; other_player = &playerB; playerA.update_board(playerB.get_board()); @@ -149,18 +149,18 @@ void GameController::remove_unit() { void GameController::resolve_unit_conflict(const Tile& attacked_unit) { switch (current_player->attack(active_unit, attacked_unit)) { - case RESULT::WON: + case Result::Won: current_player->remove_unit(attacked_unit); other_player->reverse_remove_unit(attacked_unit); break; - case RESULT::DRAW: + case Result::Draw: current_player->remove_unit(active_unit); current_player->remove_unit(attacked_unit); other_player->reverse_remove_unit(active_unit); other_player->reverse_remove_unit(attacked_unit); active_unit.set_cords(-1, -1); break; - case RESULT::LOST: + case Result::Lost: current_player->remove_unit(active_unit); other_player->reverse_remove_unit(active_unit); active_unit.set_cords(-1, -1); @@ -209,7 +209,7 @@ void GameController::randomize_units() { current_player->remove_unit(col, row); } } - while (current_player->get_board().get_state() != STATE::FULL) { + while (current_player->get_board().get_state() != State::Full) { for (int row = 8; row < current_player->get_board().get_height(); ++row) { for (int col = 0; col < current_player->get_board().get_width(); ++col) { int idx = rand() % 12; @@ -249,7 +249,7 @@ void GameController::handle_events(sf::Event& event) { if (event.type == sf::Event::MouseButtonPressed) { set_buttons_pressed(); if (!(board_a_initialized && board_b_initialized)) { - if (current_player_turn == TURN::PLAYER_A) { + if (current_player_turn == Turn::PlayerA) { drag_red_player(event); } else { drag_blue_player(event); diff --git a/src/GameView.cpp b/src/GameView.cpp index 7c14f9c..8032d77 100644 --- a/src/GameView.cpp +++ b/src/GameView.cpp @@ -9,7 +9,7 @@ GameView::GameView(Player& pA, Player& pB) playerB(pB), current_player(&playerA), other_player(&playerB), - current_player_turn(TURN::PLAYER_A), + current_player_turn(Turn::PlayerA), board_textures_path("images/board/"), pieces_textures_path("images/pieces/"), TILE_SIZE(64), @@ -228,7 +228,7 @@ void GameView::draw_obstacles(sf::RenderWindow& win) { } void GameView::draw_units_for_init(sf::RenderWindow& win, bool is_dragging, int selected_units_idx, const mouse_data& m_data) { - if (current_player_turn == TURN::PLAYER_A) { + if (current_player_turn == Turn::PlayerA) { draw_red_init_units(win, is_dragging, selected_units_idx, m_data); } else { draw_blue_init_units(win, is_dragging, selected_units_idx, m_data); @@ -362,7 +362,7 @@ void GameView::draw_unit_highlight(sf::RenderWindow& win, const Tile& active_uni void GameView::draw_sprite(sf::RenderWindow& win, int idx, int sprite_pos_x, int sprite_pos_y) { if (idx == 12) { - if (current_player_turn == TURN::PLAYER_A) { + if (current_player_turn == Turn::PlayerA) { blue_back_sprite.setPosition(sprite_pos_x, sprite_pos_y); win.draw(blue_back_sprite); } else { @@ -370,7 +370,7 @@ void GameView::draw_sprite(sf::RenderWindow& win, int idx, int sprite_pos_x, int win.draw(red_back_sprite); } } else { - if (current_player_turn == TURN::PLAYER_A) { + if (current_player_turn == Turn::PlayerA) { sprite_initial_position = red_units_sprites[idx].getPosition(); red_units_sprites[idx].setPosition(sprite_pos_x, sprite_pos_y); win.draw(red_units_sprites[idx]); diff --git a/src/Movable.cpp b/src/Movable.cpp index 8d932db..13f5cf5 100644 --- a/src/Movable.cpp +++ b/src/Movable.cpp @@ -22,20 +22,20 @@ bool Movable::can_move(int from_x, int from_y, int to_x, int to_y) const return false; } -RESULT Movable::attack(const std::shared_ptr& rhs) const +Result Movable::attack(const std::shared_ptr& rhs) const { if (!rhs) { throw std::invalid_argument( "Movable.cpp:27 - unit you try to attack doesn't exist"); } if (rhs->get_type() == "bomb") { - return RESULT::LOST; + return Result::Lost; } if (delegate->get_value() > rhs->get_value()) { - return RESULT::WON; + return Result::Won; } if (delegate->get_value() == rhs->get_value()) { - return RESULT::DRAW; + return Result::Draw; } - return RESULT::LOST; + return Result::Lost; } diff --git a/src/Player.cpp b/src/Player.cpp index f2d61a2..6d6a2ca 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -52,7 +52,7 @@ bool Player::move_unit(Tile from, Tile to) { return board.move_unit(from, to); } -RESULT Player::attack(Tile attacker, Tile attacked) { +Result Player::attack(Tile attacker, Tile attacked) { const Movable* movable = dynamic_cast(board.get_unit(attacker).get()); if (!movable) { throw std::logic_error("Player.cpp:58 - unit you wish to attack with cannot move"); diff --git a/src/main.cpp b/src/main.cpp index afa84fc..e10991c 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,8 +9,8 @@ int main() { Board board; - Player playerA("Red-A", TURN::PLAYER_A); - Player playerB("Blue-B", TURN::PLAYER_B); + Player playerA("Red-A", Turn::PlayerA); + Player playerB("Blue-B", Turn::PlayerB); GameView game_view(playerA, playerB); GameController game_controller(playerA, playerB, game_view); Game game(game_view, game_controller); From 1123b095cf742db1be0fadba4a5f2dd490301fc3 Mon Sep 17 00:00:00 2001 From: Wojciech Matusiak <62173407+WojtekMs@users.noreply.github.com> Date: Fri, 3 Jan 2025 13:16:21 +0100 Subject: [PATCH 03/11] Basic Unit refactoring - Add a new module "unit" - Remove redundant Movable interface - Extract attack logic to a separate module that can be injected (Strategy pattern) - Extract Result enum to Attack module (maybe pull it out to a separate file?) TODO: - remove get_type from Unit --- include/Attack.h | 22 ++++++ include/Player.hpp | 4 +- include/unit/BombUnit.hpp | 5 +- include/unit/FlagUnit.hpp | 8 +-- include/unit/MinerUnit.hpp | 17 +---- include/unit/Movable.hpp | 32 --------- include/unit/RegularUnit.hpp | 14 +--- include/unit/ScoutUnit.hpp | 21 ++---- include/unit/SpyUnit.hpp | 16 +---- include/unit/Unit.hpp | 31 +++++---- src/Attack.cpp | 84 +++++++++++++++++++++++ src/AttackInfoBox.cpp | 129 +++++++++++++++++++++++------------ src/Board.cpp | 5 +- src/CMakeLists.txt | 11 ++- src/GameController.cpp | 6 +- src/Movable.cpp | 41 ----------- src/Player.cpp | 13 ++-- src/unit/BombUnit.cpp | 6 ++ src/unit/FlagUnit.cpp | 6 ++ src/unit/MinerUnit.cpp | 5 ++ src/unit/RegularUnit.cpp | 4 ++ src/unit/ScoutUnit.cpp | 17 +++++ src/unit/SpyUnit.cpp | 4 ++ src/unit/Unit.cpp | 35 ++++++++++ 24 files changed, 322 insertions(+), 214 deletions(-) create mode 100644 include/Attack.h delete mode 100644 include/unit/Movable.hpp create mode 100644 src/Attack.cpp delete mode 100644 src/Movable.cpp create mode 100644 src/unit/BombUnit.cpp create mode 100644 src/unit/FlagUnit.cpp create mode 100644 src/unit/MinerUnit.cpp create mode 100644 src/unit/RegularUnit.cpp create mode 100644 src/unit/ScoutUnit.cpp create mode 100644 src/unit/SpyUnit.cpp create mode 100644 src/unit/Unit.cpp diff --git a/include/Attack.h b/include/Attack.h new file mode 100644 index 0000000..8ef92c2 --- /dev/null +++ b/include/Attack.h @@ -0,0 +1,22 @@ +#pragma once + +#include "unit/Unit.hpp" +#include "unit/MinerUnit.hpp" +#include "unit/BombUnit.hpp" +#include "unit/SpyUnit.hpp" +#include "unit/RegularUnit.hpp" + +namespace attack +{ + enum class Result + { + Lost, + Draw, + Won, + }; + std::string toString(Result result); + + void validateUnits(const std::shared_ptr &lhs, const std::shared_ptr &rhs); + // This function is the actual strategy used by Board/Player + Result attack(const std::shared_ptr &lhs, const std::shared_ptr &rhs); +} diff --git a/include/Player.hpp b/include/Player.hpp index 9686091..37e7c9f 100644 --- a/include/Player.hpp +++ b/include/Player.hpp @@ -3,9 +3,9 @@ #include #include "Board.hpp" +#include "Attack.h" enum class Turn; -enum class Result; class Player { std::string name; @@ -25,7 +25,7 @@ class Player void remove_unit(Tile chosen_unit); void reverse_remove_unit(Tile unit); bool move_unit(Tile from, Tile to); - Result attack(Tile attacker, Tile attacked); + attack::Result attack(Tile attacker, Tile attacked); void reverse_move_unit(Tile from, Tile to); void update_board(const Board& other_player_board); const Board& get_board() { return board; }; diff --git a/include/unit/BombUnit.hpp b/include/unit/BombUnit.hpp index c68cb71..7372c88 100644 --- a/include/unit/BombUnit.hpp +++ b/include/unit/BombUnit.hpp @@ -5,7 +5,6 @@ enum class Turn; class BombUnit : public Unit { public: - BombUnit(Turn player) - : Unit(0, "bomb", player, false){}; - virtual ~BombUnit(){}; + BombUnit(Turn player); + bool can_move(const Tile &from, const Tile &to) const override; }; diff --git a/include/unit/FlagUnit.hpp b/include/unit/FlagUnit.hpp index 2f4d598..c94c0cc 100644 --- a/include/unit/FlagUnit.hpp +++ b/include/unit/FlagUnit.hpp @@ -3,9 +3,9 @@ #include "unit/Unit.hpp" enum class Turn; -class FlagUnit : public Unit { +class FlagUnit : public Unit +{ public: - FlagUnit(Turn player) - : Unit(-1, "flag", player, false){}; - virtual ~FlagUnit(){}; + FlagUnit(Turn player); + bool can_move(const Tile &from, const Tile &to) const override; }; \ No newline at end of file diff --git a/include/unit/MinerUnit.hpp b/include/unit/MinerUnit.hpp index eff6899..8203780 100644 --- a/include/unit/MinerUnit.hpp +++ b/include/unit/MinerUnit.hpp @@ -1,21 +1,10 @@ #pragma once -#include "unit/Movable.hpp" #include "unit/Unit.hpp" enum class Turn; -class MinerUnit : public Unit, public Movable { +class MinerUnit : public Unit +{ public: - MinerUnit(Turn player) - : Unit(3, "miner", player, true), Movable(this){}; - virtual ~MinerUnit(){}; - virtual Result attack(const std::shared_ptr& rhs) const override { - if (rhs->get_type() == "bomb") { - return Result::Won; - } - return Movable::attack(rhs); - }; - bool can_move(int from_x, int from_y, int to_x, int to_y) const override { - return Movable::can_move(from_x, from_y, to_x, to_y); - }; + explicit MinerUnit(Turn player); }; diff --git a/include/unit/Movable.hpp b/include/unit/Movable.hpp deleted file mode 100644 index 0c51ed4..0000000 --- a/include/unit/Movable.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#pragma once - -#include -#include "Tile.hpp" - -enum class Result { - Lost, - Draw, - Won, -}; - -class Unit; - -class Movable { -public: - class Delegate { - public: - virtual int get_value() const = 0; - virtual ~Delegate() = default; - }; - -private: - Delegate* delegate; - -public: - explicit Movable(Delegate* del); - virtual bool can_move(int from_x, int from_y, int to_x, int to_y) const = 0; - virtual bool can_move(const Tile& from, const Tile& to) const { return can_move(from.x, from.y, to.x, to.y); }; - virtual Result attack(const std::shared_ptr& rhs) const = 0; - - virtual ~Movable(){}; -}; diff --git a/include/unit/RegularUnit.hpp b/include/unit/RegularUnit.hpp index 2e664e7..b9a2fc8 100644 --- a/include/unit/RegularUnit.hpp +++ b/include/unit/RegularUnit.hpp @@ -1,19 +1,9 @@ #pragma once -#include "unit/Movable.hpp" #include "unit/Unit.hpp" enum class Turn; -enum class Result; -class RegularUnit : public Unit, public Movable { +class RegularUnit : public Unit { public: - RegularUnit(int v, Turn player) - : Unit(v, "regular", player, true), Movable(this) {}; - virtual ~RegularUnit() {}; - virtual Result attack(const std::shared_ptr& rhs) const override { - return Movable::attack(rhs); - }; - bool can_move(int from_x, int from_y, int to_x, int to_y) const override { - return Movable::can_move(from_x, from_y, to_x, to_y); - }; + explicit RegularUnit(int value, Turn player); }; diff --git a/include/unit/ScoutUnit.hpp b/include/unit/ScoutUnit.hpp index 3271649..c061e7e 100644 --- a/include/unit/ScoutUnit.hpp +++ b/include/unit/ScoutUnit.hpp @@ -1,24 +1,11 @@ #pragma once #include "unit/Unit.hpp" -#include "unit/Movable.hpp" enum class Turn; -class ScoutUnit : public Unit, public Movable { +class ScoutUnit : public Unit +{ public: - ScoutUnit(Turn player) - : Unit(2, "scout", player, true), Movable(this) {}; - virtual ~ScoutUnit() {}; - virtual Result attack(const std::shared_ptr& rhs) const override { - return Movable::attack(rhs); - }; - bool can_move(int from_x, int from_y, int to_x, int to_y) const override { - if (from_x == to_x) { - return true; - } - if (from_y == to_y) { - return true; - } - return false; - }; + ScoutUnit(Turn player); + bool can_move(const Tile &from, const Tile &to) const override; }; \ No newline at end of file diff --git a/include/unit/SpyUnit.hpp b/include/unit/SpyUnit.hpp index 965d4a2..840343f 100644 --- a/include/unit/SpyUnit.hpp +++ b/include/unit/SpyUnit.hpp @@ -1,21 +1,9 @@ #pragma once #include "unit/Unit.hpp" -#include "unit/Movable.hpp" enum class Turn; -class SpyUnit : public Unit, public Movable { +class SpyUnit : public Unit { public: - SpyUnit(Turn player) - : Unit(-1, "spy", player, true), Movable(this) {}; - virtual ~SpyUnit() {}; - Result attack(const std::shared_ptr& rhs) const override { - if (rhs->get_value() == 10) { - return Result::Won; - } - return Movable::attack(rhs); - }; - bool can_move(int from_x, int from_y, int to_x, int to_y) const override { - return Movable::can_move(from_x, from_y, to_x, to_y); - }; + SpyUnit(Turn player); }; diff --git a/include/unit/Unit.hpp b/include/unit/Unit.hpp index d53873c..3868d5a 100644 --- a/include/unit/Unit.hpp +++ b/include/unit/Unit.hpp @@ -2,26 +2,27 @@ #include #include +#include "Tile.hpp" -#include "unit/Movable.hpp" - -class Board; enum class Turn; -class Unit : public Movable::Delegate { - int value{}; - std::string type{}; - Turn owner{}; +class Unit +{ +private: + int value_{}; + std::string type_{}; + Turn owner_{}; public: + static constexpr int MARSHAL_VALUE{10}; Unit() = default; - Unit(int v, const std::string& t, Turn player, bool m) - : value(v), type(t), owner(player) { - }; - int get_value() const override { return value; }; - std::string get_type() const { return type; }; - Turn get_owner() const { return owner; }; - virtual ~Unit() = default; -}; + Unit(int value, std::string type, Turn player); + int get_value() const noexcept; + [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept; + Turn get_owner() const noexcept; + virtual bool can_move(const Tile &from, const Tile &to) const; + + virtual ~Unit() = default; +}; diff --git a/src/Attack.cpp b/src/Attack.cpp new file mode 100644 index 0000000..692b4cc --- /dev/null +++ b/src/Attack.cpp @@ -0,0 +1,84 @@ +#include "Attack.h" + +#include +#include +#include +#include + +namespace attack::details { +template +requires std::derived_from && std::derived_from +std::optional conditional_call(const std::shared_ptr& lhs, const std::shared_ptr& rhs, std::function fun) { + Lhs* lptr = dynamic_cast(lhs.get()); + Rhs* rptr = dynamic_cast(rhs.get()); + if (lptr && rptr) { + return fun(*lptr, *rptr); + } + return std::nullopt; +} + +Result basicAttack(Unit& lhs, Unit& rhs) { + if (lhs.get_value() > rhs.get_value()) + { + return Result::Won; + } + if (lhs.get_value() == rhs.get_value()) + { + return Result::Draw; + } + return Result::Lost; +} + +Result attackMinerBomb(MinerUnit& lhs, BombUnit& rhs) { + return Result::Won; +} + +Result attackUnitBomb(Unit& lhs, BombUnit& rhs) { + return Result::Lost; +} + +Result attackSpyRegular(SpyUnit& lhs, RegularUnit& rhs) { + if (rhs.get_value() == Unit::MARSHAL_VALUE) { + return Result::Won; + } + return Result::Lost; +} +} + +namespace attack +{ + std::string toString(Result result) { + switch(result) { + case Result::Lost: + return "Result::Lost"; + case Result::Won: + return "Result::Won"; + case Result::Draw: + return "Result::Draw"; + } + throw std::invalid_argument("Unknown enum Result value"); + } + + void validateUnits(const std::shared_ptr &lhs, const std::shared_ptr &rhs) + { + if (!lhs || !rhs) + { + throw std::invalid_argument("Attack.cpp attack: one of the units is nullptr"); + } + } + + Result attack(const std::shared_ptr &lhs, const std::shared_ptr &rhs) + { + validateUnits(lhs, rhs); + if(auto result = details::conditional_call(lhs, rhs, details::attackMinerBomb); result) { + return result.value(); + } + if(auto result = details::conditional_call(lhs, rhs, details::attackUnitBomb); result) { + return result.value(); + } + if(auto result = details::conditional_call(lhs, rhs, details::attackSpyRegular); result) { + return result.value(); + } + return details::basicAttack(*lhs, *rhs); + } +} \ No newline at end of file diff --git a/src/AttackInfoBox.cpp b/src/AttackInfoBox.cpp index b07ed80..b22bf54 100644 --- a/src/AttackInfoBox.cpp +++ b/src/AttackInfoBox.cpp @@ -3,8 +3,9 @@ #include #include "Board.hpp" +#include "Attack.h" -AttackInfoBox::AttackInfoBox(std::array& red_units_sprites, std::array& blue_units_sprites, sf::Sprite& winning_unit_highlight) +AttackInfoBox::AttackInfoBox(std::array &red_units_sprites, std::array &blue_units_sprites, sf::Sprite &winning_unit_highlight) : path_to_textures("images/board/"), attacking_unit_pos_x(-1), attacking_unit_pos_y(-1), @@ -14,11 +15,14 @@ AttackInfoBox::AttackInfoBox(std::array& red_units_sprites, std: attacked_unit{}, attacker_ptr{}, attacked_ptr{}, - winner_highlight(winning_unit_highlight) { - for (int i = 0; i < red_units_sprites_ptrs.size(); ++i) { + winner_highlight(winning_unit_highlight) +{ + for (int i = 0; i < red_units_sprites_ptrs.size(); ++i) + { red_units_sprites_ptrs[i] = &red_units_sprites[i]; } - for (int i = 0; i < blue_units_sprites_ptrs.size(); ++i) { + for (int i = 0; i < blue_units_sprites_ptrs.size(); ++i) + { blue_units_sprites_ptrs[i] = &blue_units_sprites[i]; } load_box_texture(); @@ -30,7 +34,8 @@ AttackInfoBox::AttackInfoBox(std::array& red_units_sprites, std: box_sprite.setTexture(box_texture); } -void AttackInfoBox::draw(sf::RenderWindow& win) { +void AttackInfoBox::draw(sf::RenderWindow &win) +{ update_attacked_unit_pos(); update_attacking_unit_pos(); update_box_text_pos(); @@ -42,46 +47,59 @@ void AttackInfoBox::draw(sf::RenderWindow& win) { draw_winner_highlight(win); } -void AttackInfoBox::load_box_texture() { - if (!box_texture.loadFromFile(path_to_textures + "attack_info_box.png")) { +void AttackInfoBox::load_box_texture() +{ + if (!box_texture.loadFromFile(path_to_textures + "attack_info_box.png")) + { std::cerr << "attack info box texture failed to load!\n"; abort(); } } -void AttackInfoBox::load_font() { - if (!box_font.loadFromFile("font/lunchds.ttf")) { +void AttackInfoBox::load_font() +{ + if (!box_font.loadFromFile("font/lunchds.ttf")) + { std::cerr << "failed to load attack info box font!\n"; abort(); } } -int AttackInfoBox::get_unit_sprite_idx(const std::shared_ptr& unit) { - if (!unit) { +int AttackInfoBox::get_unit_sprite_idx(const std::shared_ptr &unit) +{ + if (!unit) + { return -1; } - if (unit->get_type() == "regular") { + if (unit->get_type() == "regular") + { return unit->get_value() - 2; } - if (unit->get_type() == "scout") { + if (unit->get_type() == "scout") + { return 0; } - if (unit->get_type() == "miner") { + if (unit->get_type() == "miner") + { return 1; } - if (unit->get_type() == "bomb") { + if (unit->get_type() == "bomb") + { return 9; } - if (unit->get_type() == "flag") { + if (unit->get_type() == "flag") + { return 10; } - if (unit->get_type() == "spy") { + if (unit->get_type() == "spy") + { return 11; } return -1; } -void AttackInfoBox::set_position(int x, int y) { +void AttackInfoBox::set_position(int x, int y) +{ box_sprite.setPosition(x, y); update_attacking_unit_pos(); update_attacked_unit_pos(); @@ -89,13 +107,18 @@ void AttackInfoBox::set_position(int x, int y) { set_winner_highlight(); } -void AttackInfoBox::set_attacking_unit(const std::shared_ptr& attacker) { - if (!attacker) { +void AttackInfoBox::set_attacking_unit(const std::shared_ptr &attacker) +{ + if (!attacker) + { return; } - if (attacker->get_owner() == Turn::PlayerA) { + if (attacker->get_owner() == Turn::PlayerA) + { attacking_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(attacker)]; - } else { + } + else + { attacking_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(attacker)]; } attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); @@ -103,13 +126,18 @@ void AttackInfoBox::set_attacking_unit(const std::shared_ptr& attacker) { attacker_ptr = attacker; } -void AttackInfoBox::set_attacked_unit(const std::shared_ptr& victim) { - if (!victim) { +void AttackInfoBox::set_attacked_unit(const std::shared_ptr &victim) +{ + if (!victim) + { return; } - if (victim->get_owner() == Turn::PlayerA) { + if (victim->get_owner() == Turn::PlayerA) + { attacked_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(victim)]; - } else { + } + else + { attacked_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(victim)]; } attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); @@ -117,52 +145,65 @@ void AttackInfoBox::set_attacked_unit(const std::shared_ptr& victim) { attacked_ptr = victim; } -void AttackInfoBox::update_attacking_unit_pos() { +void AttackInfoBox::update_attacking_unit_pos() +{ attacking_unit_pos_x = box_sprite.getPosition().x + (get_width() / 4); attacking_unit_pos_y = box_sprite.getPosition().y + ((get_height() - attacking_unit.getGlobalBounds().height) / 2); attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); } -void AttackInfoBox::update_attacked_unit_pos() { +void AttackInfoBox::update_attacked_unit_pos() +{ attacked_unit_pos_x = box_sprite.getPosition().x + get_width() * 3 / 4 - attacked_unit.getGlobalBounds().width; attacked_unit_pos_y = attacking_unit_pos_y; attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); } -void AttackInfoBox::update_box_text_pos() { +void AttackInfoBox::update_box_text_pos() +{ box_text.setPosition(box_sprite.getPosition().x + ((get_width() - box_text.getLocalBounds().width) / 2), box_sprite.getPosition().y + (get_height() - box_text.getCharacterSize()) / 2); } -std::shared_ptr AttackInfoBox::get_winner() { - if (!attacked_ptr) { +std::shared_ptr AttackInfoBox::get_winner() +{ + if (!attacked_ptr) + { return std::shared_ptr{}; } - if (!attacker_ptr) { + if (!attacker_ptr) + { return std::shared_ptr{}; } - if (const Movable* movable = dynamic_cast(attacker_ptr.get())) { - if (movable->attack(attacked_ptr) == Result::Won) { - return attacker_ptr; - } - if (movable->attack(attacked_ptr) == Result::Lost) { - return attacked_ptr; - } + const auto result = attack::attack(attacker_ptr, attacked_ptr); + if (result == attack::Result::Won) + { + return attacker_ptr; + } + if (result == attack::Result::Lost) + { + return attacked_ptr; } + // FIXME: what happens with a Draw? Both are winners then return std::shared_ptr{}; } -void AttackInfoBox::set_winner_highlight() { - if (get_winner() == attacker_ptr) { +void AttackInfoBox::set_winner_highlight() +{ + if (get_winner() == attacker_ptr) + { winner_highlight.setPosition(attacking_unit.getPosition()); } - if (get_winner() == attacked_ptr) { + if (get_winner() == attacked_ptr) + { winner_highlight.setPosition(attacked_unit.getPosition()); } } -void AttackInfoBox::draw_winner_highlight(sf::RenderWindow& win) { - if (!get_winner()) { +void AttackInfoBox::draw_winner_highlight(sf::RenderWindow &win) +{ + if (!get_winner()) + { return; } winner_highlight.setScale(1.5, 1.5); diff --git a/src/Board.cpp b/src/Board.cpp index 8232703..eccbc5d 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -203,10 +203,7 @@ bool Board::can_move(const Tile& from, const Tile& to) const { if (!units[from.y][from.x]) { return false; } - if (const Movable* movable = dynamic_cast(units[from.y][from.x].get()) ) { - return movable->can_move(from, to); - } - return false; + return units[from.y][from.x]->can_move(from, to); } bool Board::move_unit(const Tile& from, const Tile& to) { diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index b1533ff..0b23c1c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,8 +10,15 @@ add_library( GameController.cpp GameView.cpp MainMenu.cpp - Movable.cpp - Player.cpp) + Player.cpp + Attack.cpp + unit/BombUnit.cpp + unit/FlagUnit.cpp + unit/MinerUnit.cpp + unit/RegularUnit.cpp + unit/ScoutUnit.cpp + unit/SpyUnit.cpp + unit/Unit.cpp) add_executable(${PROJECT_NAME} main.cpp) diff --git a/src/GameController.cpp b/src/GameController.cpp index 6104c34..9f5fe25 100644 --- a/src/GameController.cpp +++ b/src/GameController.cpp @@ -149,18 +149,18 @@ void GameController::remove_unit() { void GameController::resolve_unit_conflict(const Tile& attacked_unit) { switch (current_player->attack(active_unit, attacked_unit)) { - case Result::Won: + case attack::Result::Won: current_player->remove_unit(attacked_unit); other_player->reverse_remove_unit(attacked_unit); break; - case Result::Draw: + case attack::Result::Draw: current_player->remove_unit(active_unit); current_player->remove_unit(attacked_unit); other_player->reverse_remove_unit(active_unit); other_player->reverse_remove_unit(attacked_unit); active_unit.set_cords(-1, -1); break; - case Result::Lost: + case attack::Result::Lost: current_player->remove_unit(active_unit); other_player->reverse_remove_unit(active_unit); active_unit.set_cords(-1, -1); diff --git a/src/Movable.cpp b/src/Movable.cpp deleted file mode 100644 index 13f5cf5..0000000 --- a/src/Movable.cpp +++ /dev/null @@ -1,41 +0,0 @@ -#include "unit/Movable.hpp" - -#include "unit/Unit.hpp" -#include "Tile.hpp" - -Movable::Movable(Movable::Delegate* del) : delegate(del) {} - -bool Movable::can_move(int from_x, int from_y, int to_x, int to_y) const -{ - if (from_x + 1 == to_x && from_y == to_y) { - return true; - } - if (from_x - 1 == to_x && from_y == to_y) { - return true; - } - if (from_x == to_x && from_y + 1 == to_y) { - return true; - } - if (from_x == to_x && from_y - 1 == to_y) { - return true; - } - return false; -} - -Result Movable::attack(const std::shared_ptr& rhs) const -{ - if (!rhs) { - throw std::invalid_argument( - "Movable.cpp:27 - unit you try to attack doesn't exist"); - } - if (rhs->get_type() == "bomb") { - return Result::Lost; - } - if (delegate->get_value() > rhs->get_value()) { - return Result::Won; - } - if (delegate->get_value() == rhs->get_value()) { - return Result::Draw; - } - return Result::Lost; -} diff --git a/src/Player.cpp b/src/Player.cpp index 6d6a2ca..934081a 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -1,7 +1,7 @@ -#include "unit/Movable.hpp" #include "unit/Unit.hpp" #include "Player.hpp" #include +#include "Attack.h" void Player::set_units_count() { units_count.insert(std::pair{"regular4", 0}); @@ -52,12 +52,11 @@ bool Player::move_unit(Tile from, Tile to) { return board.move_unit(from, to); } -Result Player::attack(Tile attacker, Tile attacked) { - const Movable* movable = dynamic_cast(board.get_unit(attacker).get()); - if (!movable) { - throw std::logic_error("Player.cpp:58 - unit you wish to attack with cannot move"); - } - return movable->attack(board.get_unit(attacked)); +attack::Result Player::attack(Tile attacker, Tile attacked) { + // TODO: make the actual implementation a strategy (use dependency injection) + const auto& attacker_unit = board.get_unit(attacker); + const auto& attacked_unit = board.get_unit(attacked); + return attack::attack(attacker_unit, attacked_unit); } void Player::reverse_move_unit(Tile from, Tile to) { diff --git a/src/unit/BombUnit.cpp b/src/unit/BombUnit.cpp new file mode 100644 index 0000000..dee9e48 --- /dev/null +++ b/src/unit/BombUnit.cpp @@ -0,0 +1,6 @@ +#include "unit/BombUnit.hpp" + +BombUnit::BombUnit(Turn player) + : Unit(-1, "bomb", player) {}; + +bool BombUnit::can_move(const Tile &, const Tile &) const { return false; } diff --git a/src/unit/FlagUnit.cpp b/src/unit/FlagUnit.cpp new file mode 100644 index 0000000..1cfb1a5 --- /dev/null +++ b/src/unit/FlagUnit.cpp @@ -0,0 +1,6 @@ +#include "unit/FlagUnit.hpp" + +FlagUnit::FlagUnit(Turn player) + : Unit(-1, "flag", player) {}; + +bool FlagUnit::can_move(const Tile &, const Tile &) const { return false; } diff --git a/src/unit/MinerUnit.cpp b/src/unit/MinerUnit.cpp new file mode 100644 index 0000000..b176a9a --- /dev/null +++ b/src/unit/MinerUnit.cpp @@ -0,0 +1,5 @@ +#include "unit/MinerUnit.hpp" + +MinerUnit::MinerUnit(Turn player) + : Unit(3, "miner", player) {} + \ No newline at end of file diff --git a/src/unit/RegularUnit.cpp b/src/unit/RegularUnit.cpp new file mode 100644 index 0000000..86bbfa0 --- /dev/null +++ b/src/unit/RegularUnit.cpp @@ -0,0 +1,4 @@ +#include "unit/RegularUnit.hpp" + +RegularUnit::RegularUnit(int value, Turn player) + : Unit(value, "regular", player) {}; diff --git a/src/unit/ScoutUnit.cpp b/src/unit/ScoutUnit.cpp new file mode 100644 index 0000000..b87854b --- /dev/null +++ b/src/unit/ScoutUnit.cpp @@ -0,0 +1,17 @@ +#include "unit/ScoutUnit.hpp" + +ScoutUnit::ScoutUnit(Turn player) + : Unit(2, "scout", player) {}; + +bool ScoutUnit::can_move(const Tile &from, const Tile &to) const +{ + if (from.x == to.x) + { + return true; + } + if (from.y == to.y) + { + return true; + } + return false; +}; diff --git a/src/unit/SpyUnit.cpp b/src/unit/SpyUnit.cpp new file mode 100644 index 0000000..9f4a9f0 --- /dev/null +++ b/src/unit/SpyUnit.cpp @@ -0,0 +1,4 @@ +#include "unit/SpyUnit.hpp" + +SpyUnit::SpyUnit(Turn player) + : Unit(1, "spy", player) {}; diff --git a/src/unit/Unit.cpp b/src/unit/Unit.cpp new file mode 100644 index 0000000..7db3e09 --- /dev/null +++ b/src/unit/Unit.cpp @@ -0,0 +1,35 @@ +#include "unit/Unit.hpp" + +Unit::Unit(int value, std::string type, Turn player) + : value_{value}, + type_{std::move(type)}, + owner_{player} +{ +} + +int Unit::get_value() const noexcept { return value_; }; + +std::string Unit::get_type() const noexcept { return type_; }; + +Turn Unit::get_owner() const noexcept { return owner_; }; + +bool Unit::can_move(const Tile &from, const Tile &to) const +{ + if (from.x + 1 == to.x && from.y == to.y) + { + return true; + } + if (from.x - 1 == to.x && from.y == to.y) + { + return true; + } + if (from.x == to.x && from.y + 1 == to.y) + { + return true; + } + if (from.x == to.x && from.y - 1 == to.y) + { + return true; + } + return false; +} From 118864730432e217b29bafff00bb5ba99d5aa6fe Mon Sep 17 00:00:00 2001 From: Wojciech Matusiak <62173407+WojtekMs@users.noreply.github.com> Date: Sun, 23 Mar 2025 16:13:36 +0100 Subject: [PATCH 04/11] Refactor Unit: remove dynamic polymorphism - Replace Unit inheritance with std::variant - Replace virtual functions with std::visit - Store Units as std::optional instead of a std::shared_ptr - Remove usage of get_type() throughout the code base --- CMakeLists.txt | 1 + include/Attack.h | 22 ------- include/AttackInfoBox.hpp | 12 ++-- include/Board.hpp | 25 ++++---- include/GameController.hpp | 9 +-- include/GameView.hpp | 2 +- include/Player.hpp | 2 +- include/Tile.hpp | 4 +- include/Turn.hpp | 6 ++ include/unit/BombUnit.hpp | 19 ++++-- include/unit/FlagUnit.hpp | 19 ++++-- include/unit/MinerUnit.hpp | 17 +++++- include/unit/RegularUnit.hpp | 13 +++- include/unit/ScoutUnit.hpp | 19 ++++-- include/unit/SpyUnit.hpp | 19 +++++- include/unit/Unit.hpp | 33 +++------- include/unit/UnitConcepts.hpp | 17 ++++++ include/unit/UnitCounter.hpp | 38 ++++++++++++ include/unit/UnitModel.hpp | 22 +++++++ include/unit/visit/Attack.hpp | 62 +++++++++++++++++++ include/unit/visit/CanMove.hpp | 68 +++++++++++++++++++++ include/unit/visit/GetOwner.hpp | 12 ++++ include/unit/visit/GetTileInfo.hpp | 24 ++++++++ include/unit/visit/GetUnitSpriteId.hpp | 26 ++++++++ src/Attack.cpp | 84 -------------------------- src/AttackInfoBox.cpp | 78 ++++++++---------------- src/Board.cpp | 69 +++++++++++---------- src/CMakeLists.txt | 4 +- src/GameController.cpp | 5 +- src/GameView.cpp | 52 ++++++---------- src/Player.cpp | 24 +++----- src/unit/BombUnit.cpp | 4 +- src/unit/FlagUnit.cpp | 4 +- src/unit/MinerUnit.cpp | 2 +- src/unit/RegularUnit.cpp | 2 +- src/unit/ScoutUnit.cpp | 15 +---- src/unit/SpyUnit.cpp | 2 +- src/unit/Unit.cpp | 35 ----------- src/unit/UnitCounter.cpp | 48 +++++++++++++++ src/unit/UnitModel.cpp | 12 ++++ 40 files changed, 560 insertions(+), 371 deletions(-) delete mode 100644 include/Attack.h create mode 100644 include/Turn.hpp create mode 100644 include/unit/UnitConcepts.hpp create mode 100644 include/unit/UnitCounter.hpp create mode 100644 include/unit/UnitModel.hpp create mode 100644 include/unit/visit/Attack.hpp create mode 100644 include/unit/visit/CanMove.hpp create mode 100644 include/unit/visit/GetOwner.hpp create mode 100644 include/unit/visit/GetTileInfo.hpp create mode 100644 include/unit/visit/GetUnitSpriteId.hpp delete mode 100644 src/Attack.cpp create mode 100644 src/unit/UnitCounter.cpp create mode 100644 src/unit/UnitModel.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 25d0881..c366236 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,6 +4,7 @@ project(stratego LANGUAGES CXX) set(CMAKE_CXX_STANDARD 23) set(CMAKE_CXX_STANDARD_REQUIRED ON) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) find_package(SFML 2.6.1 REQUIRED system window graphics CONFIG) diff --git a/include/Attack.h b/include/Attack.h deleted file mode 100644 index 8ef92c2..0000000 --- a/include/Attack.h +++ /dev/null @@ -1,22 +0,0 @@ -#pragma once - -#include "unit/Unit.hpp" -#include "unit/MinerUnit.hpp" -#include "unit/BombUnit.hpp" -#include "unit/SpyUnit.hpp" -#include "unit/RegularUnit.hpp" - -namespace attack -{ - enum class Result - { - Lost, - Draw, - Won, - }; - std::string toString(Result result); - - void validateUnits(const std::shared_ptr &lhs, const std::shared_ptr &rhs); - // This function is the actual strategy used by Board/Player - Result attack(const std::shared_ptr &lhs, const std::shared_ptr &rhs); -} diff --git a/include/AttackInfoBox.hpp b/include/AttackInfoBox.hpp index 523292e..fe14831 100644 --- a/include/AttackInfoBox.hpp +++ b/include/AttackInfoBox.hpp @@ -21,24 +21,24 @@ class AttackInfoBox sf::Sprite attacking_unit; sf::Sprite attacked_unit; sf::Sprite& winner_highlight; - std::shared_ptr attacker_ptr; - std::shared_ptr attacked_ptr; + const Unit* attacker_ptr; + const Unit* attacked_ptr; - int get_unit_sprite_idx(const std::shared_ptr& unit); + int get_unit_sprite_idx(const Unit& unit); void load_box_texture(); void load_font(); void update_attacking_unit_pos(); void update_attacked_unit_pos(); void update_box_text_pos(); - std::shared_ptr get_winner(); + const Unit* get_winner(); void set_winner_highlight(); void draw_winner_highlight(sf::RenderWindow& win); public: AttackInfoBox(std::array& red_units_sprites, std::array& blue_units_sprites, sf::Sprite& winning_unit_highlight); void draw(sf::RenderWindow& win); void set_position(int x, int y); - void set_attacking_unit(const std::shared_ptr& attacker); - void set_attacked_unit(const std::shared_ptr& victim); + void set_attacking_unit(const std::optional& attacker); + void set_attacked_unit(const std::optional& victim); float get_height() const { return box_sprite.getGlobalBounds().height; }; float get_width() const { return box_sprite.getGlobalBounds().width; }; diff --git a/include/Board.hpp b/include/Board.hpp index d7c41ab..d6d6ec7 100644 --- a/include/Board.hpp +++ b/include/Board.hpp @@ -5,14 +5,12 @@ #include #include #include +#include #include "Array2D.h" #include "Tile.hpp" - -enum class Turn { - PlayerA, - PlayerB -}; +#include "unit/Unit.hpp" +#include "Turn.hpp" enum class State { Uninitialized, @@ -22,14 +20,13 @@ enum class State { constexpr int MAX_UNIT_COUNT = 40; -class Unit; class Board { private: - int height; - int width; - State current_state; - int unit_count; - Array2D> units; + int height{}; + int width{}; + State current_state{}; + int unit_count{}; + Array2D> units; std::array obstacles; const std::map max_count_of_each_unit; @@ -38,6 +35,8 @@ class Board { Tile point_reflection(int col, int row); bool out_of_range(int col, int row) const; void set_state(State state); + bool is_unit_set(Tile tile) const; + void unset_unit(Tile tile); public: Board(); @@ -48,8 +47,8 @@ class Board { std::string get_tile_info(const Tile& tile, Turn player) const; int get_height() const { return height; }; int get_width() const { return width; }; - std::shared_ptr get_unit(int col, int row) const; - std::shared_ptr get_unit(const Tile& chosen_unit) const; + const std::optional& get_unit(int col, int row) const; + const std::optional& get_unit(const Tile& chosen_unit) const; bool can_move(const Tile& from, const Tile& to) const; bool move_unit(const Tile& from, const Tile& to); void reverse_move_unit(const Tile& from, const Tile& to); diff --git a/include/GameController.hpp b/include/GameController.hpp index f8fec7d..56d58f2 100644 --- a/include/GameController.hpp +++ b/include/GameController.hpp @@ -3,6 +3,7 @@ #include #include "Board.hpp" +#include struct mouse_data { float mouse_x; @@ -21,8 +22,8 @@ class GameController { GameView& game_view; Player* current_player; Player* other_player; - std::shared_ptr attacker; - std::shared_ptr attacked; + std::optional attacker; + std::optional attacked; sf::Clock clock; sf::Time total_time_unit_attacked; @@ -85,8 +86,8 @@ class GameController { bool get_end_game_info_box_button_pressed() { return end_game_info_box_button_pressed; }; bool get_game_finished() { return game_finished; }; bool both_boards_set() const; - std::shared_ptr get_attacker() const { return attacker; }; - std::shared_ptr get_attacked() const { return attacked; }; + std::optional get_attacker() const { return attacker; }; + std::optional get_attacked() const { return attacked; }; std::string get_victorious_player_name() const { return victorious_player_name; }; const Tile& get_active_unit() const { return active_unit; }; int get_selected_init_unit_idx() const { return selected_unit_idx; }; diff --git a/include/GameView.hpp b/include/GameView.hpp index da9a68e..444434d 100644 --- a/include/GameView.hpp +++ b/include/GameView.hpp @@ -117,7 +117,7 @@ class GameView { void draw_end_turn_button(sf::RenderWindow& win); void draw_possible_moves_for_active_unit(sf::RenderWindow& win, const Tile& active_unit); void draw_info_box(sf::RenderWindow& win); - void draw_attack_info_box(sf::RenderWindow& win, const std::shared_ptr& attacker, const std::shared_ptr& attacked); + void draw_attack_info_box(sf::RenderWindow& win, const std::optional& attacker, const std::optional& attacked); void draw_units(sf::RenderWindow& win); void draw_unit_highlight(sf::RenderWindow& win, const Tile& active_unit); void draw_end_game_screen(sf::RenderWindow& win, const std::string& victorious_name); diff --git a/include/Player.hpp b/include/Player.hpp index 37e7c9f..0d1f87a 100644 --- a/include/Player.hpp +++ b/include/Player.hpp @@ -3,7 +3,7 @@ #include #include "Board.hpp" -#include "Attack.h" +#include "unit/visit/Attack.hpp" enum class Turn; class Player diff --git a/include/Tile.hpp b/include/Tile.hpp index f09f889..edb770a 100644 --- a/include/Tile.hpp +++ b/include/Tile.hpp @@ -3,8 +3,8 @@ class Tile { public: - int x; - int y; + int x{}; + int y{}; explicit Tile(int col = 0, int row = 0) { x = col; diff --git a/include/Turn.hpp b/include/Turn.hpp new file mode 100644 index 0000000..f4f47d1 --- /dev/null +++ b/include/Turn.hpp @@ -0,0 +1,6 @@ +#pragma once + +enum class Turn { + PlayerA, + PlayerB +}; \ No newline at end of file diff --git a/include/unit/BombUnit.hpp b/include/unit/BombUnit.hpp index 7372c88..99ac5be 100644 --- a/include/unit/BombUnit.hpp +++ b/include/unit/BombUnit.hpp @@ -1,10 +1,21 @@ #pragma once -#include "unit/Unit.hpp" +#include "unit/UnitModel.hpp" +#include "unit/UnitCounter.hpp" + +namespace details { +constexpr const int maxBombCount{6}; +} enum class Turn; -class BombUnit : public Unit { +class BombUnit { + UnitModel model_; + UnitCounter counter_; public: - BombUnit(Turn player); - bool can_move(const Tile &from, const Tile &to) const override; + explicit BombUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { return UnitCounter::get_count(); } + static int get_max_count() { return UnitCounter::get_max_count(); } }; diff --git a/include/unit/FlagUnit.hpp b/include/unit/FlagUnit.hpp index c94c0cc..b6bb9e7 100644 --- a/include/unit/FlagUnit.hpp +++ b/include/unit/FlagUnit.hpp @@ -1,11 +1,22 @@ #pragma once -#include "unit/Unit.hpp" +#include "unit/UnitModel.hpp" +#include "unit/UnitCounter.hpp" + +namespace details { +constexpr const int maxFlagCount{1}; +} enum class Turn; -class FlagUnit : public Unit +class FlagUnit { + UnitModel model_; + UnitCounter counter_; public: - FlagUnit(Turn player); - bool can_move(const Tile &from, const Tile &to) const override; + explicit FlagUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { return UnitCounter::get_count(); } + static int get_max_count() { return UnitCounter::get_max_count(); } }; \ No newline at end of file diff --git a/include/unit/MinerUnit.hpp b/include/unit/MinerUnit.hpp index 8203780..6471915 100644 --- a/include/unit/MinerUnit.hpp +++ b/include/unit/MinerUnit.hpp @@ -1,10 +1,23 @@ #pragma once -#include "unit/Unit.hpp" +#include "unit/UnitModel.hpp" +#include "unit/UnitCounter.hpp" + +namespace details { +constexpr const int maxMinerCount{4}; +} + enum class Turn; -class MinerUnit : public Unit +class MinerUnit { + UnitModel model_; + UnitCounter counter_; public: explicit MinerUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { return UnitCounter::get_count(); } + static int get_max_count() { return UnitCounter::get_max_count(); } }; diff --git a/include/unit/RegularUnit.hpp b/include/unit/RegularUnit.hpp index b9a2fc8..e8c3c01 100644 --- a/include/unit/RegularUnit.hpp +++ b/include/unit/RegularUnit.hpp @@ -1,9 +1,18 @@ #pragma once -#include "unit/Unit.hpp" +#include "unit/UnitModel.hpp" +#include "unit/UnitCounter.hpp" enum class Turn; -class RegularUnit : public Unit { + +class RegularUnit { + UnitModel model_; + RegularUnitCounter counter_; public: explicit RegularUnit(int value, Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count(int value) { RegularUnitCounter::get_count(value); } + static int get_max_count(int value) { RegularUnitCounter::get_max_count(value); } }; diff --git a/include/unit/ScoutUnit.hpp b/include/unit/ScoutUnit.hpp index c061e7e..b68d0f0 100644 --- a/include/unit/ScoutUnit.hpp +++ b/include/unit/ScoutUnit.hpp @@ -1,11 +1,22 @@ #pragma once -#include "unit/Unit.hpp" +#include "unit/UnitModel.hpp" +#include "unit/UnitCounter.hpp" + +namespace details { +constexpr const int maxScoutCount{8}; +} enum class Turn; -class ScoutUnit : public Unit +class ScoutUnit { + UnitModel model_; + UnitCounter counter_; public: - ScoutUnit(Turn player); - bool can_move(const Tile &from, const Tile &to) const override; + explicit ScoutUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { return UnitCounter::get_count(); } + static int get_max_count() { return UnitCounter::get_max_count(); } }; \ No newline at end of file diff --git a/include/unit/SpyUnit.hpp b/include/unit/SpyUnit.hpp index 840343f..124d87c 100644 --- a/include/unit/SpyUnit.hpp +++ b/include/unit/SpyUnit.hpp @@ -1,9 +1,22 @@ #pragma once -#include "unit/Unit.hpp" +#include "unit/UnitModel.hpp" +#include "unit/UnitCounter.hpp" + +namespace details { +constexpr const int maxSpyCount{1}; +} enum class Turn; -class SpyUnit : public Unit { + +class SpyUnit { + UnitModel model_; + UnitCounter counter_; public: - SpyUnit(Turn player); + explicit SpyUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { return UnitCounter::get_count(); } + static int get_max_count() { return UnitCounter::get_max_count(); } }; diff --git a/include/unit/Unit.hpp b/include/unit/Unit.hpp index 3868d5a..503c850 100644 --- a/include/unit/Unit.hpp +++ b/include/unit/Unit.hpp @@ -1,28 +1,15 @@ #pragma once -#include -#include -#include "Tile.hpp" +#include -enum class Turn; +#include "unit/BombUnit.hpp" +#include "unit/FlagUnit.hpp" +#include "unit/MinerUnit.hpp" +#include "unit/RegularUnit.hpp" +#include "unit/ScoutUnit.hpp" +#include "unit/SpyUnit.hpp" -class Unit -{ -private: - int value_{}; - std::string type_{}; - Turn owner_{}; +using Unit = std::variant; -public: - static constexpr int MARSHAL_VALUE{10}; - Unit() = default; - Unit(int value, std::string type, Turn player); - - int get_value() const noexcept; - [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept; - Turn get_owner() const noexcept; - - virtual bool can_move(const Tile &from, const Tile &to) const; - - virtual ~Unit() = default; -}; +template +struct overloads : Ts... { using Ts::operator()...; }; \ No newline at end of file diff --git a/include/unit/UnitConcepts.hpp b/include/unit/UnitConcepts.hpp new file mode 100644 index 0000000..cd12bbf --- /dev/null +++ b/include/unit/UnitConcepts.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include "Turn.hpp" + +#include + +namespace unit { +template +concept Attackable = requires(UnitType unit) { + {unit.get_value()} -> std::same_as; +}; + +template +concept Owned = requires(const UnitType& unit) { + {unit.get_owner()} -> std::same_as; +}; +} \ No newline at end of file diff --git a/include/unit/UnitCounter.hpp b/include/unit/UnitCounter.hpp new file mode 100644 index 0000000..da920ca --- /dev/null +++ b/include/unit/UnitCounter.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include + +template +class UnitCounter { +private: + static int count_; +public: + UnitCounter() { ++count_; } + UnitCounter(const UnitCounter&) : UnitCounter() {} + UnitCounter(UnitCounter&&) {} + UnitCounter& operator=(const UnitCounter& rhs) { if (this != &rhs) ++count_; return *this; }; + UnitCounter& operator=(UnitCounter&&) { return *this; } + ~UnitCounter() { --count_; } + + static int get_count() { return count_; } + static int get_max_count() { return MaxCount; } +}; + +template +int UnitCounter::count_ = 0; + +class RegularUnitCounter { +private: + static std::unordered_map count_; + int unit_value_{0}; +public: + explicit RegularUnitCounter(const int unit_value); + RegularUnitCounter(const RegularUnitCounter&); + RegularUnitCounter(RegularUnitCounter&&); + RegularUnitCounter& operator=(const RegularUnitCounter&); + RegularUnitCounter& operator=(RegularUnitCounter&&); + ~RegularUnitCounter(); + + static int get_count(int unit_value); + static int get_max_count(int unit_value); +}; \ No newline at end of file diff --git a/include/unit/UnitModel.hpp b/include/unit/UnitModel.hpp new file mode 100644 index 0000000..35d708d --- /dev/null +++ b/include/unit/UnitModel.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include "Tile.hpp" + +enum class Turn; + +class UnitModel +{ +private: + int value_{}; + [[deprecated]] std::string type_{}; + Turn owner_{}; + +public: + static constexpr int MARSHAL_VALUE{10}; + UnitModel(int value, std::string type, Turn player); + int get_value() const noexcept; + [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept; + Turn get_owner() const noexcept; +}; diff --git a/include/unit/visit/Attack.hpp b/include/unit/visit/Attack.hpp new file mode 100644 index 0000000..3c91110 --- /dev/null +++ b/include/unit/visit/Attack.hpp @@ -0,0 +1,62 @@ +#pragma once + +#include +#include +#include + +#include "Tile.hpp" +#include "unit/Unit.hpp" +#include "unit/UnitConcepts.hpp" + +namespace attack { +enum class Result +{ + Lost, + Draw, + Won, +}; + +class InvalidUnitError : public std::exception { + public: + const char* what() const noexcept override { return "Invalid unit attacked or was being attacked\n"; } +}; + +} // namespace attack + + +class Attack { + template + attack::Result regular_attack(const T& lhs, const U& rhs) { + if (lhs.get_value() > rhs.get_value()) + { + return attack::Result::Won; + } + if (lhs.get_value() == rhs.get_value()) + { + return attack::Result::Draw; + } + return attack::Result::Lost; + } +public: + attack::Result operator()(const SpyUnit&, const RegularUnit& rhs) { + if (rhs.get_value() == UnitModel::MARSHAL_VALUE) { + return attack::Result::Won; + } + return attack::Result::Lost; + } + attack::Result operator()(const MinerUnit&, const BombUnit&) { + return attack::Result::Won; + } + template + attack::Result operator()(const T&, const BombUnit&) { + return attack::Result::Lost; + } + template + attack::Result operator()(const T& lhs, const U& rhs) { + return regular_attack(lhs, rhs); + } + template + attack::Result operator()(const T& lhs, const U& rhs) { + throw attack::InvalidUnitError(); + } +}; \ No newline at end of file diff --git a/include/unit/visit/CanMove.hpp b/include/unit/visit/CanMove.hpp new file mode 100644 index 0000000..1b9a281 --- /dev/null +++ b/include/unit/visit/CanMove.hpp @@ -0,0 +1,68 @@ +#pragma once + +#include +#include +#include + +#include "Tile.hpp" +#include "unit/Unit.hpp" + +class CanMove { +private: + Tile from_{}; + Tile to_{}; + + bool regularMove() const { + if (from_.x + 1 == to_.x && from_.y == to_.y) + { + return true; + } + if (from_.x - 1 == to_.x && from_.y == to_.y) + { + return true; + } + if (from_.x == to_.x && from_.y + 1 == to_.y) + { + return true; + } + if (from_.x == to_.x && from_.y - 1 == to_.y) + { + return true; + } + return false; + } + + bool scoutMove() const { + if (from_.x == to_.x) + { + return true; + } + if (from_.y == to_.y) + { + return true; + } + return false; + } + +public: + CanMove(Tile from, Tile to) : from_(from), to_(to) {} + + bool operator()(const ScoutUnit&) { + return scoutMove(); + } + bool operator()(const MinerUnit&) { + return regularMove(); + } + bool operator()(const RegularUnit&) { + return regularMove(); + } + bool operator()(const SpyUnit&) { + return regularMove(); + } + bool operator()(const FlagUnit&) { + return false; + } + bool operator()(const BombUnit&) { + return false; + } +}; \ No newline at end of file diff --git a/include/unit/visit/GetOwner.hpp b/include/unit/visit/GetOwner.hpp new file mode 100644 index 0000000..85e2916 --- /dev/null +++ b/include/unit/visit/GetOwner.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include "unit/UnitConcepts.hpp" + +enum class Turn; +class GetOwner { +public: + template + Turn operator()(const T& unit) { + return unit.get_owner(); + } +}; \ No newline at end of file diff --git a/include/unit/visit/GetTileInfo.hpp b/include/unit/visit/GetTileInfo.hpp new file mode 100644 index 0000000..c322dfc --- /dev/null +++ b/include/unit/visit/GetTileInfo.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include + +#include "Turn.hpp" +#include "unit/UnitConcepts.hpp" + +class GetTileInfo { +private: + Turn player_; + +public: + explicit GetTileInfo(Turn player) : player_(player) {} + + template + std::string operator()(const UnitType& unit) { + if (unit.get_owner() != player_) { + return "enemy"; + } else { + return unit.get_type(); + } + } +}; \ No newline at end of file diff --git a/include/unit/visit/GetUnitSpriteId.hpp b/include/unit/visit/GetUnitSpriteId.hpp new file mode 100644 index 0000000..407f8b0 --- /dev/null +++ b/include/unit/visit/GetUnitSpriteId.hpp @@ -0,0 +1,26 @@ +#pragma once + + +#include "unit/Unit.hpp" + +class GetUnitSpriteId { +public: + int operator()(const RegularUnit& unit) { + return unit.get_value() - 2; + } + int operator()(const ScoutUnit&) { + return 0; + } + int operator()(const MinerUnit&) { + return 1; + } + int operator()(const BombUnit&) { + return 9; + } + int operator()(const FlagUnit&) { + return 10; + } + int operator()(const SpyUnit&) { + return 11; + } +}; \ No newline at end of file diff --git a/src/Attack.cpp b/src/Attack.cpp deleted file mode 100644 index 692b4cc..0000000 --- a/src/Attack.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "Attack.h" - -#include -#include -#include -#include - -namespace attack::details { -template -requires std::derived_from && std::derived_from -std::optional conditional_call(const std::shared_ptr& lhs, const std::shared_ptr& rhs, std::function fun) { - Lhs* lptr = dynamic_cast(lhs.get()); - Rhs* rptr = dynamic_cast(rhs.get()); - if (lptr && rptr) { - return fun(*lptr, *rptr); - } - return std::nullopt; -} - -Result basicAttack(Unit& lhs, Unit& rhs) { - if (lhs.get_value() > rhs.get_value()) - { - return Result::Won; - } - if (lhs.get_value() == rhs.get_value()) - { - return Result::Draw; - } - return Result::Lost; -} - -Result attackMinerBomb(MinerUnit& lhs, BombUnit& rhs) { - return Result::Won; -} - -Result attackUnitBomb(Unit& lhs, BombUnit& rhs) { - return Result::Lost; -} - -Result attackSpyRegular(SpyUnit& lhs, RegularUnit& rhs) { - if (rhs.get_value() == Unit::MARSHAL_VALUE) { - return Result::Won; - } - return Result::Lost; -} -} - -namespace attack -{ - std::string toString(Result result) { - switch(result) { - case Result::Lost: - return "Result::Lost"; - case Result::Won: - return "Result::Won"; - case Result::Draw: - return "Result::Draw"; - } - throw std::invalid_argument("Unknown enum Result value"); - } - - void validateUnits(const std::shared_ptr &lhs, const std::shared_ptr &rhs) - { - if (!lhs || !rhs) - { - throw std::invalid_argument("Attack.cpp attack: one of the units is nullptr"); - } - } - - Result attack(const std::shared_ptr &lhs, const std::shared_ptr &rhs) - { - validateUnits(lhs, rhs); - if(auto result = details::conditional_call(lhs, rhs, details::attackMinerBomb); result) { - return result.value(); - } - if(auto result = details::conditional_call(lhs, rhs, details::attackUnitBomb); result) { - return result.value(); - } - if(auto result = details::conditional_call(lhs, rhs, details::attackSpyRegular); result) { - return result.value(); - } - return details::basicAttack(*lhs, *rhs); - } -} \ No newline at end of file diff --git a/src/AttackInfoBox.cpp b/src/AttackInfoBox.cpp index b22bf54..57a1dcf 100644 --- a/src/AttackInfoBox.cpp +++ b/src/AttackInfoBox.cpp @@ -3,7 +3,9 @@ #include #include "Board.hpp" -#include "Attack.h" +#include "unit/visit/Attack.hpp" +#include "unit/visit/GetOwner.hpp" +#include "unit/visit/GetUnitSpriteId.hpp" AttackInfoBox::AttackInfoBox(std::array &red_units_sprites, std::array &blue_units_sprites, sf::Sprite &winning_unit_highlight) : path_to_textures("images/board/"), @@ -65,37 +67,9 @@ void AttackInfoBox::load_font() } } -int AttackInfoBox::get_unit_sprite_idx(const std::shared_ptr &unit) +int AttackInfoBox::get_unit_sprite_idx(const Unit &unit) { - if (!unit) - { - return -1; - } - if (unit->get_type() == "regular") - { - return unit->get_value() - 2; - } - if (unit->get_type() == "scout") - { - return 0; - } - if (unit->get_type() == "miner") - { - return 1; - } - if (unit->get_type() == "bomb") - { - return 9; - } - if (unit->get_type() == "flag") - { - return 10; - } - if (unit->get_type() == "spy") - { - return 11; - } - return -1; + return std::visit(GetUnitSpriteId{}, unit); } void AttackInfoBox::set_position(int x, int y) @@ -107,42 +81,42 @@ void AttackInfoBox::set_position(int x, int y) set_winner_highlight(); } -void AttackInfoBox::set_attacking_unit(const std::shared_ptr &attacker) +void AttackInfoBox::set_attacking_unit(const std::optional &attacker) { - if (!attacker) - { + if (!attacker) { return; } - if (attacker->get_owner() == Turn::PlayerA) + const auto attackerUnit = attacker.value(); + if (std::visit(GetOwner{}, attackerUnit) == Turn::PlayerA) { - attacking_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(attacker)]; + attacking_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(attackerUnit)]; } else { - attacking_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(attacker)]; + attacking_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(attackerUnit)]; } attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); attacking_unit.scale(1.5, 1.5); - attacker_ptr = attacker; + attacker_ptr = &attackerUnit; } -void AttackInfoBox::set_attacked_unit(const std::shared_ptr &victim) +void AttackInfoBox::set_attacked_unit(const std::optional &victim) { - if (!victim) - { + if (!victim) { return; } - if (victim->get_owner() == Turn::PlayerA) + const auto victimUnit = victim.value(); + if (std::visit(GetOwner{}, victimUnit) == Turn::PlayerA) { - attacked_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(victim)]; + attacked_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(victimUnit)]; } else { - attacked_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(victim)]; + attacked_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(victimUnit)]; } attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); attacked_unit.scale(1.5, 1.5); - attacked_ptr = victim; + attacked_ptr = &victimUnit; } void AttackInfoBox::update_attacking_unit_pos() @@ -165,17 +139,13 @@ void AttackInfoBox::update_box_text_pos() box_sprite.getPosition().y + (get_height() - box_text.getCharacterSize()) / 2); } -std::shared_ptr AttackInfoBox::get_winner() +const Unit* AttackInfoBox::get_winner() { - if (!attacked_ptr) - { - return std::shared_ptr{}; - } - if (!attacker_ptr) + if (!attacked_ptr || !attacker_ptr) { - return std::shared_ptr{}; + return {}; } - const auto result = attack::attack(attacker_ptr, attacked_ptr); + const auto result = std::visit(Attack{}, *attacker_ptr, *attacked_ptr); if (result == attack::Result::Won) { return attacker_ptr; @@ -185,7 +155,7 @@ std::shared_ptr AttackInfoBox::get_winner() return attacked_ptr; } // FIXME: what happens with a Draw? Both are winners then - return std::shared_ptr{}; + return {}; } void AttackInfoBox::set_winner_highlight() diff --git a/src/Board.cpp b/src/Board.cpp index eccbc5d..7d916de 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -11,6 +11,8 @@ #include "unit/RegularUnit.hpp" #include "unit/ScoutUnit.hpp" #include "unit/SpyUnit.hpp" +#include "unit/visit/GetTileInfo.hpp" +#include "unit/visit/CanMove.hpp" Board::Board() : height(12), @@ -37,8 +39,7 @@ Board::Board() void Board::set_default_units() { for (int row = 0; row < height; ++row) { for (int col = 0; col < width; ++col) { - units[row][col].reset(); - units[row][col] = nullptr; + unset_unit(Tile{col, row}); } } } @@ -72,6 +73,14 @@ void Board::set_obstacles() { } } +bool Board::is_unit_set(Tile tile) const { + return units[tile.y][tile.x].has_value(); +} + +void Board::unset_unit(Tile tile) { + units[tile.y][tile.x] = std::nullopt; +} + bool Board::out_of_range(int col, int row) const { if (col < 0 || col >= width) { return true; @@ -86,19 +95,15 @@ std::string Board::get_tile_info(int col, int row, Turn player) const { if (out_of_range(col, row)) { return "#"; } + if (!is_unit_set(Tile{col, row})) { + return " "; + } if (std::find_if(obstacles.begin(), obstacles.end(), [col, row](const Tile& tile) { return tile.x == col && tile.y == row; }) != obstacles.end()) { return "O"; } - if (units[row][col]) { - if (units[row][col]->get_owner() != player) { - return "enemy"; - } else { - return units[row][col]->get_type(); - } - } - return " "; + return std::visit(GetTileInfo{player}, units[row][col].value()); } std::string Board::get_tile_info(const Tile& tile, Turn player) const { @@ -158,23 +163,23 @@ bool Board::set_unit(int col, int row, Turn player, int choice) { switch (choice + 2) { case 2: { - units[row][col] = std::make_shared(player); + units[row][col] = ScoutUnit(player); } break; case 3: { - units[row][col] = std::make_shared(player); + units[row][col] = MinerUnit(player); } break; case 11: { - units[row][col] = std::make_shared(player); + units[row][col] = BombUnit(player); } break; case 12: { - units[row][col] = std::make_shared(player); + units[row][col] = FlagUnit(player); } break; case 13: { - units[row][col] = std::make_shared(player); + units[row][col] = SpyUnit(player); } } if (choice + 2 > 3 && choice + 2 < 11) { - units[row][col] = std::make_shared(choice + 2, player); + units[row][col] = RegularUnit(choice + 2, player); } unit_count++; if (unit_count == MAX_UNIT_COUNT) { @@ -184,7 +189,7 @@ bool Board::set_unit(int col, int row, Turn player, int choice) { } void Board::remove_unit(int col, int row) { - units[row][col].reset(); + unset_unit(Tile{col, row}); unit_count--; if (current_state == State::Full) { current_state = State::Uninitialized; @@ -193,34 +198,33 @@ void Board::remove_unit(int col, int row) { void Board::reverse_remove_unit(int col, int row) { Tile unit = point_reflection(col, row); - units[unit.y][unit.x].reset(); + unset_unit(unit); } bool Board::can_move(const Tile& from, const Tile& to) const { if (out_of_range(from.x, from.y)) { return false; } - if (!units[from.y][from.x]) { + if (!is_unit_set(from)) { return false; } - return units[from.y][from.x]->can_move(from, to); + return std::visit(CanMove{from, to}, units[from.y][from.x].value()); } bool Board::move_unit(const Tile& from, const Tile& to) { + using std::swap; if (can_move(from, to)) { - units[from.y][from.x].swap(units[to.y][to.x]); + swap(units[from.y][from.x], units[to.y][to.x]); return true; } return false; } void Board::reverse_move_unit(const Tile& from, const Tile& to) { + using std::swap; Tile rev_from = point_reflection(from.x, from.y); Tile rev_to = point_reflection(to.x, to.y); - std::shared_ptr temp_ptr = units[rev_from.y][rev_from.x]; //<---- this does! (whaaat?) - units[rev_from.y][rev_from.x] = units[rev_to.y][rev_to.x]; - units[rev_to.y][rev_to.x] = temp_ptr; - // units[rev_from.y][rev_from.y].swap(units[rev_to.y][rev_to.x]); <---- this doesnt work! + swap(units[rev_from.y][rev_from.x], units[rev_to.y][rev_to.x]); } Tile Board::point_reflection(int col, int row) { @@ -269,26 +273,25 @@ Board& Board::operator=(const Board& rhs) { } void Board::update(const Board& other_board) { + using std::swap; Tile other_unit; *this = other_board; for (int row = 0; row < height / 2; ++row) { for (int col = 0; col < width; ++col) { other_unit = point_reflection(col, row); - units[other_unit.y][other_unit.x].swap(units[row][col]); + swap(units[other_unit.y][other_unit.x], units[row][col]); } } } -std::shared_ptr Board::get_unit(int col, int row) const { +const std::optional& Board::get_unit(int col, int row) const { if (out_of_range(col, row)) { - return std::shared_ptr{}; + // TODO: maybe more sophisticated error handling? + return std::nullopt; } return units[row][col]; } -std::shared_ptr Board::get_unit(const Tile& chosen_unit) const { - if (out_of_range(chosen_unit.x, chosen_unit.y)) { - return std::shared_ptr{}; - } - return units[chosen_unit.y][chosen_unit.x]; +const std::optional& Board::get_unit(const Tile& chosen_unit) const { + return get_unit(chosen_unit.x, chosen_unit.y); } \ No newline at end of file diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 0b23c1c..9b1ac8b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -18,7 +18,9 @@ add_library( unit/RegularUnit.cpp unit/ScoutUnit.cpp unit/SpyUnit.cpp - unit/Unit.cpp) + unit/Unit.cpp + unit/UnitCounter.cpp + unit/UnitModel.cpp) add_executable(${PROJECT_NAME} main.cpp) diff --git a/src/GameController.cpp b/src/GameController.cpp index 9f5fe25..7987a59 100644 --- a/src/GameController.cpp +++ b/src/GameController.cpp @@ -4,6 +4,7 @@ #include "GameView.hpp" #include "Player.hpp" +#include "unit/visit/GetOwner.hpp" GameController::GameController(Player& pA, Player& pB, GameView& g_view) : playerA(pA), @@ -125,7 +126,7 @@ void GameController::set_active_unit(sf::Event& event) { if (!current_player->get_board().get_unit(chosen_tile)) { return; } - if (current_player->get_board().get_unit(chosen_tile)->get_owner() != current_player->get_player_number()) { + if (std::visit(GetOwner{}, current_player->get_board().get_unit(chosen_tile).value()) != current_player->get_player_number()) { return; } @@ -181,7 +182,7 @@ void GameController::move_active_unit(sf::Event& event) { return; } if (current_player->get_tile_info(chosen_tile) == "enemy") { - if (current_player->get_board().get_unit(chosen_tile)->get_type() == "flag") { + if (std::holds_alternative(current_player->get_board().get_unit(chosen_tile).value())) { game_finished = true; victorious_player_name = current_player->get_player_name(); } diff --git a/src/GameView.cpp b/src/GameView.cpp index 8032d77..333c7f8 100644 --- a/src/GameView.cpp +++ b/src/GameView.cpp @@ -306,7 +306,7 @@ void GameView::draw_info_box(sf::RenderWindow& win) { info_box.draw(win); } -void GameView::draw_attack_info_box(sf::RenderWindow& win, const std::shared_ptr& attacker, const std::shared_ptr& attacked) { +void GameView::draw_attack_info_box(sf::RenderWindow& win, const std::optional& attacker, const std::optional& attacked) { if (!clock_started) { clock.restart(); clock_started = true; @@ -322,35 +322,23 @@ void GameView::draw_attack_info_box(sf::RenderWindow& win, const std::shared_ptr } void GameView::draw_units(sf::RenderWindow& win) { - int object_x_pos = -1; - int object_y_pos = -1; - int unit_idx = -1; for (int row = 0; row < current_player->get_board().get_height(); ++row) { - object_y_pos = (row + 1) * TILE_SIZE; + const int object_y_pos = (row + 1) * TILE_SIZE; for (int col = 0; col < current_player->get_board().get_width(); ++col) { - object_x_pos = (col + 1) * TILE_SIZE; - if (current_player->get_tile_info(col, row) == "regular") { - unit_idx = current_player->get_board().get_unit(col, row)->get_value() - 2; - draw_sprite(win, unit_idx, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "scout") { - draw_sprite(win, 0, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "miner") { - draw_sprite(win, 1, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "bomb") { - draw_sprite(win, 9, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "flag") { - draw_sprite(win, 10, object_x_pos, object_y_pos); - } - if (current_player->get_tile_info(col, row) == "spy") { - draw_sprite(win, 11, object_x_pos, object_y_pos); - } + const int object_x_pos = (col + 1) * TILE_SIZE; + const auto& unit = current_player->get_board().get_unit(col, row); + int unit_idx = std::visit(overloads{ + [](const RegularUnit& runit){ return runit.get_value() - 2; }, + [](const ScoutUnit&){ return 0; }, + [](const MinerUnit&){ return 1; }, + [](const BombUnit&){ return 9; }, + [](const FlagUnit&){ return 10; }, + [](const SpyUnit&){ return 11; }, + }, unit.value()); if (current_player->get_tile_info(col, row) == "enemy") { - draw_sprite(win, 12, object_x_pos, object_y_pos); + unit_idx = 12; } + draw_sprite(win, unit_idx, object_x_pos, object_y_pos); } } } @@ -385,14 +373,14 @@ void GameView::draw_sprite(sf::RenderWindow& win, int idx, int sprite_pos_x, int } void GameView::draw_possible_moves_for_active_unit(sf::RenderWindow& win, const Tile& active_unit) { - if (!current_player->get_board().get_unit(active_unit.x, active_unit.y)) { + const auto& unit = current_player->get_board().get_unit(active_unit.x, active_unit.y); + if (!unit) { return; } - if (current_player->get_board().get_unit(active_unit.x, active_unit.y)->get_type() == "scout") { - highlight_scout_moves(win, active_unit); - } else { - highlight_regular_moves(win, active_unit); - } + std::visit(overloads{ + [this, &win, &active_unit](const ScoutUnit&){ highlight_scout_moves(win, active_unit); }, + [this, &win, &active_unit](const auto&){ highlight_regular_moves(win, active_unit); }, + }, unit.value()); } void GameView::highlight_regular_moves(sf::RenderWindow& win, const Tile& active_unit) { diff --git a/src/Player.cpp b/src/Player.cpp index 934081a..f362352 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -1,7 +1,10 @@ -#include "unit/Unit.hpp" #include "Player.hpp" + #include -#include "Attack.h" + +#include "unit/Unit.hpp" +#include "unit/visit/Attack.hpp" +#include "unit/visit/GetOwner.hpp" void Player::set_units_count() { units_count.insert(std::pair{"regular4", 0}); @@ -20,22 +23,11 @@ void Player::set_units_count() { } void Player::set_unit(int col, int row, int choice) { - if (board.set_unit(col, row, player, choice)) { - std::shared_ptr chosen_unit = board.get_unit(col, row); - if (chosen_unit->get_type() == "regular") { - units_count[chosen_unit->get_type() + std::to_string(chosen_unit->get_value())]++; - } - units_count[chosen_unit->get_type()]++; - } + board.set_unit(col, row, player, choice); } void Player::remove_unit(int col, int row) { if (board.get_unit(col, row)) { - std::shared_ptr temp_unit = board.get_unit(col, row); - if (temp_unit->get_type() == "regular") { - units_count[temp_unit->get_type() + std::to_string(temp_unit->get_value())]--; - } - units_count[board.get_unit(col, row)->get_type()]--; board.remove_unit(col, row); } } @@ -56,7 +48,7 @@ attack::Result Player::attack(Tile attacker, Tile attacked) { // TODO: make the actual implementation a strategy (use dependency injection) const auto& attacker_unit = board.get_unit(attacker); const auto& attacked_unit = board.get_unit(attacked); - return attack::attack(attacker_unit, attacked_unit); + return std::visit(Attack{}, attacker_unit.value(), attacked_unit.value()); } void Player::reverse_move_unit(Tile from, Tile to) { @@ -71,7 +63,7 @@ bool Player::can_move(Tile from, Tile to) { return false; } if (board.get_unit(to.x, to.y)) { - if (board.get_unit(to.x, to.y)->get_owner() == player) { + if (std::visit(GetOwner{}, board.get_unit(to.x, to.y).value()) == player) { return false; } } diff --git a/src/unit/BombUnit.cpp b/src/unit/BombUnit.cpp index dee9e48..1ba222c 100644 --- a/src/unit/BombUnit.cpp +++ b/src/unit/BombUnit.cpp @@ -1,6 +1,4 @@ #include "unit/BombUnit.hpp" BombUnit::BombUnit(Turn player) - : Unit(-1, "bomb", player) {}; - -bool BombUnit::can_move(const Tile &, const Tile &) const { return false; } + : model_(-1, "bomb", player) {}; diff --git a/src/unit/FlagUnit.cpp b/src/unit/FlagUnit.cpp index 1cfb1a5..63da6ae 100644 --- a/src/unit/FlagUnit.cpp +++ b/src/unit/FlagUnit.cpp @@ -1,6 +1,4 @@ #include "unit/FlagUnit.hpp" FlagUnit::FlagUnit(Turn player) - : Unit(-1, "flag", player) {}; - -bool FlagUnit::can_move(const Tile &, const Tile &) const { return false; } + : model_(-1, "flag", player) {}; diff --git a/src/unit/MinerUnit.cpp b/src/unit/MinerUnit.cpp index b176a9a..af1a6b3 100644 --- a/src/unit/MinerUnit.cpp +++ b/src/unit/MinerUnit.cpp @@ -1,5 +1,5 @@ #include "unit/MinerUnit.hpp" MinerUnit::MinerUnit(Turn player) - : Unit(3, "miner", player) {} + : model_(3, "miner", player) {} \ No newline at end of file diff --git a/src/unit/RegularUnit.cpp b/src/unit/RegularUnit.cpp index 86bbfa0..0204e80 100644 --- a/src/unit/RegularUnit.cpp +++ b/src/unit/RegularUnit.cpp @@ -1,4 +1,4 @@ #include "unit/RegularUnit.hpp" RegularUnit::RegularUnit(int value, Turn player) - : Unit(value, "regular", player) {}; + : model_(value, "regular", player), counter_(value) {}; diff --git a/src/unit/ScoutUnit.cpp b/src/unit/ScoutUnit.cpp index b87854b..88a4773 100644 --- a/src/unit/ScoutUnit.cpp +++ b/src/unit/ScoutUnit.cpp @@ -1,17 +1,4 @@ #include "unit/ScoutUnit.hpp" ScoutUnit::ScoutUnit(Turn player) - : Unit(2, "scout", player) {}; - -bool ScoutUnit::can_move(const Tile &from, const Tile &to) const -{ - if (from.x == to.x) - { - return true; - } - if (from.y == to.y) - { - return true; - } - return false; -}; + : model_(2, "scout", player) {}; diff --git a/src/unit/SpyUnit.cpp b/src/unit/SpyUnit.cpp index 9f4a9f0..c2dde45 100644 --- a/src/unit/SpyUnit.cpp +++ b/src/unit/SpyUnit.cpp @@ -1,4 +1,4 @@ #include "unit/SpyUnit.hpp" SpyUnit::SpyUnit(Turn player) - : Unit(1, "spy", player) {}; + : model_(1, "spy", player) {}; diff --git a/src/unit/Unit.cpp b/src/unit/Unit.cpp index 7db3e09..e69de29 100644 --- a/src/unit/Unit.cpp +++ b/src/unit/Unit.cpp @@ -1,35 +0,0 @@ -#include "unit/Unit.hpp" - -Unit::Unit(int value, std::string type, Turn player) - : value_{value}, - type_{std::move(type)}, - owner_{player} -{ -} - -int Unit::get_value() const noexcept { return value_; }; - -std::string Unit::get_type() const noexcept { return type_; }; - -Turn Unit::get_owner() const noexcept { return owner_; }; - -bool Unit::can_move(const Tile &from, const Tile &to) const -{ - if (from.x + 1 == to.x && from.y == to.y) - { - return true; - } - if (from.x - 1 == to.x && from.y == to.y) - { - return true; - } - if (from.x == to.x && from.y + 1 == to.y) - { - return true; - } - if (from.x == to.x && from.y - 1 == to.y) - { - return true; - } - return false; -} diff --git a/src/unit/UnitCounter.cpp b/src/unit/UnitCounter.cpp new file mode 100644 index 0000000..ab0091a --- /dev/null +++ b/src/unit/UnitCounter.cpp @@ -0,0 +1,48 @@ +#pragma once + +#include "unit/RegularUnit.hpp" +#include "unit/UnitCounter.hpp" + +#include +#include + +std::unordered_map RegularUnitCounter::count_ = {}; + +struct RegularUnitMaxCount { + int operator()(int unit_value) { + switch (unit_value) { + case 4: + case 5: + case 6: + return 4; + case 7: + return 3; + case 8: + return 2; + case 9: + return 1; + case 10: + return 1; + default: + break; + } + std::cerr << "Unexpected unit value: " << unit_value << ", returning max count 0\n"; + return 0; + } +}; + +RegularUnitCounter::RegularUnitCounter(const int unit_value) : unit_value_(unit_value) { ++count_[unit_value]; } +RegularUnitCounter::RegularUnitCounter(const RegularUnitCounter& rhs) : RegularUnitCounter(rhs.unit_value_) {} +RegularUnitCounter& RegularUnitCounter::operator=(const RegularUnitCounter& rhs) { + if (this != &rhs) { + unit_value_ = rhs.unit_value_; + ++count_[unit_value_]; + } + return *this; +}; +RegularUnitCounter::RegularUnitCounter(RegularUnitCounter&&) = default; +RegularUnitCounter& RegularUnitCounter::operator=(RegularUnitCounter&&) = default; +RegularUnitCounter::~RegularUnitCounter() { --count_[unit_value_]; } + +int RegularUnitCounter::get_count(const int value) { return count_[value]; } +int RegularUnitCounter::get_max_count(const int value) { return RegularUnitMaxCount{}(value); } \ No newline at end of file diff --git a/src/unit/UnitModel.cpp b/src/unit/UnitModel.cpp new file mode 100644 index 0000000..57e45b1 --- /dev/null +++ b/src/unit/UnitModel.cpp @@ -0,0 +1,12 @@ +#include "unit/UnitModel.hpp" + +UnitModel::UnitModel(int value, std::string type, Turn player) +: value_(value), + type_(std::move(type)), + owner_(player) {} + + +int UnitModel::get_value() const noexcept { return value_; } +[[deprecated("Future refactoring will remove get_type()")]] +std::string UnitModel::get_type() const noexcept { return type_; } +Turn UnitModel::get_owner() const noexcept { return owner_; } \ No newline at end of file From ba5398fd4b5902c6d94e197cf5d06f06424f32e4 Mon Sep 17 00:00:00 2001 From: Wojciech Matusiak <62173407+WojtekMs@users.noreply.github.com> Date: Sun, 23 Mar 2025 16:27:41 +0100 Subject: [PATCH 05/11] Update unit counting logic Move unit counting into a UnitCounter, where each class counts itself --- include/Board.hpp | 1 - include/Player.hpp | 5 +---- src/Board.cpp | 18 ++++++------------ src/CMakeLists.txt | 1 - src/Player.cpp | 34 ++++++---------------------------- 5 files changed, 13 insertions(+), 46 deletions(-) diff --git a/include/Board.hpp b/include/Board.hpp index d6d6ec7..510638d 100644 --- a/include/Board.hpp +++ b/include/Board.hpp @@ -55,7 +55,6 @@ class Board { void update(const Board& other_board); Board& operator=(const Board& rhs); State get_state() const { return current_state; }; - int get_max_unit_count(const std::string& unit_type) const { return max_count_of_each_unit.at(unit_type); }; int get_max_unit_count(int idx) const; }; \ No newline at end of file diff --git a/include/Player.hpp b/include/Player.hpp index 0d1f87a..9a56d04 100644 --- a/include/Player.hpp +++ b/include/Player.hpp @@ -10,13 +10,10 @@ class Player { std::string name; Turn player; - std::unordered_map units_count; Board board; - void set_units_count(); public: - Player(std::string n, Turn p): name(n), player(p), units_count(), board() { set_units_count(); }; - int get_units_count(const std::string& type) const { return units_count.at(type); }; + Player(std::string n, Turn p): name(n), player(p), board() { }; int get_units_count(int idx); Turn get_player_number() { return player; }; std::string get_player_name() { return name; }; diff --git a/src/Board.cpp b/src/Board.cpp index 7d916de..56d8cb5 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -113,29 +113,23 @@ std::string Board::get_tile_info(const Tile& tile, Turn player) const { int Board::get_max_unit_count(int idx) const { switch (idx) { case 0: - return max_count_of_each_unit.at("scout"); + return ScoutUnit::get_max_count(); case 1: - return max_count_of_each_unit.at("miner"); + return MinerUnit::get_max_count(); case 2: - return max_count_of_each_unit.at("regular4"); case 3: - return max_count_of_each_unit.at("regular5"); case 4: - return max_count_of_each_unit.at("regular6"); case 5: - return max_count_of_each_unit.at("regular7"); case 6: - return max_count_of_each_unit.at("regular8"); case 7: - return max_count_of_each_unit.at("regular9"); case 8: - return max_count_of_each_unit.at("regular10"); + return RegularUnit::get_max_count(idx + 2); case 9: - return max_count_of_each_unit.at("bomb"); + return BombUnit::get_max_count(); case 10: - return max_count_of_each_unit.at("flag"); + return FlagUnit::get_max_count(); case 11: - return max_count_of_each_unit.at("spy"); + return SpyUnit::get_max_count(); } return -1; } diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9b1ac8b..32a5ed2 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,7 +11,6 @@ add_library( GameView.cpp MainMenu.cpp Player.cpp - Attack.cpp unit/BombUnit.cpp unit/FlagUnit.cpp unit/MinerUnit.cpp diff --git a/src/Player.cpp b/src/Player.cpp index f362352..39a8397 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -6,22 +6,6 @@ #include "unit/visit/Attack.hpp" #include "unit/visit/GetOwner.hpp" -void Player::set_units_count() { - units_count.insert(std::pair{"regular4", 0}); - units_count.insert(std::pair{"regular5", 0}); - units_count.insert(std::pair{"regular6", 0}); - units_count.insert(std::pair{"regular7", 0}); - units_count.insert(std::pair{"regular8", 0}); - units_count.insert(std::pair{"regular9", 0}); - units_count.insert(std::pair{"regular10", 0}); - units_count.insert(std::pair{"bomb", 0}); - units_count.insert(std::pair{"miner", 0}); - units_count.insert(std::pair{"flag", 0}); - units_count.insert(std::pair{"spy", 0}); - units_count.insert(std::pair{"scout", 0}); - units_count.insert(std::pair{"marshal", 0}); -} - void Player::set_unit(int col, int row, int choice) { board.set_unit(col, row, player, choice); } @@ -89,29 +73,23 @@ std::string Player::get_tile_info(Tile tile) const { int Player::get_units_count(int idx) { switch (idx) { case 0: - return units_count.at("scout"); + return ScoutUnit::get_count(); case 1: - return units_count.at("miner"); + return MinerUnit::get_count(); case 2: - return units_count.at("regular4"); case 3: - return units_count.at("regular5"); case 4: - return units_count.at("regular6"); case 5: - return units_count.at("regular7"); case 6: - return units_count.at("regular8"); case 7: - return units_count.at("regular9"); case 8: - return units_count.at("regular10"); + return RegularUnit::get_count(idx + 2); case 9: - return units_count.at("bomb"); + return BombUnit::get_count(); case 10: - return units_count.at("flag"); + return FlagUnit::get_count(); case 11: - return units_count.at("spy"); + return SpyUnit::get_count(); } return -1; } From 3bc92073f341bc9c95f89baf6e63b84a440fe9fb Mon Sep 17 00:00:00 2001 From: Wojciech Matusiak <62173407+WojtekMs@users.noreply.github.com> Date: Sun, 23 Mar 2025 17:18:53 +0100 Subject: [PATCH 06/11] Format code using clang-format Add clang-format to requirements.txt --- .gitignore | 1 + include/Array2D.h | 187 +++--- include/AttackInfoBox.hpp | 76 +-- include/BigButton.hpp | 21 +- include/Board.hpp | 75 +-- include/Box.hpp | 76 +-- include/Button.hpp | 19 +- include/ButtonInterface.hpp | 50 +- include/Game.hpp | 24 +- include/GameController.hpp | 158 ++--- include/GameView.hpp | 223 +++--- include/MainMenu.hpp | 80 ++- include/Player.hpp | 47 +- include/Tile.hpp | 38 +- include/Turn.hpp | 7 +- include/cScreen.hpp | 7 +- include/unit/BombUnit.hpp | 26 +- include/unit/FlagUnit.hpp | 29 +- include/unit/MinerUnit.hpp | 30 +- include/unit/RegularUnit.hpp | 24 +- include/unit/ScoutUnit.hpp | 29 +- include/unit/SpyUnit.hpp | 26 +- include/unit/Unit.hpp | 8 +- include/unit/UnitConcepts.hpp | 14 +- include/unit/UnitCounter.hpp | 53 +- include/unit/UnitModel.hpp | 21 +- include/unit/visit/Attack.hpp | 81 ++- include/unit/visit/CanMove.hpp | 84 +-- include/unit/visit/GetOwner.hpp | 9 +- include/unit/visit/GetTileInfo.hpp | 21 +- include/unit/visit/GetUnitSpriteId.hpp | 27 +- requirements.txt | 1 + src/AttackInfoBox.cpp | 263 ++++---- src/BigButton.cpp | 42 +- src/Board.cpp | 436 ++++++------ src/Box.cpp | 189 +++--- src/Button.cpp | 44 +- src/ButtonInterface.cpp | 50 +- src/Game.cpp | 126 ++-- src/GameController.cpp | 496 +++++++------- src/GameView.cpp | 893 +++++++++++++------------ src/MainMenu.cpp | 433 ++++++------ src/Player.cpp | 104 ++- src/main.cpp | 36 +- src/unit/BombUnit.cpp | 3 +- src/unit/FlagUnit.cpp | 3 +- src/unit/MinerUnit.cpp | 4 +- src/unit/ScoutUnit.cpp | 3 +- src/unit/SpyUnit.cpp | 3 +- src/unit/UnitCounter.cpp | 76 ++- src/unit/UnitModel.cpp | 13 +- 51 files changed, 2414 insertions(+), 2375 deletions(-) create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index dd7b397..1c126fa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ build* .vscode CMakeUserPresets.json +env diff --git a/include/Array2D.h b/include/Array2D.h index faea24d..6f4d20b 100644 --- a/include/Array2D.h +++ b/include/Array2D.h @@ -6,140 +6,109 @@ #include #include -template -class Array -{ - std::vector data; - void check_range(int idx) const - { - if (idx < 0 || static_cast(idx) >= data.size()) { - std::cerr << "KABOOM !" << std::endl; - throw std::out_of_range("Invalid COLUMN access"); - } +template class Array { + std::vector data; + void check_range(int idx) const { + if (idx < 0 || static_cast(idx) >= data.size()) { + std::cerr << "KABOOM !" << std::endl; + throw std::out_of_range("Invalid COLUMN access"); } + } public: - explicit Array(int size) : data(size) - { - } - T &operator[](int idx) - { - check_range(idx); - return data[idx]; - } - const T &operator[](int idx) const - { - check_range(idx); - return data[idx]; - } + explicit Array(int size) : data(size) {} + T &operator[](int idx) { + check_range(idx); + return data[idx]; + } + const T &operator[](int idx) const { + check_range(idx); + return data[idx]; + } }; -template -class Array2D -{ - std::vector> data; - void check_range(int idx) const - { - if (idx < 0 || static_cast(idx) >= data.size()) { - std::cerr << "KABOOM !" << std::endl; - throw std::out_of_range("Invalid ROW access"); - } +template class Array2D { + std::vector> data; + void check_range(int idx) const { + if (idx < 0 || static_cast(idx) >= data.size()) { + std::cerr << "KABOOM !" << std::endl; + throw std::out_of_range("Invalid ROW access"); } + } public: - explicit Array2D(int width, int height) : data(height, Array(width)) {} - Array &operator[](int idx) - { - check_range(idx); - return data[idx]; - } - const Array &operator[](int idx) const - { - check_range(idx); - return data[idx]; - } + explicit Array2D(int width, int height) : data(height, Array(width)) {} + Array &operator[](int idx) { + check_range(idx); + return data[idx]; + } + const Array &operator[](int idx) const { + check_range(idx); + return data[idx]; + } }; -template <> -class Array -{ +template <> class Array { public: - class my_bool - { - public: - bool value; - my_bool(bool val = false) : value(val){}; - inline friend std::ostream &operator<<(std::ostream &stream, my_bool rhs); - inline operator bool() const; - inline operator bool(); - - }; + class my_bool { + public: + bool value; + my_bool(bool val = false) : value(val) {}; + inline friend std::ostream &operator<<(std::ostream &stream, my_bool rhs); + inline operator bool() const; + inline operator bool(); + }; private: - std::vector data; - void check_range(int idx) const - { - if (idx < 0 || static_cast(idx) >= data.size()) { - std::cerr << "KABOOM !" << std::endl; - throw std::out_of_range("Invalid COLUMN access"); - } + std::vector data; + void check_range(int idx) const { + if (idx < 0 || static_cast(idx) >= data.size()) { + std::cerr << "KABOOM !" << std::endl; + throw std::out_of_range("Invalid COLUMN access"); } + } public: - explicit Array(int size) : data(size) - { - } - my_bool &operator[](int idx) - { - check_range(idx); - return data[idx]; - } - const my_bool &operator[](int idx) const - { - check_range(idx); - return data[idx]; - } + explicit Array(int size) : data(size) {} + my_bool &operator[](int idx) { + check_range(idx); + return data[idx]; + } + const my_bool &operator[](int idx) const { + check_range(idx); + return data[idx]; + } }; -std::ostream &operator<<(std::ostream &stream, Array::my_bool rhs) -{ - stream << rhs.value; - return stream; -} - -Array::my_bool::operator bool() const { - return (const bool)value; +std::ostream &operator<<(std::ostream &stream, Array::my_bool rhs) { + stream << rhs.value; + return stream; } -Array::my_bool::operator bool() { - return value; -} +Array::my_bool::operator bool() const { return (const bool)value; } +Array::my_bool::operator bool() { return value; } -template <> -class Array2D -{ - std::vector::my_bool>> data; - void check_range(int idx) const - { - if (idx < 0 || static_cast(idx) >= data.size()) { - std::cerr << "KABOOM !" << std::endl; - throw std::out_of_range("Invalid ROW access"); - } +template <> class Array2D { + std::vector::my_bool>> data; + void check_range(int idx) const { + if (idx < 0 || static_cast(idx) >= data.size()) { + std::cerr << "KABOOM !" << std::endl; + throw std::out_of_range("Invalid ROW access"); } + } public: - explicit Array2D(int width, int height) : data(height, Array::my_bool>(width)) {} - Array::my_bool> &operator[](int idx) - { - check_range(idx); - return data[idx]; - } - const Array::my_bool> &operator[](int idx) const - { - check_range(idx); - return data[idx]; - } + explicit Array2D(int width, int height) + : data(height, Array::my_bool>(width)) {} + Array::my_bool> &operator[](int idx) { + check_range(idx); + return data[idx]; + } + const Array::my_bool> &operator[](int idx) const { + check_range(idx); + return data[idx]; + } }; #endif /* ARRAY2D_H_ */ diff --git a/include/AttackInfoBox.hpp b/include/AttackInfoBox.hpp index fe14831..8b00a08 100644 --- a/include/AttackInfoBox.hpp +++ b/include/AttackInfoBox.hpp @@ -1,46 +1,46 @@ #pragma once -#include #include +#include #include "unit/Unit.hpp" -class AttackInfoBox -{ - const std::string path_to_textures; - int attacking_unit_pos_x; - int attacking_unit_pos_y; - int attacked_unit_pos_x; - int attacked_unit_pos_y; - std::array red_units_sprites_ptrs; - std::array blue_units_sprites_ptrs; - sf::Texture box_texture; - sf::Sprite box_sprite; - sf::Font box_font; - sf::Text box_text; - sf::Sprite attacking_unit; - sf::Sprite attacked_unit; - sf::Sprite& winner_highlight; - const Unit* attacker_ptr; - const Unit* attacked_ptr; +class AttackInfoBox { + const std::string path_to_textures; + int attacking_unit_pos_x; + int attacking_unit_pos_y; + int attacked_unit_pos_x; + int attacked_unit_pos_y; + std::array red_units_sprites_ptrs; + std::array blue_units_sprites_ptrs; + sf::Texture box_texture; + sf::Sprite box_sprite; + sf::Font box_font; + sf::Text box_text; + sf::Sprite attacking_unit; + sf::Sprite attacked_unit; + sf::Sprite &winner_highlight; + const Unit *attacker_ptr; + const Unit *attacked_ptr; + + int get_unit_sprite_idx(const Unit &unit); + void load_box_texture(); + void load_font(); + void update_attacking_unit_pos(); + void update_attacked_unit_pos(); + void update_box_text_pos(); + const Unit *get_winner(); + void set_winner_highlight(); + void draw_winner_highlight(sf::RenderWindow &win); - int get_unit_sprite_idx(const Unit& unit); - void load_box_texture(); - void load_font(); - void update_attacking_unit_pos(); - void update_attacked_unit_pos(); - void update_box_text_pos(); - const Unit* get_winner(); - void set_winner_highlight(); - void draw_winner_highlight(sf::RenderWindow& win); - public: - AttackInfoBox(std::array& red_units_sprites, std::array& blue_units_sprites, sf::Sprite& winning_unit_highlight); - void draw(sf::RenderWindow& win); - void set_position(int x, int y); - void set_attacking_unit(const std::optional& attacker); - void set_attacked_unit(const std::optional& victim); - float get_height() const { return box_sprite.getGlobalBounds().height; }; - float get_width() const { return box_sprite.getGlobalBounds().width; }; - - +public: + AttackInfoBox(std::array &red_units_sprites, + std::array &blue_units_sprites, + sf::Sprite &winning_unit_highlight); + void draw(sf::RenderWindow &win); + void set_position(int x, int y); + void set_attacking_unit(const std::optional &attacker); + void set_attacked_unit(const std::optional &victim); + float get_height() const { return box_sprite.getGlobalBounds().height; }; + float get_width() const { return box_sprite.getGlobalBounds().width; }; }; \ No newline at end of file diff --git a/include/BigButton.hpp b/include/BigButton.hpp index 16b357d..fb70a7e 100644 --- a/include/BigButton.hpp +++ b/include/BigButton.hpp @@ -2,16 +2,15 @@ #include "ButtonInterface.hpp" -class BigButton : public ButtonInterface -{ - protected: - sf::Texture button_texture; - sf::Texture highlighted_button_texture; +class BigButton : public ButtonInterface { +protected: + sf::Texture button_texture; + sf::Texture highlighted_button_texture; - void load_button_texture(); - void load_highlighted_button_texture(); - - public: - explicit BigButton(const std::string& button_text = "default"); - void draw(sf::RenderWindow& win); + void load_button_texture(); + void load_highlighted_button_texture(); + +public: + explicit BigButton(const std::string &button_text = "default"); + void draw(sf::RenderWindow &win); }; \ No newline at end of file diff --git a/include/Board.hpp b/include/Board.hpp index 510638d..4715c95 100644 --- a/include/Board.hpp +++ b/include/Board.hpp @@ -3,58 +3,57 @@ #include #include #include +#include #include #include -#include #include "Array2D.h" #include "Tile.hpp" -#include "unit/Unit.hpp" #include "Turn.hpp" +#include "unit/Unit.hpp" enum class State { - Uninitialized, - Initialized, - Full, + Uninitialized, + Initialized, + Full, }; constexpr int MAX_UNIT_COUNT = 40; class Board { private: - int height{}; - int width{}; - State current_state{}; - int unit_count{}; - Array2D> units; - std::array obstacles; - const std::map max_count_of_each_unit; - - void set_default_units(); - void set_obstacles(); - Tile point_reflection(int col, int row); - bool out_of_range(int col, int row) const; - void set_state(State state); - bool is_unit_set(Tile tile) const; - void unset_unit(Tile tile); + int height{}; + int width{}; + State current_state{}; + int unit_count{}; + Array2D> units; + std::array obstacles; + const std::map max_count_of_each_unit; + + void set_default_units(); + void set_obstacles(); + Tile point_reflection(int col, int row); + bool out_of_range(int col, int row) const; + void set_state(State state); + bool is_unit_set(Tile tile) const; + void unset_unit(Tile tile); public: - Board(); - bool set_unit(int col, int row, Turn player, int choice); - void remove_unit(int col, int row); - void reverse_remove_unit(int col, int row); - std::string get_tile_info(int col, int row, Turn player) const; - std::string get_tile_info(const Tile& tile, Turn player) const; - int get_height() const { return height; }; - int get_width() const { return width; }; - const std::optional& get_unit(int col, int row) const; - const std::optional& get_unit(const Tile& chosen_unit) const; - bool can_move(const Tile& from, const Tile& to) const; - bool move_unit(const Tile& from, const Tile& to); - void reverse_move_unit(const Tile& from, const Tile& to); - void update(const Board& other_board); - Board& operator=(const Board& rhs); - State get_state() const { return current_state; }; - int get_max_unit_count(int idx) const; - + Board(); + bool set_unit(int col, int row, Turn player, int choice); + void remove_unit(int col, int row); + void reverse_remove_unit(int col, int row); + std::string get_tile_info(int col, int row, Turn player) const; + std::string get_tile_info(const Tile &tile, Turn player) const; + int get_height() const { return height; }; + int get_width() const { return width; }; + const std::optional &get_unit(int col, int row) const; + const std::optional &get_unit(const Tile &chosen_unit) const; + bool can_move(const Tile &from, const Tile &to) const; + bool move_unit(const Tile &from, const Tile &to); + void reverse_move_unit(const Tile &from, const Tile &to); + void update(const Board &other_board); + Board &operator=(const Board &rhs); + State get_state() const { return current_state; }; + int get_max_unit_count(int idx) const; }; \ No newline at end of file diff --git a/include/Box.hpp b/include/Box.hpp index 25b7350..faf8f9d 100644 --- a/include/Box.hpp +++ b/include/Box.hpp @@ -4,44 +4,44 @@ #include "Button.hpp" -class Box -{ - protected: - const std::string path_to_textures; - size_t max_char_count_inside_box; - size_t max_number_of_text_lines_inside_box; - int box_text_x_pos; - int box_text_y_pos; - int button_x_pos; - int button_y_pos; - Button button; - sf::Font font; - sf::Text box_text; - sf::Texture box_texture; - sf::Sprite box_sprite; - - void load_box_texture(); - void load_font(); - void set_default_text(const std::string& text); - void update_text_pos(); - void update_button_pos(); - void break_text_into_lines(); - void update_max_char_count(); - public: - explicit Box(const std::string& text = "default"); - void set_position(int x, int y); - void set_position(const sf::Vector2f& coords); - void set_text(const std::string& text); - void set_button_text(const std::string& text = "OK"); - void set_button_highlight_on() { button.highlight_on(); }; - void set_button_highlight_off() { button.highlight_off(); }; - bool button_contains(int x, int y) const { return button.contains(x, y); }; - bool button_is_highlighted() const { return button.is_highlighted(); }; - void draw(sf::RenderWindow& win); - float get_height() const { return box_sprite.getGlobalBounds().height; }; - float get_width() const { return box_sprite.getGlobalBounds().width; }; - sf::Vector2f get_position() const { return box_sprite.getPosition(); }; - size_t get_max_char_count_inside_box() const { return max_char_count_inside_box; }; +class Box { +protected: + const std::string path_to_textures; + size_t max_char_count_inside_box; + size_t max_number_of_text_lines_inside_box; + int box_text_x_pos; + int box_text_y_pos; + int button_x_pos; + int button_y_pos; + Button button; + sf::Font font; + sf::Text box_text; + sf::Texture box_texture; + sf::Sprite box_sprite; + void load_box_texture(); + void load_font(); + void set_default_text(const std::string &text); + void update_text_pos(); + void update_button_pos(); + void break_text_into_lines(); + void update_max_char_count(); +public: + explicit Box(const std::string &text = "default"); + void set_position(int x, int y); + void set_position(const sf::Vector2f &coords); + void set_text(const std::string &text); + void set_button_text(const std::string &text = "OK"); + void set_button_highlight_on() { button.highlight_on(); }; + void set_button_highlight_off() { button.highlight_off(); }; + bool button_contains(int x, int y) const { return button.contains(x, y); }; + bool button_is_highlighted() const { return button.is_highlighted(); }; + void draw(sf::RenderWindow &win); + float get_height() const { return box_sprite.getGlobalBounds().height; }; + float get_width() const { return box_sprite.getGlobalBounds().width; }; + sf::Vector2f get_position() const { return box_sprite.getPosition(); }; + size_t get_max_char_count_inside_box() const { + return max_char_count_inside_box; + }; }; \ No newline at end of file diff --git a/include/Button.hpp b/include/Button.hpp index 1890c5f..4d38c1a 100644 --- a/include/Button.hpp +++ b/include/Button.hpp @@ -4,18 +4,15 @@ #include "ButtonInterface.hpp" -class Button : public ButtonInterface -{ +class Button : public ButtonInterface { protected: - sf::Texture button_texture; - sf::Texture highlighted_button_texture; + sf::Texture button_texture; + sf::Texture highlighted_button_texture; + + void load_button_texture(); + void load_highlighted_button_texture(); - void load_button_texture(); - void load_highlighted_button_texture(); public: - explicit Button(const std::string& text = "default"); - void draw(sf::RenderWindow& win); + explicit Button(const std::string &text = "default"); + void draw(sf::RenderWindow &win); }; - - - diff --git a/include/ButtonInterface.hpp b/include/ButtonInterface.hpp index 7ebb2df..191f98e 100644 --- a/include/ButtonInterface.hpp +++ b/include/ButtonInterface.hpp @@ -4,31 +4,33 @@ class ButtonInterface { protected: - int text_x_pos; - int text_y_pos; - bool highlighted; - const std::string path_to_textures; - sf::Sprite button; - sf::Sprite highlighted_button; - sf::Font font; - sf::Text button_text; + int text_x_pos; + int text_y_pos; + bool highlighted; + const std::string path_to_textures; + sf::Sprite button; + sf::Sprite highlighted_button; + sf::Font font; + sf::Text button_text; - void load_font(); - void set_default_button_text(const std::string& text); - void update_text_pos(); + void load_font(); + void set_default_button_text(const std::string &text); + void update_text_pos(); public: - explicit ButtonInterface(const std::string& text); - void set_text(const std::string& text); - void set_position(int x, int y); - void set_position(sf::Vector2f coords); - virtual void draw(sf::RenderWindow& win) = 0; - float get_height() const { return button.getGlobalBounds().height; }; - float get_width() const { return button.getGlobalBounds().width; }; - bool contains(int x, int y) const { return button.getGlobalBounds().contains(x, y); }; - void highlight_on() { highlighted = true; }; - void highlight_off() { highlighted = false; }; - bool is_highlighted() const { return highlighted; }; - sf::Vector2f get_position() const { return button.getPosition(); }; - sf::String get_text() const { return button_text.getString(); }; + explicit ButtonInterface(const std::string &text); + void set_text(const std::string &text); + void set_position(int x, int y); + void set_position(sf::Vector2f coords); + virtual void draw(sf::RenderWindow &win) = 0; + float get_height() const { return button.getGlobalBounds().height; }; + float get_width() const { return button.getGlobalBounds().width; }; + bool contains(int x, int y) const { + return button.getGlobalBounds().contains(x, y); + }; + void highlight_on() { highlighted = true; }; + void highlight_off() { highlighted = false; }; + bool is_highlighted() const { return highlighted; }; + sf::Vector2f get_position() const { return button.getPosition(); }; + sf::String get_text() const { return button_text.getString(); }; }; \ No newline at end of file diff --git a/include/Game.hpp b/include/Game.hpp index 1040558..ee199e0 100644 --- a/include/Game.hpp +++ b/include/Game.hpp @@ -1,17 +1,17 @@ #pragma once -#include "cScreen.hpp" -#include "GameView.hpp" #include "GameController.hpp" +#include "GameView.hpp" +#include "cScreen.hpp" + +class Game : public cScreen { + GameView &game_view; + GameController &game_controller; + sf::Clock clock; + bool clock_started; + void draw(sf::RenderWindow &win); -class Game :public cScreen -{ - GameView& game_view; - GameController& game_controller; - sf::Clock clock; - bool clock_started; - void draw(sf::RenderWindow& win); - public: - Game(GameView& g_view, GameController& g_controller); - std::string run(sf::RenderWindow& win) override; +public: + Game(GameView &g_view, GameController &g_controller); + std::string run(sf::RenderWindow &win) override; }; \ No newline at end of file diff --git a/include/GameController.hpp b/include/GameController.hpp index 56d58f2..9791f8b 100644 --- a/include/GameController.hpp +++ b/include/GameController.hpp @@ -1,15 +1,15 @@ #pragma once #include +#include #include "Board.hpp" -#include struct mouse_data { - float mouse_x; - float mouse_y; - float mouse_object_offset_x; - float mouse_object_offset_y; + float mouse_x; + float mouse_y; + float mouse_object_offset_x; + float mouse_object_offset_y; }; enum class Turn; @@ -17,84 +17,88 @@ class Player; class GameView; class GameController { - Player& playerA; - Player& playerB; - GameView& game_view; - Player* current_player; - Player* other_player; - std::optional attacker; - std::optional attacked; - sf::Clock clock; - sf::Time total_time_unit_attacked; + Player &playerA; + Player &playerB; + GameView &game_view; + Player *current_player; + Player *other_player; + std::optional attacker; + std::optional attacked; + sf::Clock clock; + sf::Time total_time_unit_attacked; - std::string victorious_player_name; - Turn current_player_turn; - mouse_data m_data; - size_t TILE_SIZE; - size_t selected_unit_idx; + std::string victorious_player_name; + Turn current_player_turn; + mouse_data m_data; + size_t TILE_SIZE; + size_t selected_unit_idx; - bool dragging; - bool board_a_initialized; - bool board_b_initialized; - bool is_active_unit; - bool unit_moved_this_round; - bool end_turn_button_pressed; - bool turn_approved; - bool unit_attacked; - bool remove_button_pressed; - bool done_button_pressed; - bool randomize_button_pressed; - bool end_game_info_box_button_pressed; - bool game_finished; - bool clock_started; + bool dragging; + bool board_a_initialized; + bool board_b_initialized; + bool is_active_unit; + bool unit_moved_this_round; + bool end_turn_button_pressed; + bool turn_approved; + bool unit_attacked; + bool remove_button_pressed; + bool done_button_pressed; + bool randomize_button_pressed; + bool end_game_info_box_button_pressed; + bool game_finished; + bool clock_started; - Tile active_unit; - Tile attacking_unit; - Tile attacked_unit; + Tile active_unit; + Tile attacking_unit; + Tile attacked_unit; - void TEST_SET_RANDOM_UNITS(); - sf::Vector2f return_pixels(int col, int row) const; - Tile return_tile(const sf::Vector2f& coords) const; - Tile return_tile(int x, int y) const; + void TEST_SET_RANDOM_UNITS(); + sf::Vector2f return_pixels(int col, int row) const; + Tile return_tile(const sf::Vector2f &coords) const; + Tile return_tile(int x, int y) const; - void drag_red_player(sf::Event& event); - void drag_blue_player(sf::Event& event); - void change_init_turn(sf::Event& event); - void set_unit(sf::Event& event); - void remove_unit(); - void randomize_units(); - void set_active_unit(sf::Event& event); - void change_player_turn(); - void move_active_unit(sf::Event& event); - bool is_out_of_the_board(int x, int y); - void set_buttons_pressed(); - void resolve_unit_conflict(const Tile& attacked_unit); + void drag_red_player(sf::Event &event); + void drag_blue_player(sf::Event &event); + void change_init_turn(sf::Event &event); + void set_unit(sf::Event &event); + void remove_unit(); + void randomize_units(); + void set_active_unit(sf::Event &event); + void change_player_turn(); + void move_active_unit(sf::Event &event); + bool is_out_of_the_board(int x, int y); + void set_buttons_pressed(); + void resolve_unit_conflict(const Tile &attacked_unit); public: - GameController(Player& pA, Player& pB, GameView& g_view); - bool get_dragging() { return dragging; }; - bool get_board_a_initialized() { return board_a_initialized; }; - bool get_board_b_initialized() { return board_b_initialized; }; - bool get_is_active_unit() { return is_active_unit; }; - bool get_unit_moved_this_round() { return unit_moved_this_round; }; - bool get_end_turn_button_pressed() { return end_turn_button_pressed; }; - bool get_turn_approved() { return turn_approved; }; - bool get_unit_attacked() const { return unit_attacked; }; - bool get_remove_button_pressed() { return remove_button_pressed; }; - bool get_done_button_pressed() { return done_button_pressed; }; - bool get_randomize_button_pressed() { return randomize_button_pressed; }; - bool get_end_game_info_box_button_pressed() { return end_game_info_box_button_pressed; }; - bool get_game_finished() { return game_finished; }; - bool both_boards_set() const; - std::optional get_attacker() const { return attacker; }; - std::optional get_attacked() const { return attacked; }; - std::string get_victorious_player_name() const { return victorious_player_name; }; - const Tile& get_active_unit() const { return active_unit; }; - int get_selected_init_unit_idx() const { return selected_unit_idx; }; - const mouse_data& get_mouse_data() const { return m_data; }; - Player* get_current_player() const { return current_player; }; - Player* get_other_player() const { return other_player; }; - void update_unit_attacked(const sf::Time& time_past); + GameController(Player &pA, Player &pB, GameView &g_view); + bool get_dragging() { return dragging; }; + bool get_board_a_initialized() { return board_a_initialized; }; + bool get_board_b_initialized() { return board_b_initialized; }; + bool get_is_active_unit() { return is_active_unit; }; + bool get_unit_moved_this_round() { return unit_moved_this_round; }; + bool get_end_turn_button_pressed() { return end_turn_button_pressed; }; + bool get_turn_approved() { return turn_approved; }; + bool get_unit_attacked() const { return unit_attacked; }; + bool get_remove_button_pressed() { return remove_button_pressed; }; + bool get_done_button_pressed() { return done_button_pressed; }; + bool get_randomize_button_pressed() { return randomize_button_pressed; }; + bool get_end_game_info_box_button_pressed() { + return end_game_info_box_button_pressed; + }; + bool get_game_finished() { return game_finished; }; + bool both_boards_set() const; + std::optional get_attacker() const { return attacker; }; + std::optional get_attacked() const { return attacked; }; + std::string get_victorious_player_name() const { + return victorious_player_name; + }; + const Tile &get_active_unit() const { return active_unit; }; + int get_selected_init_unit_idx() const { return selected_unit_idx; }; + const mouse_data &get_mouse_data() const { return m_data; }; + Player *get_current_player() const { return current_player; }; + Player *get_other_player() const { return other_player; }; + void update_unit_attacked(const sf::Time &time_past); - void handle_events(sf::Event& event); + void handle_events(sf::Event &event); }; \ No newline at end of file diff --git a/include/GameView.hpp b/include/GameView.hpp index 444434d..c85ab78 100644 --- a/include/GameView.hpp +++ b/include/GameView.hpp @@ -14,111 +14,124 @@ class Player; enum class Turn; class GameView { - Player& playerA; - Player& playerB; - Player* current_player; - Player* other_player; - Turn current_player_turn; - - const std::string board_textures_path; - const std::string pieces_textures_path; - - int TILE_SIZE; - int X_ADDITIONAL_SPACE; - sf::Vector2f window_size; - sf::Vector2f sprite_initial_position; - - bool clock_started; - - sf::Sprite board_border; - sf::Sprite grass_light; - sf::Sprite grass_dark; - std::array obstacle_sprites; - std::array red_units_sprites; - sf::Sprite red_back_sprite; - std::array blue_units_sprites; - sf::Sprite blue_back_sprite; - sf::Sprite yellow_highlight_sprite; - sf::Sprite white_highlight_sprite; - sf::Sprite green_highlight_sprite; - sf::Sprite red_highlight_sprite; - - sf::Texture board_border_texture; - sf::Texture grass_light_texture; - sf::Texture grass_dark_texture; - std::array obstacle_textures; - std::array red_unit_textures; - sf::Texture red_back_texture; - std::array blue_unit_textures; - sf::Texture blue_back_texture; - sf::Texture yellow_highlight_texture; - sf::Texture white_highlight_texture; - sf::Texture green_highlight_texture; - sf::Texture red_highlight_texture; - - sf::Clock clock; - sf::Font font; - sf::Text text; - Button done_button; - Button randomize_button; - Button remove_button; - Button end_turn_button; - Box info_box; - AttackInfoBox attack_info_box; - Box end_game_info_box; - - void load_obstacle_textures(); - void load_grass_textures(); - void load_board_border_texture(); - void load_red_units_textures(); - void load_blue_units_textures(); - void load_highlight_textures(); - void load_font(); - void set_obstacle_sprites(); - void set_red_units_sprites(); - void set_blue_units_sprites(); - void set_highlight_sprites(); - - sf::Vector2f return_pixels(int col, int row) const; - Tile return_tile(const sf::Vector2f& coords) const; - Tile return_tile(int x, int y) const; - - bool check_if_viable(Tile from, int to_x, int to_y); - void highlight_regular_moves(sf::RenderWindow& win, const Tile& active_unit); - void highlight_scout_moves(sf::RenderWindow& win, const Tile& active_unit); - bool highlight_tile(sf::RenderWindow& win, const Tile& active_unit, int to_x, int to_y); - void draw_red_init_units(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data); - void draw_blue_init_units(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data); + Player &playerA; + Player &playerB; + Player *current_player; + Player *other_player; + Turn current_player_turn; + + const std::string board_textures_path; + const std::string pieces_textures_path; + + int TILE_SIZE; + int X_ADDITIONAL_SPACE; + sf::Vector2f window_size; + sf::Vector2f sprite_initial_position; + + bool clock_started; + + sf::Sprite board_border; + sf::Sprite grass_light; + sf::Sprite grass_dark; + std::array obstacle_sprites; + std::array red_units_sprites; + sf::Sprite red_back_sprite; + std::array blue_units_sprites; + sf::Sprite blue_back_sprite; + sf::Sprite yellow_highlight_sprite; + sf::Sprite white_highlight_sprite; + sf::Sprite green_highlight_sprite; + sf::Sprite red_highlight_sprite; + + sf::Texture board_border_texture; + sf::Texture grass_light_texture; + sf::Texture grass_dark_texture; + std::array obstacle_textures; + std::array red_unit_textures; + sf::Texture red_back_texture; + std::array blue_unit_textures; + sf::Texture blue_back_texture; + sf::Texture yellow_highlight_texture; + sf::Texture white_highlight_texture; + sf::Texture green_highlight_texture; + sf::Texture red_highlight_texture; + + sf::Clock clock; + sf::Font font; + sf::Text text; + Button done_button; + Button randomize_button; + Button remove_button; + Button end_turn_button; + Box info_box; + AttackInfoBox attack_info_box; + Box end_game_info_box; + + void load_obstacle_textures(); + void load_grass_textures(); + void load_board_border_texture(); + void load_red_units_textures(); + void load_blue_units_textures(); + void load_highlight_textures(); + void load_font(); + void set_obstacle_sprites(); + void set_red_units_sprites(); + void set_blue_units_sprites(); + void set_highlight_sprites(); + + sf::Vector2f return_pixels(int col, int row) const; + Tile return_tile(const sf::Vector2f &coords) const; + Tile return_tile(int x, int y) const; + + bool check_if_viable(Tile from, int to_x, int to_y); + void highlight_regular_moves(sf::RenderWindow &win, const Tile &active_unit); + void highlight_scout_moves(sf::RenderWindow &win, const Tile &active_unit); + bool highlight_tile(sf::RenderWindow &win, const Tile &active_unit, int to_x, + int to_y); + void draw_red_init_units(sf::RenderWindow &win, bool is_dragging, + int selected_unit_idx, const mouse_data &m_data); + void draw_blue_init_units(sf::RenderWindow &win, bool is_dragging, + int selected_unit_idx, const mouse_data &m_data); public: - GameView(Player& pA, Player& pB); - void update_players(Player* current, Player* other); - void set_button_highlights(int mouse_x, int mouse_y); - - sf::Vector2f get_window_size() { return window_size; }; - const std::array& get_red_units_sprites() const { return red_units_sprites; }; - const std::array& get_blue_units_sprites() const { return blue_units_sprites; }; - const Button& get_done_button() const { return done_button; }; - const Button& get_randomize_button() const { return randomize_button; }; - const Button& get_remove_button() const { return remove_button; }; - const Button& get_end_turn_button() const { return end_turn_button; }; - const Box& get_info_box() const { return info_box; }; - const Box& get_end_game_info_box() const { return end_game_info_box; }; - const AttackInfoBox& get_attack_info_box() const { return attack_info_box; }; - - void draw_board_border(sf::RenderWindow& win); - void draw_grass(sf::RenderWindow& win); - void draw_obstacles(sf::RenderWindow& win); - void draw_units_for_init(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data); - void draw_sprite(sf::RenderWindow& win, int idx, int sprite_pos_x, int sprite_pos_y); - void draw_done_button(sf::RenderWindow& win); - void draw_randomize_button(sf::RenderWindow& win); - void draw_remove_button(sf::RenderWindow& win); - void draw_end_turn_button(sf::RenderWindow& win); - void draw_possible_moves_for_active_unit(sf::RenderWindow& win, const Tile& active_unit); - void draw_info_box(sf::RenderWindow& win); - void draw_attack_info_box(sf::RenderWindow& win, const std::optional& attacker, const std::optional& attacked); - void draw_units(sf::RenderWindow& win); - void draw_unit_highlight(sf::RenderWindow& win, const Tile& active_unit); - void draw_end_game_screen(sf::RenderWindow& win, const std::string& victorious_name); + GameView(Player &pA, Player &pB); + void update_players(Player *current, Player *other); + void set_button_highlights(int mouse_x, int mouse_y); + + sf::Vector2f get_window_size() { return window_size; }; + const std::array &get_red_units_sprites() const { + return red_units_sprites; + }; + const std::array &get_blue_units_sprites() const { + return blue_units_sprites; + }; + const Button &get_done_button() const { return done_button; }; + const Button &get_randomize_button() const { return randomize_button; }; + const Button &get_remove_button() const { return remove_button; }; + const Button &get_end_turn_button() const { return end_turn_button; }; + const Box &get_info_box() const { return info_box; }; + const Box &get_end_game_info_box() const { return end_game_info_box; }; + const AttackInfoBox &get_attack_info_box() const { return attack_info_box; }; + + void draw_board_border(sf::RenderWindow &win); + void draw_grass(sf::RenderWindow &win); + void draw_obstacles(sf::RenderWindow &win); + void draw_units_for_init(sf::RenderWindow &win, bool is_dragging, + int selected_unit_idx, const mouse_data &m_data); + void draw_sprite(sf::RenderWindow &win, int idx, int sprite_pos_x, + int sprite_pos_y); + void draw_done_button(sf::RenderWindow &win); + void draw_randomize_button(sf::RenderWindow &win); + void draw_remove_button(sf::RenderWindow &win); + void draw_end_turn_button(sf::RenderWindow &win); + void draw_possible_moves_for_active_unit(sf::RenderWindow &win, + const Tile &active_unit); + void draw_info_box(sf::RenderWindow &win); + void draw_attack_info_box(sf::RenderWindow &win, + const std::optional &attacker, + const std::optional &attacked); + void draw_units(sf::RenderWindow &win); + void draw_unit_highlight(sf::RenderWindow &win, const Tile &active_unit); + void draw_end_game_screen(sf::RenderWindow &win, + const std::string &victorious_name); }; \ No newline at end of file diff --git a/include/MainMenu.hpp b/include/MainMenu.hpp index 1ff7d46..a20c6c8 100644 --- a/include/MainMenu.hpp +++ b/include/MainMenu.hpp @@ -2,50 +2,48 @@ #include "BigButton.hpp" #include "Button.hpp" -#include "cScreen.hpp" -#include "Player.hpp" #include "Game.hpp" +#include "Player.hpp" +#include "cScreen.hpp" -class MainMenu : public cScreen -{ - Player& playerA; - Player& playerB; - BigButton start_game_button; - BigButton game_rules_button; - BigButton exit_button; - Button next; - Button prev; - Box player_1_name; - Box player_2_name; - bool names_entered; - bool game_started_button_pressed; - bool rules_button_pressed; - bool exit_button_pressed; - bool next_button_pressed; - bool prev_button_pressed; - bool player_1_name_approved; - bool player_2_name_approved; - bool entering_from_menu; - std::string nickname; - sf::String nickname_drawn; - const std::string path_to_textures; - int idx; - - std::array rules_textures; - sf::Texture logo_texture; - std::array rules_sprites; - sf::Sprite logo_sprite; +class MainMenu : public cScreen { + Player &playerA; + Player &playerB; + BigButton start_game_button; + BigButton game_rules_button; + BigButton exit_button; + Button next; + Button prev; + Box player_1_name; + Box player_2_name; + bool names_entered; + bool game_started_button_pressed; + bool rules_button_pressed; + bool exit_button_pressed; + bool next_button_pressed; + bool prev_button_pressed; + bool player_1_name_approved; + bool player_2_name_approved; + bool entering_from_menu; + std::string nickname; + sf::String nickname_drawn; + const std::string path_to_textures; + int idx; - void draw_menu(sf::RenderWindow& win); - void draw_names(sf::RenderWindow& win); - void draw_rules(sf::RenderWindow& win); - void draw_rule(sf::RenderWindow& win, int idx); - void highlight_buttons(int mouse_x, int mouse_y); - void enter_names(sf::Event& event); - void set_buttons_pressed(); + std::array rules_textures; + sf::Texture logo_texture; + std::array rules_sprites; + sf::Sprite logo_sprite; - public: - MainMenu(Player& pA, Player& pB); - std::string run(sf::RenderWindow& win) override; + void draw_menu(sf::RenderWindow &win); + void draw_names(sf::RenderWindow &win); + void draw_rules(sf::RenderWindow &win); + void draw_rule(sf::RenderWindow &win, int idx); + void highlight_buttons(int mouse_x, int mouse_y); + void enter_names(sf::Event &event); + void set_buttons_pressed(); +public: + MainMenu(Player &pA, Player &pB); + std::string run(sf::RenderWindow &win) override; }; \ No newline at end of file diff --git a/include/Player.hpp b/include/Player.hpp index 9a56d04..d6fa47c 100644 --- a/include/Player.hpp +++ b/include/Player.hpp @@ -6,28 +6,27 @@ #include "unit/visit/Attack.hpp" enum class Turn; -class Player -{ - std::string name; - Turn player; - Board board; - - public: - Player(std::string n, Turn p): name(n), player(p), board() { }; - int get_units_count(int idx); - Turn get_player_number() { return player; }; - std::string get_player_name() { return name; }; - void set_unit(int col, int row, int choice); - void remove_unit(int col, int row); - void remove_unit(Tile chosen_unit); - void reverse_remove_unit(Tile unit); - bool move_unit(Tile from, Tile to); - attack::Result attack(Tile attacker, Tile attacked); - void reverse_move_unit(Tile from, Tile to); - void update_board(const Board& other_player_board); - const Board& get_board() { return board; }; - std::string get_tile_info(int col, int row) const; - std::string get_tile_info(Tile tile) const; - bool can_move(Tile from, Tile to); - void set_name(const std::string& n) { name = n; }; +class Player { + std::string name; + Turn player; + Board board; + +public: + Player(std::string n, Turn p) : name(n), player(p), board() {}; + int get_units_count(int idx); + Turn get_player_number() { return player; }; + std::string get_player_name() { return name; }; + void set_unit(int col, int row, int choice); + void remove_unit(int col, int row); + void remove_unit(Tile chosen_unit); + void reverse_remove_unit(Tile unit); + bool move_unit(Tile from, Tile to); + attack::Result attack(Tile attacker, Tile attacked); + void reverse_move_unit(Tile from, Tile to); + void update_board(const Board &other_player_board); + const Board &get_board() { return board; }; + std::string get_tile_info(int col, int row) const; + std::string get_tile_info(Tile tile) const; + bool can_move(Tile from, Tile to); + void set_name(const std::string &n) { name = n; }; }; \ No newline at end of file diff --git a/include/Tile.hpp b/include/Tile.hpp index edb770a..678f571 100644 --- a/include/Tile.hpp +++ b/include/Tile.hpp @@ -1,24 +1,20 @@ -#pragma once +#pragma once -class Tile -{ +class Tile { public: - int x{}; - int y{}; - explicit Tile(int col = 0, int row = 0) - { - x = col; - y = row; - }; - bool operator==(const Tile &rhs) const { return x == rhs.x && y == rhs.y; }; - void set_cords(const Tile &rhs) - { - x = rhs.x; - y = rhs.y; - }; - void set_cords(int Ax, int Ay) - { - x = Ax; - y = Ay; - }; + int x{}; + int y{}; + explicit Tile(int col = 0, int row = 0) { + x = col; + y = row; + }; + bool operator==(const Tile &rhs) const { return x == rhs.x && y == rhs.y; }; + void set_cords(const Tile &rhs) { + x = rhs.x; + y = rhs.y; + }; + void set_cords(int Ax, int Ay) { + x = Ax; + y = Ay; + }; }; \ No newline at end of file diff --git a/include/Turn.hpp b/include/Turn.hpp index f4f47d1..0c63f53 100644 --- a/include/Turn.hpp +++ b/include/Turn.hpp @@ -1,6 +1,3 @@ -#pragma once +#pragma once -enum class Turn { - PlayerA, - PlayerB -}; \ No newline at end of file +enum class Turn { PlayerA, PlayerB }; \ No newline at end of file diff --git a/include/cScreen.hpp b/include/cScreen.hpp index ca6829d..67aa50c 100644 --- a/include/cScreen.hpp +++ b/include/cScreen.hpp @@ -3,8 +3,7 @@ #include #include -class cScreen -{ - public: - virtual std::string run(sf::RenderWindow& win) = 0; +class cScreen { +public: + virtual std::string run(sf::RenderWindow &win) = 0; }; \ No newline at end of file diff --git a/include/unit/BombUnit.hpp b/include/unit/BombUnit.hpp index 99ac5be..d976e7c 100644 --- a/include/unit/BombUnit.hpp +++ b/include/unit/BombUnit.hpp @@ -1,7 +1,7 @@ #pragma once -#include "unit/UnitModel.hpp" #include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" namespace details { constexpr const int maxBombCount{6}; @@ -9,13 +9,21 @@ constexpr const int maxBombCount{6}; enum class Turn; class BombUnit { - UnitModel model_; - UnitCounter counter_; + UnitModel model_; + UnitCounter counter_; + public: - explicit BombUnit(Turn player); - int get_value() const noexcept { return model_.get_value(); } - [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } - Turn get_owner() const noexcept { return model_.get_owner(); } - static int get_count() { return UnitCounter::get_count(); } - static int get_max_count() { return UnitCounter::get_max_count(); } + explicit BombUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { + return UnitCounter::get_count(); + } + static int get_max_count() { + return UnitCounter::get_max_count(); + } }; diff --git a/include/unit/FlagUnit.hpp b/include/unit/FlagUnit.hpp index b6bb9e7..d59f4e2 100644 --- a/include/unit/FlagUnit.hpp +++ b/include/unit/FlagUnit.hpp @@ -1,22 +1,29 @@ #pragma once -#include "unit/UnitModel.hpp" #include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" namespace details { constexpr const int maxFlagCount{1}; } enum class Turn; -class FlagUnit -{ - UnitModel model_; - UnitCounter counter_; +class FlagUnit { + UnitModel model_; + UnitCounter counter_; + public: - explicit FlagUnit(Turn player); - int get_value() const noexcept { return model_.get_value(); } - [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } - Turn get_owner() const noexcept { return model_.get_owner(); } - static int get_count() { return UnitCounter::get_count(); } - static int get_max_count() { return UnitCounter::get_max_count(); } + explicit FlagUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { + return UnitCounter::get_count(); + } + static int get_max_count() { + return UnitCounter::get_max_count(); + } }; \ No newline at end of file diff --git a/include/unit/MinerUnit.hpp b/include/unit/MinerUnit.hpp index 6471915..96af010 100644 --- a/include/unit/MinerUnit.hpp +++ b/include/unit/MinerUnit.hpp @@ -1,23 +1,29 @@ #pragma once -#include "unit/UnitModel.hpp" #include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" namespace details { constexpr const int maxMinerCount{4}; } - enum class Turn; -class MinerUnit -{ - UnitModel model_; - UnitCounter counter_; +class MinerUnit { + UnitModel model_; + UnitCounter counter_; + public: - explicit MinerUnit(Turn player); - int get_value() const noexcept { return model_.get_value(); } - [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } - Turn get_owner() const noexcept { return model_.get_owner(); } - static int get_count() { return UnitCounter::get_count(); } - static int get_max_count() { return UnitCounter::get_max_count(); } + explicit MinerUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { + return UnitCounter::get_count(); + } + static int get_max_count() { + return UnitCounter::get_max_count(); + } }; diff --git a/include/unit/RegularUnit.hpp b/include/unit/RegularUnit.hpp index e8c3c01..d904c09 100644 --- a/include/unit/RegularUnit.hpp +++ b/include/unit/RegularUnit.hpp @@ -1,18 +1,24 @@ #pragma once -#include "unit/UnitModel.hpp" #include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" enum class Turn; class RegularUnit { - UnitModel model_; - RegularUnitCounter counter_; + UnitModel model_; + RegularUnitCounter counter_; + public: - explicit RegularUnit(int value, Turn player); - int get_value() const noexcept { return model_.get_value(); } - [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } - Turn get_owner() const noexcept { return model_.get_owner(); } - static int get_count(int value) { RegularUnitCounter::get_count(value); } - static int get_max_count(int value) { RegularUnitCounter::get_max_count(value); } + explicit RegularUnit(int value, Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count(int value) { RegularUnitCounter::get_count(value); } + static int get_max_count(int value) { + RegularUnitCounter::get_max_count(value); + } }; diff --git a/include/unit/ScoutUnit.hpp b/include/unit/ScoutUnit.hpp index b68d0f0..eccd105 100644 --- a/include/unit/ScoutUnit.hpp +++ b/include/unit/ScoutUnit.hpp @@ -1,22 +1,29 @@ #pragma once -#include "unit/UnitModel.hpp" #include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" namespace details { constexpr const int maxScoutCount{8}; } enum class Turn; -class ScoutUnit -{ - UnitModel model_; - UnitCounter counter_; +class ScoutUnit { + UnitModel model_; + UnitCounter counter_; + public: - explicit ScoutUnit(Turn player); - int get_value() const noexcept { return model_.get_value(); } - [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } - Turn get_owner() const noexcept { return model_.get_owner(); } - static int get_count() { return UnitCounter::get_count(); } - static int get_max_count() { return UnitCounter::get_max_count(); } + explicit ScoutUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { + return UnitCounter::get_count(); + } + static int get_max_count() { + return UnitCounter::get_max_count(); + } }; \ No newline at end of file diff --git a/include/unit/SpyUnit.hpp b/include/unit/SpyUnit.hpp index 124d87c..9f8ffe4 100644 --- a/include/unit/SpyUnit.hpp +++ b/include/unit/SpyUnit.hpp @@ -1,7 +1,7 @@ #pragma once -#include "unit/UnitModel.hpp" #include "unit/UnitCounter.hpp" +#include "unit/UnitModel.hpp" namespace details { constexpr const int maxSpyCount{1}; @@ -10,13 +10,21 @@ constexpr const int maxSpyCount{1}; enum class Turn; class SpyUnit { - UnitModel model_; - UnitCounter counter_; + UnitModel model_; + UnitCounter counter_; + public: - explicit SpyUnit(Turn player); - int get_value() const noexcept { return model_.get_value(); } - [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept { return model_.get_type(); } - Turn get_owner() const noexcept { return model_.get_owner(); } - static int get_count() { return UnitCounter::get_count(); } - static int get_max_count() { return UnitCounter::get_max_count(); } + explicit SpyUnit(Turn player); + int get_value() const noexcept { return model_.get_value(); } + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept { + return model_.get_type(); + } + Turn get_owner() const noexcept { return model_.get_owner(); } + static int get_count() { + return UnitCounter::get_count(); + } + static int get_max_count() { + return UnitCounter::get_max_count(); + } }; diff --git a/include/unit/Unit.hpp b/include/unit/Unit.hpp index 503c850..68abc67 100644 --- a/include/unit/Unit.hpp +++ b/include/unit/Unit.hpp @@ -9,7 +9,9 @@ #include "unit/ScoutUnit.hpp" #include "unit/SpyUnit.hpp" -using Unit = std::variant; +using Unit = std::variant; -template -struct overloads : Ts... { using Ts::operator()...; }; \ No newline at end of file +template struct overloads : Ts... { + using Ts::operator()...; +}; \ No newline at end of file diff --git a/include/unit/UnitConcepts.hpp b/include/unit/UnitConcepts.hpp index cd12bbf..74c56ee 100644 --- a/include/unit/UnitConcepts.hpp +++ b/include/unit/UnitConcepts.hpp @@ -1,17 +1,17 @@ -#pragma once - -#include "Turn.hpp" +#pragma once #include +#include "Turn.hpp" + namespace unit { template concept Attackable = requires(UnitType unit) { - {unit.get_value()} -> std::same_as; + { unit.get_value() } -> std::same_as; }; template -concept Owned = requires(const UnitType& unit) { - {unit.get_owner()} -> std::same_as; +concept Owned = requires(const UnitType &unit) { + { unit.get_owner() } -> std::same_as; }; -} \ No newline at end of file +} // namespace unit \ No newline at end of file diff --git a/include/unit/UnitCounter.hpp b/include/unit/UnitCounter.hpp index da920ca..d437afb 100644 --- a/include/unit/UnitCounter.hpp +++ b/include/unit/UnitCounter.hpp @@ -1,21 +1,25 @@ -#pragma once +#pragma once #include -template -class UnitCounter { +template class UnitCounter { private: - static int count_; + static int count_; + public: - UnitCounter() { ++count_; } - UnitCounter(const UnitCounter&) : UnitCounter() {} - UnitCounter(UnitCounter&&) {} - UnitCounter& operator=(const UnitCounter& rhs) { if (this != &rhs) ++count_; return *this; }; - UnitCounter& operator=(UnitCounter&&) { return *this; } - ~UnitCounter() { --count_; } - - static int get_count() { return count_; } - static int get_max_count() { return MaxCount; } + UnitCounter() { ++count_; } + UnitCounter(const UnitCounter &) : UnitCounter() {} + UnitCounter(UnitCounter &&) {} + UnitCounter &operator=(const UnitCounter &rhs) { + if (this != &rhs) + ++count_; + return *this; + }; + UnitCounter &operator=(UnitCounter &&) { return *this; } + ~UnitCounter() { --count_; } + + static int get_count() { return count_; } + static int get_max_count() { return MaxCount; } }; template @@ -23,16 +27,17 @@ int UnitCounter::count_ = 0; class RegularUnitCounter { private: - static std::unordered_map count_; - int unit_value_{0}; + static std::unordered_map count_; + int unit_value_{0}; + public: - explicit RegularUnitCounter(const int unit_value); - RegularUnitCounter(const RegularUnitCounter&); - RegularUnitCounter(RegularUnitCounter&&); - RegularUnitCounter& operator=(const RegularUnitCounter&); - RegularUnitCounter& operator=(RegularUnitCounter&&); - ~RegularUnitCounter(); - - static int get_count(int unit_value); - static int get_max_count(int unit_value); + explicit RegularUnitCounter(const int unit_value); + RegularUnitCounter(const RegularUnitCounter &); + RegularUnitCounter(RegularUnitCounter &&); + RegularUnitCounter &operator=(const RegularUnitCounter &); + RegularUnitCounter &operator=(RegularUnitCounter &&); + ~RegularUnitCounter(); + + static int get_count(int unit_value); + static int get_max_count(int unit_value); }; \ No newline at end of file diff --git a/include/unit/UnitModel.hpp b/include/unit/UnitModel.hpp index 35d708d..f7b6acb 100644 --- a/include/unit/UnitModel.hpp +++ b/include/unit/UnitModel.hpp @@ -2,21 +2,22 @@ #include #include + #include "Tile.hpp" enum class Turn; -class UnitModel -{ +class UnitModel { private: - int value_{}; - [[deprecated]] std::string type_{}; - Turn owner_{}; + int value_{}; + [[deprecated]] std::string type_{}; + Turn owner_{}; public: - static constexpr int MARSHAL_VALUE{10}; - UnitModel(int value, std::string type, Turn player); - int get_value() const noexcept; - [[deprecated("Future refactoring will remove get_type()")]] std::string get_type() const noexcept; - Turn get_owner() const noexcept; + static constexpr int MARSHAL_VALUE{10}; + UnitModel(int value, std::string type, Turn player); + int get_value() const noexcept; + [[deprecated("Future refactoring will remove get_type()")]] std::string + get_type() const noexcept; + Turn get_owner() const noexcept; }; diff --git a/include/unit/visit/Attack.hpp b/include/unit/visit/Attack.hpp index 3c91110..5c02ba6 100644 --- a/include/unit/visit/Attack.hpp +++ b/include/unit/visit/Attack.hpp @@ -1,62 +1,61 @@ -#pragma once +#pragma once +#include #include #include -#include #include "Tile.hpp" #include "unit/Unit.hpp" #include "unit/UnitConcepts.hpp" namespace attack { -enum class Result -{ - Lost, - Draw, - Won, +enum class Result { + Lost, + Draw, + Won, }; class InvalidUnitError : public std::exception { - public: - const char* what() const noexcept override { return "Invalid unit attacked or was being attacked\n"; } +public: + const char *what() const noexcept override { + return "Invalid unit attacked or was being attacked\n"; + } }; } // namespace attack - class Attack { - template - attack::Result regular_attack(const T& lhs, const U& rhs) { - if (lhs.get_value() > rhs.get_value()) - { - return attack::Result::Won; - } - if (lhs.get_value() == rhs.get_value()) - { - return attack::Result::Draw; - } - return attack::Result::Lost; - } -public: - attack::Result operator()(const SpyUnit&, const RegularUnit& rhs) { - if (rhs.get_value() == UnitModel::MARSHAL_VALUE) { - return attack::Result::Won; - } - return attack::Result::Lost; - } - attack::Result operator()(const MinerUnit&, const BombUnit&) { - return attack::Result::Won; - } - template - attack::Result operator()(const T&, const BombUnit&) { - return attack::Result::Lost; + template + attack::Result regular_attack(const T &lhs, const U &rhs) { + if (lhs.get_value() > rhs.get_value()) { + return attack::Result::Won; } - template - attack::Result operator()(const T& lhs, const U& rhs) { - return regular_attack(lhs, rhs); + if (lhs.get_value() == rhs.get_value()) { + return attack::Result::Draw; } - template - attack::Result operator()(const T& lhs, const U& rhs) { - throw attack::InvalidUnitError(); + return attack::Result::Lost; + } + +public: + attack::Result operator()(const SpyUnit &, const RegularUnit &rhs) { + if (rhs.get_value() == UnitModel::MARSHAL_VALUE) { + return attack::Result::Won; } + return attack::Result::Lost; + } + attack::Result operator()(const MinerUnit &, const BombUnit &) { + return attack::Result::Won; + } + template + attack::Result operator()(const T &, const BombUnit &) { + return attack::Result::Lost; + } + template + attack::Result operator()(const T &lhs, const U &rhs) { + return regular_attack(lhs, rhs); + } + template + attack::Result operator()(const T &lhs, const U &rhs) { + throw attack::InvalidUnitError(); + } }; \ No newline at end of file diff --git a/include/unit/visit/CanMove.hpp b/include/unit/visit/CanMove.hpp index 1b9a281..d482810 100644 --- a/include/unit/visit/CanMove.hpp +++ b/include/unit/visit/CanMove.hpp @@ -1,68 +1,50 @@ -#pragma once +#pragma once +#include #include #include -#include #include "Tile.hpp" #include "unit/Unit.hpp" class CanMove { private: - Tile from_{}; - Tile to_{}; - - bool regularMove() const { - if (from_.x + 1 == to_.x && from_.y == to_.y) - { - return true; - } - if (from_.x - 1 == to_.x && from_.y == to_.y) - { - return true; - } - if (from_.x == to_.x && from_.y + 1 == to_.y) - { - return true; - } - if (from_.x == to_.x && from_.y - 1 == to_.y) - { - return true; - } - return false; - } - - bool scoutMove() const { - if (from_.x == to_.x) - { - return true; - } - if (from_.y == to_.y) - { - return true; - } - return false; - } + Tile from_{}; + Tile to_{}; -public: - CanMove(Tile from, Tile to) : from_(from), to_(to) {} - - bool operator()(const ScoutUnit&) { - return scoutMove(); + bool regularMove() const { + if (from_.x + 1 == to_.x && from_.y == to_.y) { + return true; } - bool operator()(const MinerUnit&) { - return regularMove(); + if (from_.x - 1 == to_.x && from_.y == to_.y) { + return true; } - bool operator()(const RegularUnit&) { - return regularMove(); + if (from_.x == to_.x && from_.y + 1 == to_.y) { + return true; } - bool operator()(const SpyUnit&) { - return regularMove(); + if (from_.x == to_.x && from_.y - 1 == to_.y) { + return true; } - bool operator()(const FlagUnit&) { - return false; + return false; + } + + bool scoutMove() const { + if (from_.x == to_.x) { + return true; } - bool operator()(const BombUnit&) { - return false; + if (from_.y == to_.y) { + return true; } + return false; + } + +public: + CanMove(Tile from, Tile to) : from_(from), to_(to) {} + + bool operator()(const ScoutUnit &) { return scoutMove(); } + bool operator()(const MinerUnit &) { return regularMove(); } + bool operator()(const RegularUnit &) { return regularMove(); } + bool operator()(const SpyUnit &) { return regularMove(); } + bool operator()(const FlagUnit &) { return false; } + bool operator()(const BombUnit &) { return false; } }; \ No newline at end of file diff --git a/include/unit/visit/GetOwner.hpp b/include/unit/visit/GetOwner.hpp index 85e2916..83f7829 100644 --- a/include/unit/visit/GetOwner.hpp +++ b/include/unit/visit/GetOwner.hpp @@ -1,12 +1,11 @@ -#pragma once +#pragma once #include "unit/UnitConcepts.hpp" enum class Turn; class GetOwner { public: - template - Turn operator()(const T& unit) { - return unit.get_owner(); - } + template Turn operator()(const T &unit) { + return unit.get_owner(); + } }; \ No newline at end of file diff --git a/include/unit/visit/GetTileInfo.hpp b/include/unit/visit/GetTileInfo.hpp index c322dfc..6bb9aa0 100644 --- a/include/unit/visit/GetTileInfo.hpp +++ b/include/unit/visit/GetTileInfo.hpp @@ -1,24 +1,23 @@ -#pragma once +#pragma once -#include #include +#include #include "Turn.hpp" #include "unit/UnitConcepts.hpp" class GetTileInfo { private: - Turn player_; + Turn player_; public: - explicit GetTileInfo(Turn player) : player_(player) {} + explicit GetTileInfo(Turn player) : player_(player) {} - template - std::string operator()(const UnitType& unit) { - if (unit.get_owner() != player_) { - return "enemy"; - } else { - return unit.get_type(); - } + template std::string operator()(const UnitType &unit) { + if (unit.get_owner() != player_) { + return "enemy"; + } else { + return unit.get_type(); } + } }; \ No newline at end of file diff --git a/include/unit/visit/GetUnitSpriteId.hpp b/include/unit/visit/GetUnitSpriteId.hpp index 407f8b0..870b140 100644 --- a/include/unit/visit/GetUnitSpriteId.hpp +++ b/include/unit/visit/GetUnitSpriteId.hpp @@ -1,26 +1,13 @@ -#pragma once - +#pragma once #include "unit/Unit.hpp" class GetUnitSpriteId { public: - int operator()(const RegularUnit& unit) { - return unit.get_value() - 2; - } - int operator()(const ScoutUnit&) { - return 0; - } - int operator()(const MinerUnit&) { - return 1; - } - int operator()(const BombUnit&) { - return 9; - } - int operator()(const FlagUnit&) { - return 10; - } - int operator()(const SpyUnit&) { - return 11; - } + int operator()(const RegularUnit &unit) { return unit.get_value() - 2; } + int operator()(const ScoutUnit &) { return 0; } + int operator()(const MinerUnit &) { return 1; } + int operator()(const BombUnit &) { return 9; } + int operator()(const FlagUnit &) { return 10; } + int operator()(const SpyUnit &) { return 11; } }; \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..1a90aa8 --- /dev/null +++ b/requirements.txt @@ -0,0 +1 @@ +clang-format==20.1.0 diff --git a/src/AttackInfoBox.cpp b/src/AttackInfoBox.cpp index 57a1dcf..d5f002b 100644 --- a/src/AttackInfoBox.cpp +++ b/src/AttackInfoBox.cpp @@ -7,176 +7,149 @@ #include "unit/visit/GetOwner.hpp" #include "unit/visit/GetUnitSpriteId.hpp" -AttackInfoBox::AttackInfoBox(std::array &red_units_sprites, std::array &blue_units_sprites, sf::Sprite &winning_unit_highlight) - : path_to_textures("images/board/"), - attacking_unit_pos_x(-1), - attacking_unit_pos_y(-1), - attacked_unit_pos_x(-1), - attacked_unit_pos_y(-1), - attacking_unit{}, - attacked_unit{}, - attacker_ptr{}, - attacked_ptr{}, - winner_highlight(winning_unit_highlight) -{ - for (int i = 0; i < red_units_sprites_ptrs.size(); ++i) - { - red_units_sprites_ptrs[i] = &red_units_sprites[i]; - } - for (int i = 0; i < blue_units_sprites_ptrs.size(); ++i) - { - blue_units_sprites_ptrs[i] = &blue_units_sprites[i]; - } - load_box_texture(); - load_font(); - box_text.setFont(box_font); - box_text.setString("VS"); - box_text.setFillColor(sf::Color::Yellow); - box_text.setCharacterSize(40); - box_sprite.setTexture(box_texture); +AttackInfoBox::AttackInfoBox(std::array &red_units_sprites, + std::array &blue_units_sprites, + sf::Sprite &winning_unit_highlight) + : path_to_textures("images/board/"), attacking_unit_pos_x(-1), + attacking_unit_pos_y(-1), attacked_unit_pos_x(-1), + attacked_unit_pos_y(-1), attacking_unit{}, attacked_unit{}, + attacker_ptr{}, attacked_ptr{}, winner_highlight(winning_unit_highlight) { + for (int i = 0; i < red_units_sprites_ptrs.size(); ++i) { + red_units_sprites_ptrs[i] = &red_units_sprites[i]; + } + for (int i = 0; i < blue_units_sprites_ptrs.size(); ++i) { + blue_units_sprites_ptrs[i] = &blue_units_sprites[i]; + } + load_box_texture(); + load_font(); + box_text.setFont(box_font); + box_text.setString("VS"); + box_text.setFillColor(sf::Color::Yellow); + box_text.setCharacterSize(40); + box_sprite.setTexture(box_texture); } -void AttackInfoBox::draw(sf::RenderWindow &win) -{ - update_attacked_unit_pos(); - update_attacking_unit_pos(); - update_box_text_pos(); - set_winner_highlight(); - win.draw(box_sprite); - win.draw(attacking_unit); - win.draw(box_text); - win.draw(attacked_unit); - draw_winner_highlight(win); +void AttackInfoBox::draw(sf::RenderWindow &win) { + update_attacked_unit_pos(); + update_attacking_unit_pos(); + update_box_text_pos(); + set_winner_highlight(); + win.draw(box_sprite); + win.draw(attacking_unit); + win.draw(box_text); + win.draw(attacked_unit); + draw_winner_highlight(win); } -void AttackInfoBox::load_box_texture() -{ - if (!box_texture.loadFromFile(path_to_textures + "attack_info_box.png")) - { - std::cerr << "attack info box texture failed to load!\n"; - abort(); - } +void AttackInfoBox::load_box_texture() { + if (!box_texture.loadFromFile(path_to_textures + "attack_info_box.png")) { + std::cerr << "attack info box texture failed to load!\n"; + abort(); + } } -void AttackInfoBox::load_font() -{ - if (!box_font.loadFromFile("font/lunchds.ttf")) - { - std::cerr << "failed to load attack info box font!\n"; - abort(); - } +void AttackInfoBox::load_font() { + if (!box_font.loadFromFile("font/lunchds.ttf")) { + std::cerr << "failed to load attack info box font!\n"; + abort(); + } } -int AttackInfoBox::get_unit_sprite_idx(const Unit &unit) -{ - return std::visit(GetUnitSpriteId{}, unit); +int AttackInfoBox::get_unit_sprite_idx(const Unit &unit) { + return std::visit(GetUnitSpriteId{}, unit); } -void AttackInfoBox::set_position(int x, int y) -{ - box_sprite.setPosition(x, y); - update_attacking_unit_pos(); - update_attacked_unit_pos(); - update_box_text_pos(); - set_winner_highlight(); +void AttackInfoBox::set_position(int x, int y) { + box_sprite.setPosition(x, y); + update_attacking_unit_pos(); + update_attacked_unit_pos(); + update_box_text_pos(); + set_winner_highlight(); } -void AttackInfoBox::set_attacking_unit(const std::optional &attacker) -{ - if (!attacker) { - return; - } - const auto attackerUnit = attacker.value(); - if (std::visit(GetOwner{}, attackerUnit) == Turn::PlayerA) - { - attacking_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(attackerUnit)]; - } - else - { - attacking_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(attackerUnit)]; - } - attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); - attacking_unit.scale(1.5, 1.5); - attacker_ptr = &attackerUnit; +void AttackInfoBox::set_attacking_unit(const std::optional &attacker) { + if (!attacker) { + return; + } + const auto attackerUnit = attacker.value(); + if (std::visit(GetOwner{}, attackerUnit) == Turn::PlayerA) { + attacking_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(attackerUnit)]; + } else { + attacking_unit = + *blue_units_sprites_ptrs[get_unit_sprite_idx(attackerUnit)]; + } + attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); + attacking_unit.scale(1.5, 1.5); + attacker_ptr = &attackerUnit; } -void AttackInfoBox::set_attacked_unit(const std::optional &victim) -{ - if (!victim) { - return; - } - const auto victimUnit = victim.value(); - if (std::visit(GetOwner{}, victimUnit) == Turn::PlayerA) - { - attacked_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(victimUnit)]; - } - else - { - attacked_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(victimUnit)]; - } - attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); - attacked_unit.scale(1.5, 1.5); - attacked_ptr = &victimUnit; +void AttackInfoBox::set_attacked_unit(const std::optional &victim) { + if (!victim) { + return; + } + const auto victimUnit = victim.value(); + if (std::visit(GetOwner{}, victimUnit) == Turn::PlayerA) { + attacked_unit = *red_units_sprites_ptrs[get_unit_sprite_idx(victimUnit)]; + } else { + attacked_unit = *blue_units_sprites_ptrs[get_unit_sprite_idx(victimUnit)]; + } + attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); + attacked_unit.scale(1.5, 1.5); + attacked_ptr = &victimUnit; } -void AttackInfoBox::update_attacking_unit_pos() -{ - attacking_unit_pos_x = box_sprite.getPosition().x + (get_width() / 4); - attacking_unit_pos_y = box_sprite.getPosition().y + ((get_height() - attacking_unit.getGlobalBounds().height) / 2); - attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); +void AttackInfoBox::update_attacking_unit_pos() { + attacking_unit_pos_x = box_sprite.getPosition().x + (get_width() / 4); + attacking_unit_pos_y = + box_sprite.getPosition().y + + ((get_height() - attacking_unit.getGlobalBounds().height) / 2); + attacking_unit.setPosition(attacking_unit_pos_x, attacking_unit_pos_y); } -void AttackInfoBox::update_attacked_unit_pos() -{ - attacked_unit_pos_x = box_sprite.getPosition().x + get_width() * 3 / 4 - attacked_unit.getGlobalBounds().width; - attacked_unit_pos_y = attacking_unit_pos_y; - attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); +void AttackInfoBox::update_attacked_unit_pos() { + attacked_unit_pos_x = box_sprite.getPosition().x + get_width() * 3 / 4 - + attacked_unit.getGlobalBounds().width; + attacked_unit_pos_y = attacking_unit_pos_y; + attacked_unit.setPosition(attacked_unit_pos_x, attacked_unit_pos_y); } -void AttackInfoBox::update_box_text_pos() -{ - box_text.setPosition(box_sprite.getPosition().x + ((get_width() - box_text.getLocalBounds().width) / 2), - box_sprite.getPosition().y + (get_height() - box_text.getCharacterSize()) / 2); +void AttackInfoBox::update_box_text_pos() { + box_text.setPosition( + box_sprite.getPosition().x + + ((get_width() - box_text.getLocalBounds().width) / 2), + box_sprite.getPosition().y + + (get_height() - box_text.getCharacterSize()) / 2); } -const Unit* AttackInfoBox::get_winner() -{ - if (!attacked_ptr || !attacker_ptr) - { - return {}; - } - const auto result = std::visit(Attack{}, *attacker_ptr, *attacked_ptr); - if (result == attack::Result::Won) - { - return attacker_ptr; - } - if (result == attack::Result::Lost) - { - return attacked_ptr; - } - // FIXME: what happens with a Draw? Both are winners then +const Unit *AttackInfoBox::get_winner() { + if (!attacked_ptr || !attacker_ptr) { return {}; + } + const auto result = std::visit(Attack{}, *attacker_ptr, *attacked_ptr); + if (result == attack::Result::Won) { + return attacker_ptr; + } + if (result == attack::Result::Lost) { + return attacked_ptr; + } + // FIXME: what happens with a Draw? Both are winners then + return {}; } -void AttackInfoBox::set_winner_highlight() -{ - if (get_winner() == attacker_ptr) - { - winner_highlight.setPosition(attacking_unit.getPosition()); - } - if (get_winner() == attacked_ptr) - { - winner_highlight.setPosition(attacked_unit.getPosition()); - } +void AttackInfoBox::set_winner_highlight() { + if (get_winner() == attacker_ptr) { + winner_highlight.setPosition(attacking_unit.getPosition()); + } + if (get_winner() == attacked_ptr) { + winner_highlight.setPosition(attacked_unit.getPosition()); + } } -void AttackInfoBox::draw_winner_highlight(sf::RenderWindow &win) -{ - if (!get_winner()) - { - return; - } - winner_highlight.setScale(1.5, 1.5); - win.draw(winner_highlight); - winner_highlight.setScale(1, 1); +void AttackInfoBox::draw_winner_highlight(sf::RenderWindow &win) { + if (!get_winner()) { + return; + } + winner_highlight.setScale(1.5, 1.5); + win.draw(winner_highlight); + winner_highlight.setScale(1, 1); } \ No newline at end of file diff --git a/src/BigButton.cpp b/src/BigButton.cpp index b60861e..bc3ac7b 100644 --- a/src/BigButton.cpp +++ b/src/BigButton.cpp @@ -2,34 +2,34 @@ #include -BigButton::BigButton(const std::string& text) - : ButtonInterface(text) { - load_button_texture(); - load_highlighted_button_texture(); +BigButton::BigButton(const std::string &text) : ButtonInterface(text) { + load_button_texture(); + load_highlighted_button_texture(); - button.setTexture(button_texture); - highlighted_button.setTexture(highlighted_button_texture); + button.setTexture(button_texture); + highlighted_button.setTexture(highlighted_button_texture); } void BigButton::load_button_texture() { - if (!button_texture.loadFromFile(path_to_textures + "big_button.png")) { - std::cerr << "big button texture failed to load!\n"; - abort(); - } + if (!button_texture.loadFromFile(path_to_textures + "big_button.png")) { + std::cerr << "big button texture failed to load!\n"; + abort(); + } } void BigButton::load_highlighted_button_texture() { - if (!highlighted_button_texture.loadFromFile(path_to_textures + "big_button_highlighted.png")) { - std::cerr << "big button highlighted texture failed to load!\n"; - abort(); - } + if (!highlighted_button_texture.loadFromFile(path_to_textures + + "big_button_highlighted.png")) { + std::cerr << "big button highlighted texture failed to load!\n"; + abort(); + } } -void BigButton::draw(sf::RenderWindow& win) { - if (highlighted) { - win.draw(highlighted_button); - } else { - win.draw(button); - } - win.draw(button_text); +void BigButton::draw(sf::RenderWindow &win) { + if (highlighted) { + win.draw(highlighted_button); + } else { + win.draw(button); + } + win.draw(button_text); } \ No newline at end of file diff --git a/src/Board.cpp b/src/Board.cpp index 56d8cb5..be1d7bc 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -11,281 +11,275 @@ #include "unit/RegularUnit.hpp" #include "unit/ScoutUnit.hpp" #include "unit/SpyUnit.hpp" -#include "unit/visit/GetTileInfo.hpp" #include "unit/visit/CanMove.hpp" +#include "unit/visit/GetTileInfo.hpp" Board::Board() - : height(12), - width(10), - current_state(State::Uninitialized), - unit_count(0), - units(width, height), - max_count_of_each_unit({{"flag", 1}, - {"scout", 8}, - {"miner", 5}, - {"bomb", 6}, - {"spy", 1}, - {"regular4", 4}, - {"regular5", 4}, - {"regular6", 4}, - {"regular7", 3}, - {"regular8", 2}, - {"regular9", 1}, - {"regular10", 1}}) { - set_obstacles(); - set_default_units(); + : height(12), width(10), current_state(State::Uninitialized), unit_count(0), + units(width, height), max_count_of_each_unit({{"flag", 1}, + {"scout", 8}, + {"miner", 5}, + {"bomb", 6}, + {"spy", 1}, + {"regular4", 4}, + {"regular5", 4}, + {"regular6", 4}, + {"regular7", 3}, + {"regular8", 2}, + {"regular9", 1}, + {"regular10", 1}}) { + set_obstacles(); + set_default_units(); } void Board::set_default_units() { - for (int row = 0; row < height; ++row) { - for (int col = 0; col < width; ++col) { - unset_unit(Tile{col, row}); - } + for (int row = 0; row < height; ++row) { + for (int col = 0; col < width; ++col) { + unset_unit(Tile{col, row}); } + } } void Board::set_obstacles() { - int left_obstacle_x = 2; - int obstacle_y = 5; - int right_obstacle_x = 6; - int j = 0; - for (size_t i = 0; i < obstacles.size(); ++i) { - if (i % 2 == 0) { - j = 0; - } - if (i < 2) { - obstacles[i].x = left_obstacle_x + j; - obstacles[i].y = obstacle_y; - } - if (i > 1 && i < 4) { - obstacles[i].x = left_obstacle_x + j; - obstacles[i].y = obstacle_y + 1; - } - if (i > 3 && i < 6) { - obstacles[i].x = right_obstacle_x + j; - obstacles[i].y = obstacle_y; - } - if (i > 5 && i < 8) { - obstacles[i].x = right_obstacle_x + j; - obstacles[i].y = obstacle_y + 1; - } - j++; + int left_obstacle_x = 2; + int obstacle_y = 5; + int right_obstacle_x = 6; + int j = 0; + for (size_t i = 0; i < obstacles.size(); ++i) { + if (i % 2 == 0) { + j = 0; + } + if (i < 2) { + obstacles[i].x = left_obstacle_x + j; + obstacles[i].y = obstacle_y; + } + if (i > 1 && i < 4) { + obstacles[i].x = left_obstacle_x + j; + obstacles[i].y = obstacle_y + 1; } + if (i > 3 && i < 6) { + obstacles[i].x = right_obstacle_x + j; + obstacles[i].y = obstacle_y; + } + if (i > 5 && i < 8) { + obstacles[i].x = right_obstacle_x + j; + obstacles[i].y = obstacle_y + 1; + } + j++; + } } bool Board::is_unit_set(Tile tile) const { - return units[tile.y][tile.x].has_value(); + return units[tile.y][tile.x].has_value(); } -void Board::unset_unit(Tile tile) { - units[tile.y][tile.x] = std::nullopt; -} +void Board::unset_unit(Tile tile) { units[tile.y][tile.x] = std::nullopt; } bool Board::out_of_range(int col, int row) const { - if (col < 0 || col >= width) { - return true; - } - if (row < 0 || row >= height) { - return true; - } - return false; + if (col < 0 || col >= width) { + return true; + } + if (row < 0 || row >= height) { + return true; + } + return false; } std::string Board::get_tile_info(int col, int row, Turn player) const { - if (out_of_range(col, row)) { - return "#"; - } - if (!is_unit_set(Tile{col, row})) { - return " "; - } - if (std::find_if(obstacles.begin(), obstacles.end(), [col, row](const Tile& tile) { - return tile.x == col && tile.y == row; - }) != obstacles.end()) { - return "O"; - } - return std::visit(GetTileInfo{player}, units[row][col].value()); + if (out_of_range(col, row)) { + return "#"; + } + if (!is_unit_set(Tile{col, row})) { + return " "; + } + if (std::find_if(obstacles.begin(), obstacles.end(), + [col, row](const Tile &tile) { + return tile.x == col && tile.y == row; + }) != obstacles.end()) { + return "O"; + } + return std::visit(GetTileInfo{player}, units[row][col].value()); } -std::string Board::get_tile_info(const Tile& tile, Turn player) const { - return get_tile_info(tile.x, tile.y, player); +std::string Board::get_tile_info(const Tile &tile, Turn player) const { + return get_tile_info(tile.x, tile.y, player); } int Board::get_max_unit_count(int idx) const { - switch (idx) { - case 0: - return ScoutUnit::get_max_count(); - case 1: - return MinerUnit::get_max_count(); - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - return RegularUnit::get_max_count(idx + 2); - case 9: - return BombUnit::get_max_count(); - case 10: - return FlagUnit::get_max_count(); - case 11: - return SpyUnit::get_max_count(); - } - return -1; + switch (idx) { + case 0: + return ScoutUnit::get_max_count(); + case 1: + return MinerUnit::get_max_count(); + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + return RegularUnit::get_max_count(idx + 2); + case 9: + return BombUnit::get_max_count(); + case 10: + return FlagUnit::get_max_count(); + case 11: + return SpyUnit::get_max_count(); + } + return -1; } -void Board::set_state(State state) { - current_state = state; -} +void Board::set_state(State state) { current_state = state; } bool Board::set_unit(int col, int row, Turn player, int choice) { - if (col < 0 || col >= width) { - return false; - } - if (row < (height - 4) || row >= height) { - return false; - } - if (choice < 0 && choice >= 12) { - return false; - } - if (get_tile_info(col, row, player) != " ") { - return false; - } - if (current_state == State::Full) { - return false; - } + if (col < 0 || col >= width) { + return false; + } + if (row < (height - 4) || row >= height) { + return false; + } + if (choice < 0 && choice >= 12) { + return false; + } + if (get_tile_info(col, row, player) != " ") { + return false; + } + if (current_state == State::Full) { + return false; + } - switch (choice + 2) { - case 2: { - units[row][col] = ScoutUnit(player); - } break; - case 3: { - units[row][col] = MinerUnit(player); - } break; - case 11: { - units[row][col] = BombUnit(player); - } break; - case 12: { - units[row][col] = FlagUnit(player); - } break; - case 13: { - units[row][col] = SpyUnit(player); - } - } - if (choice + 2 > 3 && choice + 2 < 11) { - units[row][col] = RegularUnit(choice + 2, player); - } - unit_count++; - if (unit_count == MAX_UNIT_COUNT) { - current_state = State::Full; - } - return true; + switch (choice + 2) { + case 2: { + units[row][col] = ScoutUnit(player); + } break; + case 3: { + units[row][col] = MinerUnit(player); + } break; + case 11: { + units[row][col] = BombUnit(player); + } break; + case 12: { + units[row][col] = FlagUnit(player); + } break; + case 13: { + units[row][col] = SpyUnit(player); + } + } + if (choice + 2 > 3 && choice + 2 < 11) { + units[row][col] = RegularUnit(choice + 2, player); + } + unit_count++; + if (unit_count == MAX_UNIT_COUNT) { + current_state = State::Full; + } + return true; } void Board::remove_unit(int col, int row) { - unset_unit(Tile{col, row}); - unit_count--; - if (current_state == State::Full) { - current_state = State::Uninitialized; - } + unset_unit(Tile{col, row}); + unit_count--; + if (current_state == State::Full) { + current_state = State::Uninitialized; + } } void Board::reverse_remove_unit(int col, int row) { - Tile unit = point_reflection(col, row); - unset_unit(unit); + Tile unit = point_reflection(col, row); + unset_unit(unit); } -bool Board::can_move(const Tile& from, const Tile& to) const { - if (out_of_range(from.x, from.y)) { - return false; - } - if (!is_unit_set(from)) { - return false; - } - return std::visit(CanMove{from, to}, units[from.y][from.x].value()); +bool Board::can_move(const Tile &from, const Tile &to) const { + if (out_of_range(from.x, from.y)) { + return false; + } + if (!is_unit_set(from)) { + return false; + } + return std::visit(CanMove{from, to}, units[from.y][from.x].value()); } -bool Board::move_unit(const Tile& from, const Tile& to) { - using std::swap; - if (can_move(from, to)) { - swap(units[from.y][from.x], units[to.y][to.x]); - return true; - } - return false; +bool Board::move_unit(const Tile &from, const Tile &to) { + using std::swap; + if (can_move(from, to)) { + swap(units[from.y][from.x], units[to.y][to.x]); + return true; + } + return false; } -void Board::reverse_move_unit(const Tile& from, const Tile& to) { - using std::swap; - Tile rev_from = point_reflection(from.x, from.y); - Tile rev_to = point_reflection(to.x, to.y); - swap(units[rev_from.y][rev_from.x], units[rev_to.y][rev_to.x]); +void Board::reverse_move_unit(const Tile &from, const Tile &to) { + using std::swap; + Tile rev_from = point_reflection(from.x, from.y); + Tile rev_to = point_reflection(to.x, to.y); + swap(units[rev_from.y][rev_from.x], units[rev_to.y][rev_to.x]); } Tile Board::point_reflection(int col, int row) { - Tile distance; - Tile distance_point; - Tile reflection; - Tile reflection_point; - if (col >= 5 && row <= 5) { //first quarter of the board - distance_point = Tile(4, 6); - reflection_point = Tile(5, 5); - } - if (col <= 4 && row <= 5) { //second quarter of the board - distance_point = Tile(5, 6); - reflection_point = Tile(4, 5); - } - if (col <= 4 && row >= 6) { //third quarter of the board - distance_point = Tile(5, 5); - reflection_point = Tile(4, 6); - } - if (col >= 5 && row >= 6) { //fourth quarter of the board - distance_point = Tile(4, 5); - reflection_point = Tile(5, 6); - } - distance.x = col - distance_point.x; - distance.y = row - distance_point.y; - reflection.x = -distance.x; - reflection.y = -distance.y; - return Tile(reflection_point.x + reflection.x, reflection_point.y + reflection.y); + Tile distance; + Tile distance_point; + Tile reflection; + Tile reflection_point; + if (col >= 5 && row <= 5) { // first quarter of the board + distance_point = Tile(4, 6); + reflection_point = Tile(5, 5); + } + if (col <= 4 && row <= 5) { // second quarter of the board + distance_point = Tile(5, 6); + reflection_point = Tile(4, 5); + } + if (col <= 4 && row >= 6) { // third quarter of the board + distance_point = Tile(5, 5); + reflection_point = Tile(4, 6); + } + if (col >= 5 && row >= 6) { // fourth quarter of the board + distance_point = Tile(4, 5); + reflection_point = Tile(5, 6); + } + distance.x = col - distance_point.x; + distance.y = row - distance_point.y; + reflection.x = -distance.x; + reflection.y = -distance.y; + return Tile(reflection_point.x + reflection.x, + reflection_point.y + reflection.y); } -Board& Board::operator=(const Board& rhs) { - if (this == &rhs) { - return *this; - } - height = rhs.height; - width = rhs.width; - for (int row = 0; row < height; ++row) { - for (int col = 0; col < width; ++col) { - units[row][col] = rhs.units[row][col]; - } - } - for (size_t i = 0; i < obstacles.size(); ++i) { - obstacles[i] = rhs.obstacles[i]; - } +Board &Board::operator=(const Board &rhs) { + if (this == &rhs) { return *this; + } + height = rhs.height; + width = rhs.width; + for (int row = 0; row < height; ++row) { + for (int col = 0; col < width; ++col) { + units[row][col] = rhs.units[row][col]; + } + } + for (size_t i = 0; i < obstacles.size(); ++i) { + obstacles[i] = rhs.obstacles[i]; + } + return *this; } -void Board::update(const Board& other_board) { - using std::swap; - Tile other_unit; - *this = other_board; - for (int row = 0; row < height / 2; ++row) { - for (int col = 0; col < width; ++col) { - other_unit = point_reflection(col, row); - swap(units[other_unit.y][other_unit.x], units[row][col]); - } +void Board::update(const Board &other_board) { + using std::swap; + Tile other_unit; + *this = other_board; + for (int row = 0; row < height / 2; ++row) { + for (int col = 0; col < width; ++col) { + other_unit = point_reflection(col, row); + swap(units[other_unit.y][other_unit.x], units[row][col]); } + } } -const std::optional& Board::get_unit(int col, int row) const { - if (out_of_range(col, row)) { - // TODO: maybe more sophisticated error handling? - return std::nullopt; - } - return units[row][col]; +const std::optional &Board::get_unit(int col, int row) const { + if (out_of_range(col, row)) { + // TODO: maybe more sophisticated error handling? + return std::nullopt; + } + return units[row][col]; } -const std::optional& Board::get_unit(const Tile& chosen_unit) const { - return get_unit(chosen_unit.x, chosen_unit.y); +const std::optional &Board::get_unit(const Tile &chosen_unit) const { + return get_unit(chosen_unit.x, chosen_unit.y); } \ No newline at end of file diff --git a/src/Box.cpp b/src/Box.cpp index 24a8ce4..5e0192f 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -3,125 +3,136 @@ #include #include -Box::Box(const std::string& text) - : path_to_textures("images/board/"), - max_char_count_inside_box(12), - max_number_of_text_lines_inside_box(3), - box_text_x_pos(-1), - box_text_y_pos(-1), - button_x_pos(-1), - button_y_pos(-1) { - load_box_texture(); - load_font(); - set_default_text(text); - update_max_char_count(); - set_button_text(); - box_sprite.setTexture(box_texture); - update_button_pos(); - update_text_pos(); +Box::Box(const std::string &text) + : path_to_textures("images/board/"), max_char_count_inside_box(12), + max_number_of_text_lines_inside_box(3), box_text_x_pos(-1), + box_text_y_pos(-1), button_x_pos(-1), button_y_pos(-1) { + load_box_texture(); + load_font(); + set_default_text(text); + update_max_char_count(); + set_button_text(); + box_sprite.setTexture(box_texture); + update_button_pos(); + update_text_pos(); } void Box::load_box_texture() { - if (!box_texture.loadFromFile(path_to_textures + "box.png")) { - std::cerr << "box texture failed to load!\n"; - abort(); - } + if (!box_texture.loadFromFile(path_to_textures + "box.png")) { + std::cerr << "box texture failed to load!\n"; + abort(); + } } void Box::load_font() { - if (!font.loadFromFile("font/chandas1-2.ttf")) { - std::cerr << "font failed to load inside Box class!\n"; - abort(); - } + if (!font.loadFromFile("font/chandas1-2.ttf")) { + std::cerr << "font failed to load inside Box class!\n"; + abort(); + } } -void Box::set_default_text(const std::string& text) { - box_text.setFont(font); - box_text.setString(text); - update_text_pos(); +void Box::set_default_text(const std::string &text) { + box_text.setFont(font); + box_text.setString(text); + update_text_pos(); } void Box::update_text_pos() { - box_text_x_pos = (box_sprite.getPosition().x + (box_sprite.getGlobalBounds().width - box_text.getLocalBounds().width) / 2); - box_text_y_pos = (box_sprite.getPosition().y + 2 * box_text.getCharacterSize()); - box_text.setPosition(box_text_x_pos, box_text_y_pos); + box_text_x_pos = + (box_sprite.getPosition().x + + (box_sprite.getGlobalBounds().width - box_text.getLocalBounds().width) / + 2); + box_text_y_pos = + (box_sprite.getPosition().y + 2 * box_text.getCharacterSize()); + box_text.setPosition(box_text_x_pos, box_text_y_pos); } void Box::update_button_pos() { - button_x_pos = box_sprite.getPosition().x + (box_sprite.getGlobalBounds().width - button.get_width()) / 2; - button_y_pos = box_sprite.getPosition().y + box_sprite.getGlobalBounds().height - 2 * box_text.getCharacterSize() - button.get_height(); - button.set_position(button_x_pos, button_y_pos); + button_x_pos = box_sprite.getPosition().x + + (box_sprite.getGlobalBounds().width - button.get_width()) / 2; + button_y_pos = box_sprite.getPosition().y + + box_sprite.getGlobalBounds().height - + 2 * box_text.getCharacterSize() - button.get_height(); + button.set_position(button_x_pos, button_y_pos); } void Box::set_position(int x, int y) { - box_sprite.setPosition(x, y); - update_text_pos(); - box_text.setPosition(box_text_x_pos, box_text_y_pos); - update_button_pos(); - button.set_position(button_x_pos, button_y_pos); + box_sprite.setPosition(x, y); + update_text_pos(); + box_text.setPosition(box_text_x_pos, box_text_y_pos); + update_button_pos(); + button.set_position(button_x_pos, button_y_pos); } -void Box::set_position(const sf::Vector2f& coords) { - set_position(coords.x, coords.y); +void Box::set_position(const sf::Vector2f &coords) { + set_position(coords.x, coords.y); } -void Box::set_text(const std::string& text) { - box_text.setString(text); - break_text_into_lines(); - update_text_pos(); +void Box::set_text(const std::string &text) { + box_text.setString(text); + break_text_into_lines(); + update_text_pos(); } -void Box::set_button_text(const std::string& text) { - button.set_text(text); -} +void Box::set_button_text(const std::string &text) { button.set_text(text); } -void Box::draw(sf::RenderWindow& win) { - win.draw(box_sprite); - win.draw(box_text); - button.draw(win); +void Box::draw(sf::RenderWindow &win) { + win.draw(box_sprite); + win.draw(box_text); + button.draw(win); } void Box::update_max_char_count() { - int max_chars_per_line = box_sprite.getLocalBounds().width / box_text.getCharacterSize(); - max_char_count_inside_box = max_chars_per_line * max_number_of_text_lines_inside_box; + int max_chars_per_line = + box_sprite.getLocalBounds().width / box_text.getCharacterSize(); + max_char_count_inside_box = + max_chars_per_line * max_number_of_text_lines_inside_box; } void Box::break_text_into_lines() { - if (box_text.getString().getSize() * box_text.getCharacterSize() < box_sprite.getLocalBounds().width) { - return; + if (box_text.getString().getSize() * box_text.getCharacterSize() < + box_sprite.getLocalBounds().width) { + return; + } + std::istringstream temp_stream(box_text.getString()); + std::vector words( + (std::istream_iterator(temp_stream)), + std::istream_iterator()); + std::string temp_text; + size_t char_count_inside_line = 0; + size_t line_count = 0; + size_t space_count_in_line = 0; + size_t char_count_that_will_fit_in_line = 0; + size_t char_count_of_next_word = 0; + size_t idx_of_the_first_char_in_new_line = 0; + for (size_t i = 0; i < words.size() - 1; ++i) { + char_count_of_next_word = words[i + 1].size(); + char_count_inside_line += words[i].size(); + if (char_count_inside_line * box_text.getCharacterSize() > get_width()) { + temp_text += (words[i] + "\n"); + line_count++; + idx_of_the_first_char_in_new_line = char_count_inside_line + 2; + char_count_inside_line = 0; + } else { + char_count_that_will_fit_in_line = + box_sprite.getLocalBounds().width - + char_count_inside_line * box_text.getCharacterSize(); + if (char_count_of_next_word > char_count_that_will_fit_in_line || + i == words.size() - 2) { + float denting = (box_sprite.getLocalBounds().width - + char_count_inside_line * box_text.getCharacterSize()) / + 2; + int spaces = (denting / box_text.getCharacterSize() + 0.5); + temp_text.insert(idx_of_the_first_char_in_new_line, spaces, ' '); + } + temp_text += (words[i] + " "); + } + if (line_count > 3) { + break; } - std::istringstream temp_stream(box_text.getString()); - std::vector words((std::istream_iterator(temp_stream)), std::istream_iterator()); - std::string temp_text; - size_t char_count_inside_line = 0; - size_t line_count = 0; - size_t space_count_in_line = 0; - size_t char_count_that_will_fit_in_line = 0; - size_t char_count_of_next_word = 0; - size_t idx_of_the_first_char_in_new_line = 0; - for (size_t i = 0; i < words.size() - 1; ++i) { - char_count_of_next_word = words[i + 1].size(); - char_count_inside_line += words[i].size(); - if (char_count_inside_line * box_text.getCharacterSize() > get_width()) { - temp_text += (words[i] + "\n"); - line_count++; - idx_of_the_first_char_in_new_line = char_count_inside_line + 2; - char_count_inside_line = 0; - } else { - char_count_that_will_fit_in_line = box_sprite.getLocalBounds().width - char_count_inside_line * box_text.getCharacterSize(); - if (char_count_of_next_word > char_count_that_will_fit_in_line || i == words.size() - 2) { - float denting = (box_sprite.getLocalBounds().width - char_count_inside_line * box_text.getCharacterSize()) / 2; - int spaces = (denting / box_text.getCharacterSize() + 0.5); - temp_text.insert(idx_of_the_first_char_in_new_line, spaces, ' '); - } - temp_text += (words[i] + " "); - } - if (line_count > 3) { - break; - } - if (i == words.size() - 2) { - temp_text += words[i + 1]; - } + if (i == words.size() - 2) { + temp_text += words[i + 1]; } - box_text.setString(temp_text); + } + box_text.setString(temp_text); } diff --git a/src/Button.cpp b/src/Button.cpp index 13f2319..1284e03 100644 --- a/src/Button.cpp +++ b/src/Button.cpp @@ -2,34 +2,34 @@ #include -Button::Button(const std::string& text) -:ButtonInterface(text) -{ - load_button_texture(); - load_highlighted_button_texture(); - button.setTexture(button_texture); - highlighted_button.setTexture(highlighted_button_texture); +Button::Button(const std::string &text) : ButtonInterface(text) { + load_button_texture(); + load_highlighted_button_texture(); + button.setTexture(button_texture); + highlighted_button.setTexture(highlighted_button_texture); } void Button::load_button_texture() { - if (!button_texture.loadFromFile(path_to_textures + "button.png")) { - std::cerr << "wooden texture loading inside Button class failed!\n"; - abort(); - } + if (!button_texture.loadFromFile(path_to_textures + "button.png")) { + std::cerr << "wooden texture loading inside Button class failed!\n"; + abort(); + } } void Button::load_highlighted_button_texture() { - if (!highlighted_button_texture.loadFromFile(path_to_textures + "button_highlighted.png")) { - std::cerr << "highlighted wooden texture loading inside Button class failed!\n"; - abort(); - } + if (!highlighted_button_texture.loadFromFile(path_to_textures + + "button_highlighted.png")) { + std::cerr << "highlighted wooden texture loading inside Button class " + "failed!\n"; + abort(); + } } -void Button::draw(sf::RenderWindow& win) { - if (highlighted) { - win.draw(highlighted_button); - } else { - win.draw(button); - } - win.draw(button_text); +void Button::draw(sf::RenderWindow &win) { + if (highlighted) { + win.draw(highlighted_button); + } else { + win.draw(button); + } + win.draw(button_text); } diff --git a/src/ButtonInterface.cpp b/src/ButtonInterface.cpp index ed4c67c..69d7182 100644 --- a/src/ButtonInterface.cpp +++ b/src/ButtonInterface.cpp @@ -2,44 +2,48 @@ #include -ButtonInterface::ButtonInterface(const std::string& text) +ButtonInterface::ButtonInterface(const std::string &text) : path_to_textures("images/board/") { - load_font(); - set_default_button_text(text); - update_text_pos(); - highlighted = false; + load_font(); + set_default_button_text(text); + update_text_pos(); + highlighted = false; } void ButtonInterface::load_font() { - if (!font.loadFromFile("font/chandas1-2.ttf")) { - std::cerr << "font failed loading inside ButtonInterface class!\n"; - abort(); - } + if (!font.loadFromFile("font/chandas1-2.ttf")) { + std::cerr << "font failed loading inside ButtonInterface class!\n"; + abort(); + } } -void ButtonInterface::set_default_button_text(const std::string& text) { - button_text.setFont(font); - button_text.setString(text); - button_text.setFillColor(sf::Color::Yellow); +void ButtonInterface::set_default_button_text(const std::string &text) { + button_text.setFont(font); + button_text.setString(text); + button_text.setFillColor(sf::Color::Yellow); } void ButtonInterface::update_text_pos() { - text_x_pos = (button.getPosition().x + (button.getGlobalBounds().width - button_text.getLocalBounds().width) / 2); - text_y_pos = (button.getPosition().y + (button.getGlobalBounds().height - button_text.getCharacterSize()) / 2); - button_text.setPosition(text_x_pos, text_y_pos); + text_x_pos = (button.getPosition().x + (button.getGlobalBounds().width - + button_text.getLocalBounds().width) / + 2); + text_y_pos = + (button.getPosition().y + + (button.getGlobalBounds().height - button_text.getCharacterSize()) / 2); + button_text.setPosition(text_x_pos, text_y_pos); } void ButtonInterface::set_position(int x, int y) { - button.setPosition(x, y); - highlighted_button.setPosition(x, y); - update_text_pos(); + button.setPosition(x, y); + highlighted_button.setPosition(x, y); + update_text_pos(); } void ButtonInterface::set_position(sf::Vector2f coords) { - set_position(coords.x, coords.y); + set_position(coords.x, coords.y); } -void ButtonInterface::set_text(const std::string& text) { - button_text.setString(text); - update_text_pos(); +void ButtonInterface::set_text(const std::string &text) { + button_text.setString(text); + update_text_pos(); } \ No newline at end of file diff --git a/src/Game.cpp b/src/Game.cpp index d9bd233..7de1a07 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -1,73 +1,75 @@ #include "Game.hpp" -Game::Game(GameView& g_view, GameController& g_controller) - : game_view(g_view), - game_controller(g_controller), - clock_started(false) { -} +Game::Game(GameView &g_view, GameController &g_controller) + : game_view(g_view), game_controller(g_controller), clock_started(false) {} -std::string Game::run(sf::RenderWindow& win) { - - while (win.isOpen()) { - sf::Event event; - game_view.update_players(game_controller.get_current_player(), game_controller.get_other_player()); - while (win.pollEvent(event)) { - if (event.type == sf::Event::Closed) { - win.close(); - return "exit"; - } - if (event.type == sf::Event::KeyPressed) { - if (event.key.code == sf::Keyboard::Escape) { - return "menu"; - } - } - if (event.type == sf::Event::MouseButtonPressed) { - if(game_controller.get_end_game_info_box_button_pressed()) { - return "menu"; - } - } - game_controller.handle_events(event); +std::string Game::run(sf::RenderWindow &win) { + while (win.isOpen()) { + sf::Event event; + game_view.update_players(game_controller.get_current_player(), + game_controller.get_other_player()); + while (win.pollEvent(event)) { + if (event.type == sf::Event::Closed) { + win.close(); + return "exit"; + } + if (event.type == sf::Event::KeyPressed) { + if (event.key.code == sf::Keyboard::Escape) { + return "menu"; + } + } + if (event.type == sf::Event::MouseButtonPressed) { + if (game_controller.get_end_game_info_box_button_pressed()) { + return "menu"; } - win.clear(); - draw(win); - win.display(); + } + game_controller.handle_events(event); } - return "exit"; + win.clear(); + draw(win); + win.display(); + } + return "exit"; } -void Game::draw(sf::RenderWindow& win) { - if (game_controller.get_game_finished()) { - game_view.draw_end_game_screen(win, game_controller.get_victorious_player_name()); - return; - } - game_view.draw_board_border(win); - game_view.draw_grass(win); - game_view.draw_obstacles(win); - if (game_controller.get_end_turn_button_pressed()) { - game_view.draw_info_box(win); - return; - } - game_controller.update_unit_attacked(clock.restart()); - if (game_controller.get_unit_attacked()) { - game_view.draw_attack_info_box(win, game_controller.get_attacker(), game_controller.get_attacked()); - return; - } - game_view.draw_units(win); +void Game::draw(sf::RenderWindow &win) { + if (game_controller.get_game_finished()) { + game_view.draw_end_game_screen( + win, game_controller.get_victorious_player_name()); + return; + } + game_view.draw_board_border(win); + game_view.draw_grass(win); + game_view.draw_obstacles(win); + if (game_controller.get_end_turn_button_pressed()) { + game_view.draw_info_box(win); + return; + } + game_controller.update_unit_attacked(clock.restart()); + if (game_controller.get_unit_attacked()) { + game_view.draw_attack_info_box(win, game_controller.get_attacker(), + game_controller.get_attacked()); + return; + } + game_view.draw_units(win); + if (game_controller.get_is_active_unit()) { + game_view.draw_unit_highlight(win, game_controller.get_active_unit()); + } + if (!game_controller.both_boards_set()) { + game_view.draw_units_for_init(win, game_controller.get_dragging(), + game_controller.get_selected_init_unit_idx(), + game_controller.get_mouse_data()); + game_view.draw_done_button(win); + game_view.draw_randomize_button(win); if (game_controller.get_is_active_unit()) { - game_view.draw_unit_highlight(win, game_controller.get_active_unit()); + game_view.draw_remove_button(win); } - if (!game_controller.both_boards_set()) { - game_view.draw_units_for_init(win, game_controller.get_dragging(), - game_controller.get_selected_init_unit_idx(), game_controller.get_mouse_data()); - game_view.draw_done_button(win); - game_view.draw_randomize_button(win); - if (game_controller.get_is_active_unit()) { - game_view.draw_remove_button(win); - } - } else { - game_view.draw_end_turn_button(win); - if (game_controller.get_is_active_unit() && !game_controller.get_unit_moved_this_round()) { - game_view.draw_possible_moves_for_active_unit(win, game_controller.get_active_unit()); - } + } else { + game_view.draw_end_turn_button(win); + if (game_controller.get_is_active_unit() && + !game_controller.get_unit_moved_this_round()) { + game_view.draw_possible_moves_for_active_unit( + win, game_controller.get_active_unit()); } + } } diff --git a/src/GameController.cpp b/src/GameController.cpp index 7987a59..c2efd38 100644 --- a/src/GameController.cpp +++ b/src/GameController.cpp @@ -6,307 +6,309 @@ #include "Player.hpp" #include "unit/visit/GetOwner.hpp" -GameController::GameController(Player& pA, Player& pB, GameView& g_view) - : playerA(pA), - playerB(pB), - game_view(g_view), - current_player(&pA), - other_player(&pB), - attacker{}, - attacked{}, - victorious_player_name("none"), - current_player_turn(Turn::PlayerA), - TILE_SIZE(64), - selected_unit_idx(0), - dragging(false), - board_a_initialized(false), - board_b_initialized(false), - is_active_unit(false), - unit_moved_this_round(false), - end_turn_button_pressed(false), - turn_approved(false), - unit_attacked(false), - remove_button_pressed(false), - done_button_pressed(false), - randomize_button_pressed(false), - end_game_info_box_button_pressed(false), - game_finished(false), - active_unit(-1, -1), - attacking_unit(-1, -1), - attacked_unit(-1, -1) { -} +GameController::GameController(Player &pA, Player &pB, GameView &g_view) + : playerA(pA), playerB(pB), game_view(g_view), current_player(&pA), + other_player(&pB), attacker{}, attacked{}, victorious_player_name("none"), + current_player_turn(Turn::PlayerA), TILE_SIZE(64), selected_unit_idx(0), + dragging(false), board_a_initialized(false), board_b_initialized(false), + is_active_unit(false), unit_moved_this_round(false), + end_turn_button_pressed(false), turn_approved(false), + unit_attacked(false), remove_button_pressed(false), + done_button_pressed(false), randomize_button_pressed(false), + end_game_info_box_button_pressed(false), game_finished(false), + active_unit(-1, -1), attacking_unit(-1, -1), attacked_unit(-1, -1) {} -void GameController::update_unit_attacked(const sf::Time& time_past) { - if (unit_attacked) { - total_time_unit_attacked += time_past; - } - if (total_time_unit_attacked.asSeconds() > 1.5) { - total_time_unit_attacked = sf::Time(); - unit_attacked = false; - } +void GameController::update_unit_attacked(const sf::Time &time_past) { + if (unit_attacked) { + total_time_unit_attacked += time_past; + } + if (total_time_unit_attacked.asSeconds() > 1.5) { + total_time_unit_attacked = sf::Time(); + unit_attacked = false; + } } -void GameController::drag_red_player(sf::Event& event) { - const auto unit_selected = std::find_if(game_view.get_red_units_sprites().cbegin(), game_view.get_red_units_sprites().cend(), - [&event](const sf::Sprite& unit_sprite) { - return unit_sprite.getGlobalBounds().contains(event.mouseButton.x, event.mouseButton.y); - }); - if (unit_selected != game_view.get_red_units_sprites().cend()) { - dragging = true; - m_data.mouse_object_offset_x = event.mouseButton.x - unit_selected->getGlobalBounds().left; - m_data.mouse_object_offset_y = event.mouseButton.y - unit_selected->getGlobalBounds().top; - } - selected_unit_idx = std::distance(std::cbegin(game_view.get_red_units_sprites()), unit_selected); +void GameController::drag_red_player(sf::Event &event) { + const auto unit_selected = + std::find_if(game_view.get_red_units_sprites().cbegin(), + game_view.get_red_units_sprites().cend(), + [&event](const sf::Sprite &unit_sprite) { + return unit_sprite.getGlobalBounds().contains( + event.mouseButton.x, event.mouseButton.y); + }); + if (unit_selected != game_view.get_red_units_sprites().cend()) { + dragging = true; + m_data.mouse_object_offset_x = + event.mouseButton.x - unit_selected->getGlobalBounds().left; + m_data.mouse_object_offset_y = + event.mouseButton.y - unit_selected->getGlobalBounds().top; + } + selected_unit_idx = std::distance( + std::cbegin(game_view.get_red_units_sprites()), unit_selected); } -void GameController::drag_blue_player(sf::Event& event) { - const auto unit_selected = std::find_if(game_view.get_blue_units_sprites().cbegin(), game_view.get_blue_units_sprites().cend(), - [&event](const sf::Sprite& unit_sprite) { - return unit_sprite.getGlobalBounds().contains(event.mouseButton.x, event.mouseButton.y); - }); - if (unit_selected != game_view.get_blue_units_sprites().cend()) { - dragging = true; - m_data.mouse_object_offset_x = event.mouseButton.x - unit_selected->getGlobalBounds().left; - m_data.mouse_object_offset_y = event.mouseButton.y - unit_selected->getGlobalBounds().top; - } - selected_unit_idx = std::distance(std::cbegin(game_view.get_blue_units_sprites()), unit_selected); +void GameController::drag_blue_player(sf::Event &event) { + const auto unit_selected = + std::find_if(game_view.get_blue_units_sprites().cbegin(), + game_view.get_blue_units_sprites().cend(), + [&event](const sf::Sprite &unit_sprite) { + return unit_sprite.getGlobalBounds().contains( + event.mouseButton.x, event.mouseButton.y); + }); + if (unit_selected != game_view.get_blue_units_sprites().cend()) { + dragging = true; + m_data.mouse_object_offset_x = + event.mouseButton.x - unit_selected->getGlobalBounds().left; + m_data.mouse_object_offset_y = + event.mouseButton.y - unit_selected->getGlobalBounds().top; + } + selected_unit_idx = std::distance( + std::cbegin(game_view.get_blue_units_sprites()), unit_selected); } void GameController::change_player_turn() { - if (unit_moved_this_round && turn_approved) { - if (current_player_turn == Turn::PlayerA) { - current_player_turn = Turn::PlayerB; - current_player = &playerB; - other_player = &playerA; - } else { - current_player_turn = Turn::PlayerA; - current_player = &playerA; - other_player = &playerB; - } - unit_moved_this_round = false; - turn_approved = false; - is_active_unit = false; + if (unit_moved_this_round && turn_approved) { + if (current_player_turn == Turn::PlayerA) { + current_player_turn = Turn::PlayerB; + current_player = &playerB; + other_player = &playerA; + } else { + current_player_turn = Turn::PlayerA; + current_player = &playerA; + other_player = &playerB; } + unit_moved_this_round = false; + turn_approved = false; + is_active_unit = false; + } } -void GameController::change_init_turn(sf::Event& event) { - if (done_button_pressed) { - if (current_player_turn == Turn::PlayerA) { - if (playerA.get_board().get_state() == State::Full) { - board_a_initialized = true; - current_player_turn = Turn::PlayerB; - current_player = &playerB; - other_player = &playerA; - playerB.update_board(playerA.get_board()); - } - } else { - if (playerB.get_board().get_state() == State::Full) { - board_b_initialized = true; - current_player_turn = Turn::PlayerA; - current_player = &playerA; - other_player = &playerB; - playerA.update_board(playerB.get_board()); - } - } - is_active_unit = false; - done_button_pressed = false; +void GameController::change_init_turn(sf::Event &event) { + if (done_button_pressed) { + if (current_player_turn == Turn::PlayerA) { + if (playerA.get_board().get_state() == State::Full) { + board_a_initialized = true; + current_player_turn = Turn::PlayerB; + current_player = &playerB; + other_player = &playerA; + playerB.update_board(playerA.get_board()); + } + } else { + if (playerB.get_board().get_state() == State::Full) { + board_b_initialized = true; + current_player_turn = Turn::PlayerA; + current_player = &playerA; + other_player = &playerB; + playerA.update_board(playerB.get_board()); + } } + is_active_unit = false; + done_button_pressed = false; + } } -void GameController::set_unit(sf::Event& event) { - dragging = false; - Tile tile(return_tile(event.mouseButton.x, event.mouseButton.y)); - if (current_player->get_units_count(selected_unit_idx) < current_player->get_board().get_max_unit_count(selected_unit_idx)) { - current_player->set_unit(tile.x, tile.y, selected_unit_idx); - } +void GameController::set_unit(sf::Event &event) { + dragging = false; + Tile tile(return_tile(event.mouseButton.x, event.mouseButton.y)); + if (current_player->get_units_count(selected_unit_idx) < + current_player->get_board().get_max_unit_count(selected_unit_idx)) { + current_player->set_unit(tile.x, tile.y, selected_unit_idx); + } } -void GameController::set_active_unit(sf::Event& event) { - Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); - if (!current_player->get_board().get_unit(chosen_tile)) { - return; - } - if (std::visit(GetOwner{}, current_player->get_board().get_unit(chosen_tile).value()) != current_player->get_player_number()) { - return; - } +void GameController::set_active_unit(sf::Event &event) { + Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); + if (!current_player->get_board().get_unit(chosen_tile)) { + return; + } + if (std::visit(GetOwner{}, + current_player->get_board().get_unit(chosen_tile).value()) != + current_player->get_player_number()) { + return; + } - if (active_unit == chosen_tile && is_active_unit) { - active_unit.set_cords(-1, -1); - is_active_unit = false; - } else { - active_unit.set_cords(chosen_tile); - is_active_unit = true; - } + if (active_unit == chosen_tile && is_active_unit) { + active_unit.set_cords(-1, -1); + is_active_unit = false; + } else { + active_unit.set_cords(chosen_tile); + is_active_unit = true; + } } void GameController::remove_unit() { - if (is_active_unit && remove_button_pressed) { - current_player->remove_unit(active_unit.x, active_unit.y); - active_unit.set_cords(-1, -1); - is_active_unit = false; - remove_button_pressed = false; - } -} - -void GameController::resolve_unit_conflict(const Tile& attacked_unit) { - switch (current_player->attack(active_unit, attacked_unit)) { - case attack::Result::Won: - current_player->remove_unit(attacked_unit); - other_player->reverse_remove_unit(attacked_unit); - break; - case attack::Result::Draw: - current_player->remove_unit(active_unit); - current_player->remove_unit(attacked_unit); - other_player->reverse_remove_unit(active_unit); - other_player->reverse_remove_unit(attacked_unit); - active_unit.set_cords(-1, -1); - break; - case attack::Result::Lost: - current_player->remove_unit(active_unit); - other_player->reverse_remove_unit(active_unit); - active_unit.set_cords(-1, -1); - break; - } + if (is_active_unit && remove_button_pressed) { + current_player->remove_unit(active_unit.x, active_unit.y); + active_unit.set_cords(-1, -1); is_active_unit = false; + remove_button_pressed = false; + } } -void GameController::move_active_unit(sf::Event& event) { - Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); - if (!is_active_unit) { - return; - } - if (unit_moved_this_round) { - return; - } - if (!current_player->can_move(active_unit, chosen_tile)) { - return; - } - if (current_player->get_tile_info(chosen_tile) == "enemy") { - if (std::holds_alternative(current_player->get_board().get_unit(chosen_tile).value())) { - game_finished = true; - victorious_player_name = current_player->get_player_name(); - } - attacker = current_player->get_board().get_unit(active_unit); - attacked = current_player->get_board().get_unit(chosen_tile); - resolve_unit_conflict(chosen_tile); - unit_attacked = true; - unit_moved_this_round = true; +void GameController::resolve_unit_conflict(const Tile &attacked_unit) { + switch (current_player->attack(active_unit, attacked_unit)) { + case attack::Result::Won: + current_player->remove_unit(attacked_unit); + other_player->reverse_remove_unit(attacked_unit); + break; + case attack::Result::Draw: + current_player->remove_unit(active_unit); + current_player->remove_unit(attacked_unit); + other_player->reverse_remove_unit(active_unit); + other_player->reverse_remove_unit(attacked_unit); + active_unit.set_cords(-1, -1); + break; + case attack::Result::Lost: + current_player->remove_unit(active_unit); + other_player->reverse_remove_unit(active_unit); + active_unit.set_cords(-1, -1); + break; + } + is_active_unit = false; +} +void GameController::move_active_unit(sf::Event &event) { + Tile chosen_tile(return_tile(event.mouseButton.x, event.mouseButton.y)); + if (!is_active_unit) { + return; + } + if (unit_moved_this_round) { + return; + } + if (!current_player->can_move(active_unit, chosen_tile)) { + return; + } + if (current_player->get_tile_info(chosen_tile) == "enemy") { + if (std::holds_alternative( + current_player->get_board().get_unit(chosen_tile).value())) { + game_finished = true; + victorious_player_name = current_player->get_player_name(); } - if (current_player->move_unit(active_unit, chosen_tile)) { - other_player->reverse_move_unit(active_unit, chosen_tile); - active_unit.set_cords(-1, -1); - unit_moved_this_round = true; - is_active_unit = false; - } + attacker = current_player->get_board().get_unit(active_unit); + attacked = current_player->get_board().get_unit(chosen_tile); + resolve_unit_conflict(chosen_tile); + unit_attacked = true; + unit_moved_this_round = true; + } + if (current_player->move_unit(active_unit, chosen_tile)) { + other_player->reverse_move_unit(active_unit, chosen_tile); + active_unit.set_cords(-1, -1); + unit_moved_this_round = true; + is_active_unit = false; + } } void GameController::randomize_units() { - if (!randomize_button_pressed) { - return; + if (!randomize_button_pressed) { + return; + } + for (int row = 8; row < current_player->get_board().get_height(); ++row) { + for (int col = 0; col < current_player->get_board().get_width(); ++col) { + current_player->remove_unit(col, row); } + } + while (current_player->get_board().get_state() != State::Full) { for (int row = 8; row < current_player->get_board().get_height(); ++row) { - for (int col = 0; col < current_player->get_board().get_width(); ++col) { - current_player->remove_unit(col, row); - } - } - while (current_player->get_board().get_state() != State::Full) { - for (int row = 8; row < current_player->get_board().get_height(); ++row) { - for (int col = 0; col < current_player->get_board().get_width(); ++col) { - int idx = rand() % 12; - if (current_player->get_units_count(idx) < current_player->get_board().get_max_unit_count(idx)) - current_player->set_unit(col, row, idx); - } - } + for (int col = 0; col < current_player->get_board().get_width(); ++col) { + int idx = rand() % 12; + if (current_player->get_units_count(idx) < + current_player->get_board().get_max_unit_count(idx)) + current_player->set_unit(col, row, idx); + } } - randomize_button_pressed = false; + } + randomize_button_pressed = false; } void GameController::set_buttons_pressed() { - if (game_view.get_end_turn_button().is_highlighted() && unit_moved_this_round) { - end_turn_button_pressed = true; + if (game_view.get_end_turn_button().is_highlighted() && + unit_moved_this_round) { + end_turn_button_pressed = true; + } + if (game_view.get_info_box().button_is_highlighted() && + end_turn_button_pressed) { + turn_approved = true; + end_turn_button_pressed = false; + } + if (!(board_a_initialized && board_b_initialized)) { + if (game_view.get_done_button().is_highlighted()) { + done_button_pressed = true; } - if (game_view.get_info_box().button_is_highlighted() && end_turn_button_pressed) { - turn_approved = true; - end_turn_button_pressed = false; - } - if (!(board_a_initialized && board_b_initialized)) { - if (game_view.get_done_button().is_highlighted()) { - done_button_pressed = true; - } - if (game_view.get_randomize_button().is_highlighted()) { - randomize_button_pressed = true; - } - if (game_view.get_remove_button().is_highlighted()) { - remove_button_pressed = true; - } + if (game_view.get_randomize_button().is_highlighted()) { + randomize_button_pressed = true; } - if (game_finished && game_view.get_end_game_info_box().button_is_highlighted()) { - end_game_info_box_button_pressed = true; + if (game_view.get_remove_button().is_highlighted()) { + remove_button_pressed = true; } + } + if (game_finished && + game_view.get_end_game_info_box().button_is_highlighted()) { + end_game_info_box_button_pressed = true; + } } -void GameController::handle_events(sf::Event& event) { - if (event.type == sf::Event::MouseButtonPressed) { - set_buttons_pressed(); - if (!(board_a_initialized && board_b_initialized)) { - if (current_player_turn == Turn::PlayerA) { - drag_red_player(event); - } else { - drag_blue_player(event); - } - remove_unit(); - randomize_units(); - change_init_turn(event); - } - if (!is_out_of_the_board(event.mouseButton.x, event.mouseButton.y)) { - set_active_unit(event); - } - if (board_a_initialized && board_b_initialized) { - change_player_turn(); - move_active_unit(event); - } +void GameController::handle_events(sf::Event &event) { + if (event.type == sf::Event::MouseButtonPressed) { + set_buttons_pressed(); + if (!(board_a_initialized && board_b_initialized)) { + if (current_player_turn == Turn::PlayerA) { + drag_red_player(event); + } else { + drag_blue_player(event); + } + remove_unit(); + randomize_units(); + change_init_turn(event); } - if (event.type == sf::Event::MouseButtonReleased) { - if (!(board_a_initialized && board_b_initialized)) { - set_unit(event); - } + if (!is_out_of_the_board(event.mouseButton.x, event.mouseButton.y)) { + set_active_unit(event); } - if (event.type == sf::Event::MouseMoved) { - m_data.mouse_x = event.mouseMove.x; - m_data.mouse_y = event.mouseMove.y; - game_view.set_button_highlights(m_data.mouse_x, m_data.mouse_y); + if (board_a_initialized && board_b_initialized) { + change_player_turn(); + move_active_unit(event); } + } + if (event.type == sf::Event::MouseButtonReleased) { + if (!(board_a_initialized && board_b_initialized)) { + set_unit(event); + } + } + if (event.type == sf::Event::MouseMoved) { + m_data.mouse_x = event.mouseMove.x; + m_data.mouse_y = event.mouseMove.y; + game_view.set_button_highlights(m_data.mouse_x, m_data.mouse_y); + } } sf::Vector2f GameController::return_pixels(int col, int row) const { - if (col < 0 && row < 0) { - return sf::Vector2f{-1, -1}; - } - return sf::Vector2f(TILE_SIZE * (col + 1), TILE_SIZE * (row + 1)); + if (col < 0 && row < 0) { + return sf::Vector2f{-1, -1}; + } + return sf::Vector2f(TILE_SIZE * (col + 1), TILE_SIZE * (row + 1)); } -Tile GameController::return_tile(const sf::Vector2f& coords) const { - return Tile((coords.x - TILE_SIZE) / TILE_SIZE, (coords.y - TILE_SIZE) / TILE_SIZE); +Tile GameController::return_tile(const sf::Vector2f &coords) const { + return Tile((coords.x - TILE_SIZE) / TILE_SIZE, + (coords.y - TILE_SIZE) / TILE_SIZE); } Tile GameController::return_tile(int x, int y) const { - if (x < 0 && y < 0) { - return Tile{-1, -1}; - } - return return_tile(sf::Vector2f(x, y)); + if (x < 0 && y < 0) { + return Tile{-1, -1}; + } + return return_tile(sf::Vector2f(x, y)); } bool GameController::is_out_of_the_board(int x, int y) { - if (current_player->get_tile_info(return_tile(x, y)) == "#") { - return true; - } - return false; + if (current_player->get_tile_info(return_tile(x, y)) == "#") { + return true; + } + return false; } bool GameController::both_boards_set() const { - if (board_a_initialized && board_b_initialized) { - return true; - } - return false; + if (board_a_initialized && board_b_initialized) { + return true; + } + return false; }; diff --git a/src/GameView.cpp b/src/GameView.cpp index 333c7f8..91bec4e 100644 --- a/src/GameView.cpp +++ b/src/GameView.cpp @@ -4,491 +4,544 @@ #include "Player.hpp" -GameView::GameView(Player& pA, Player& pB) - : playerA(pA), - playerB(pB), - current_player(&playerA), - other_player(&playerB), - current_player_turn(Turn::PlayerA), +GameView::GameView(Player &pA, Player &pB) + : playerA(pA), playerB(pB), current_player(&playerA), + other_player(&playerB), current_player_turn(Turn::PlayerA), board_textures_path("images/board/"), - pieces_textures_path("images/pieces/"), - TILE_SIZE(64), + pieces_textures_path("images/pieces/"), TILE_SIZE(64), X_ADDITIONAL_SPACE(512), window_size(12 * TILE_SIZE + X_ADDITIONAL_SPACE, 14 * TILE_SIZE), - sprite_initial_position(-1, -1), - clock_started(false), - done_button("Done"), - randomize_button("Randomize"), - remove_button("Remove"), - end_turn_button("End Turn"), + sprite_initial_position(-1, -1), clock_started(false), + done_button("Done"), randomize_button("Randomize"), + remove_button("Remove"), end_turn_button("End Turn"), info_box("End of Turn"), - attack_info_box(red_units_sprites, blue_units_sprites, yellow_highlight_sprite), + attack_info_box(red_units_sprites, blue_units_sprites, + yellow_highlight_sprite), end_game_info_box("None") { - load_obstacle_textures(); - load_grass_textures(); - load_board_border_texture(); - load_red_units_textures(); - load_blue_units_textures(); - load_highlight_textures(); + load_obstacle_textures(); + load_grass_textures(); + load_board_border_texture(); + load_red_units_textures(); + load_blue_units_textures(); + load_highlight_textures(); - set_obstacle_sprites(); - set_red_units_sprites(); - set_blue_units_sprites(); - set_highlight_sprites(); + set_obstacle_sprites(); + set_red_units_sprites(); + set_blue_units_sprites(); + set_highlight_sprites(); - load_font(); - text.setFont(font); + load_font(); + text.setFont(font); - board_border.setTexture(board_border_texture); - grass_light.setTexture(grass_light_texture); - grass_dark.setTexture(grass_dark_texture); + board_border.setTexture(board_border_texture); + grass_light.setTexture(grass_light_texture); + grass_dark.setTexture(grass_dark_texture); } void GameView::set_obstacle_sprites() { - for (size_t i = 0; i < obstacle_sprites.size(); i++) { - obstacle_sprites[i].setTexture(obstacle_textures[i]); - } + for (size_t i = 0; i < obstacle_sprites.size(); i++) { + obstacle_sprites[i].setTexture(obstacle_textures[i]); + } } void GameView::load_board_border_texture() { - if (!board_border_texture.loadFromFile("images/board/border_scaled.png")) { - std::cerr << "board border error loading from file!\n"; - abort(); - } + if (!board_border_texture.loadFromFile("images/board/border_scaled.png")) { + std::cerr << "board border error loading from file!\n"; + abort(); + } } void GameView::load_grass_textures() { - if (!grass_light_texture.loadFromFile("images/board/grass1_scaled.png")) { - std::cerr << "grass light error loading from file!\n"; - abort(); - } - if (!grass_dark_texture.loadFromFile("images/board/grass2_scaled.png")) { - std::cerr << "grass dark error loading from file!\n"; - abort(); - } + if (!grass_light_texture.loadFromFile("images/board/grass1_scaled.png")) { + std::cerr << "grass light error loading from file!\n"; + abort(); + } + if (!grass_dark_texture.loadFromFile("images/board/grass2_scaled.png")) { + std::cerr << "grass dark error loading from file!\n"; + abort(); + } } void GameView::load_obstacle_textures() { - for (size_t i = 0; i < obstacle_textures.size(); ++i) { - if (i <= 3) { - if (!obstacle_textures[i].loadFromFile(board_textures_path + "lake1_" + std::to_string(i + 1) + ".png")) { - std::cerr << "obstacle texture lake1_" + std::to_string(i + 1) + "failed to load!\n"; - abort(); - } - } else { - if (!obstacle_textures[i].loadFromFile(board_textures_path + "lake2_" + std::to_string(i - 3) + ".png")) { - std::cerr << "obstacle texture lake2_" + std::to_string(i + 1) + "failed to load!\n"; - abort(); - } - } + for (size_t i = 0; i < obstacle_textures.size(); ++i) { + if (i <= 3) { + if (!obstacle_textures[i].loadFromFile(board_textures_path + "lake1_" + + std::to_string(i + 1) + ".png")) { + std::cerr << "obstacle texture lake1_" + std::to_string(i + 1) + + "failed to load!\n"; + abort(); + } + } else { + if (!obstacle_textures[i].loadFromFile(board_textures_path + "lake2_" + + std::to_string(i - 3) + ".png")) { + std::cerr << "obstacle texture lake2_" + std::to_string(i + 1) + + "failed to load!\n"; + abort(); + } } + } } void GameView::load_font() { - if (!font.loadFromFile("font/chandas1-2.ttf")) { - std::cerr << "font loading failed!\n"; - abort(); - } + if (!font.loadFromFile("font/chandas1-2.ttf")) { + std::cerr << "font loading failed!\n"; + abort(); + } } void GameView::load_highlight_textures() { - if (!red_highlight_texture.loadFromFile(board_textures_path + "highlight_red.png")) { - std::cerr << "red highlight texture failed!\n"; - abort(); - } - if (!yellow_highlight_texture.loadFromFile(board_textures_path + "highlight_yellow.png")) { - std::cerr << "yellow highlight texture failed!\n"; - abort(); - } - if (!green_highlight_texture.loadFromFile(board_textures_path + "highlight_green.png")) { - std::cerr << "green highlight texture failed!\n"; - abort(); - } + if (!red_highlight_texture.loadFromFile(board_textures_path + + "highlight_red.png")) { + std::cerr << "red highlight texture failed!\n"; + abort(); + } + if (!yellow_highlight_texture.loadFromFile(board_textures_path + + "highlight_yellow.png")) { + std::cerr << "yellow highlight texture failed!\n"; + abort(); + } + if (!green_highlight_texture.loadFromFile(board_textures_path + + "highlight_green.png")) { + std::cerr << "green highlight texture failed!\n"; + abort(); + } } void GameView::set_highlight_sprites() { - yellow_highlight_sprite.setTexture(yellow_highlight_texture); - green_highlight_sprite.setTexture(green_highlight_texture); - red_highlight_sprite.setTexture(red_highlight_texture); + yellow_highlight_sprite.setTexture(yellow_highlight_texture); + green_highlight_sprite.setTexture(green_highlight_texture); + red_highlight_sprite.setTexture(red_highlight_texture); } void GameView::load_blue_units_textures() { - for (size_t i = 0; i < 9; ++i) { - if (!blue_unit_textures[i].loadFromFile("images/pieces/blue/blue_" + std::to_string(i + 2) + ".png")) { - std::cerr << "blue unit" + std::to_string(i + 2) + "failed to load a texture!\n"; - abort(); - } - } - if (!blue_unit_textures[9].loadFromFile("images/pieces/blue/blue_bomb.png")) { - std::cerr << "blue bomb loading texture failed! \n"; - abort(); - } - if (!blue_unit_textures[10].loadFromFile("images/pieces/blue/blue_flag.png")) { - std::cerr << "blue flag loading texture failed! \n"; - abort(); - } - if (!blue_unit_textures[11].loadFromFile("images/pieces/blue/blue_spy.png")) { - std::cerr << "blue spy loading texture failed! \n"; - abort(); - } - if (!blue_back_texture.loadFromFile("images/pieces/blue/blue_back.png")) { - std::cerr << "blue back loading texture failed! \n"; - abort(); - } + for (size_t i = 0; i < 9; ++i) { + if (!blue_unit_textures[i].loadFromFile("images/pieces/blue/blue_" + + std::to_string(i + 2) + ".png")) { + std::cerr << "blue unit" + std::to_string(i + 2) + + "failed to load a texture!\n"; + abort(); + } + } + if (!blue_unit_textures[9].loadFromFile("images/pieces/blue/blue_bomb.png")) { + std::cerr << "blue bomb loading texture failed! \n"; + abort(); + } + if (!blue_unit_textures[10].loadFromFile( + "images/pieces/blue/blue_flag.png")) { + std::cerr << "blue flag loading texture failed! \n"; + abort(); + } + if (!blue_unit_textures[11].loadFromFile("images/pieces/blue/blue_spy.png")) { + std::cerr << "blue spy loading texture failed! \n"; + abort(); + } + if (!blue_back_texture.loadFromFile("images/pieces/blue/blue_back.png")) { + std::cerr << "blue back loading texture failed! \n"; + abort(); + } } void GameView::set_blue_units_sprites() { - for (size_t i = 0; i < blue_units_sprites.size(); ++i) { - blue_units_sprites[i].setTexture(blue_unit_textures[i]); - } - blue_back_sprite.setTexture(blue_back_texture); + for (size_t i = 0; i < blue_units_sprites.size(); ++i) { + blue_units_sprites[i].setTexture(blue_unit_textures[i]); + } + blue_back_sprite.setTexture(blue_back_texture); } void GameView::load_red_units_textures() { - for (size_t i = 0; i < 9; ++i) { - if (!red_unit_textures[i].loadFromFile("images/pieces/red/red_" + std::to_string(i + 2) + ".png")) { - std::cerr << "red unit" + std::to_string(i + 2) + " failed to load a texture!\n"; - abort(); - } - } - if (!red_unit_textures[9].loadFromFile("images/pieces/red/red_bomb.png")) { - std::cerr << "red bomb loading texture failed! \n"; - abort(); - } - if (!red_unit_textures[10].loadFromFile("images/pieces/red/red_flag.png")) { - std::cerr << "red flag loading texture failed! \n"; - abort(); - } - if (!red_unit_textures[11].loadFromFile("images/pieces/red/red_spy.png")) { - std::cerr << "red spy loading texture failed! \n"; - abort(); - } - if (!red_back_texture.loadFromFile("images/pieces/red/red_back.png")) { - std::cerr << "red back loading texture failed! \n"; - abort(); - } + for (size_t i = 0; i < 9; ++i) { + if (!red_unit_textures[i].loadFromFile("images/pieces/red/red_" + + std::to_string(i + 2) + ".png")) { + std::cerr << "red unit" + std::to_string(i + 2) + + " failed to load a texture!\n"; + abort(); + } + } + if (!red_unit_textures[9].loadFromFile("images/pieces/red/red_bomb.png")) { + std::cerr << "red bomb loading texture failed! \n"; + abort(); + } + if (!red_unit_textures[10].loadFromFile("images/pieces/red/red_flag.png")) { + std::cerr << "red flag loading texture failed! \n"; + abort(); + } + if (!red_unit_textures[11].loadFromFile("images/pieces/red/red_spy.png")) { + std::cerr << "red spy loading texture failed! \n"; + abort(); + } + if (!red_back_texture.loadFromFile("images/pieces/red/red_back.png")) { + std::cerr << "red back loading texture failed! \n"; + abort(); + } } void GameView::set_red_units_sprites() { - for (size_t i = 0; i < red_units_sprites.size(); ++i) { - red_units_sprites[i].setTexture(red_unit_textures[i]); - } - red_back_sprite.setTexture(red_back_texture); -} - -void GameView::update_players(Player* current, Player* other) { - current_player = current; - other_player = other; - current_player_turn = current_player->get_player_number(); -} - -void GameView::draw_grass(sf::RenderWindow& win) { - for (int row = 0; row < playerA.get_board().get_height(); ++row) { - int tile_y_pos = (row + 1) * TILE_SIZE; - for (int col = 0; col < playerA.get_board().get_width(); ++col) { - int tile_x_pos = (col + 1) * TILE_SIZE; - grass_light.setPosition(tile_x_pos, tile_y_pos); - grass_dark.setPosition(tile_x_pos, tile_y_pos); - if (col % 2) { - if (row % 2) { - win.draw(grass_light); - } else { - win.draw(grass_dark); - } - - } else { - if (row % 2) { - win.draw(grass_dark); - } else { - win.draw(grass_light); - } - } - } - } -} - -void GameView::draw_obstacles(sf::RenderWindow& win) { - int i = 0; - int j = 4; - for (size_t row = 5; row < 7; ++row) { - int obstacle_y_pos = TILE_SIZE * (row + 1); - for (size_t col = 2; col < 4; ++col) { - size_t obstacle_x_pos = TILE_SIZE * (col + 1); - obstacle_sprites[i].setPosition(obstacle_x_pos, obstacle_y_pos); - win.draw(obstacle_sprites[i]); - i++; + for (size_t i = 0; i < red_units_sprites.size(); ++i) { + red_units_sprites[i].setTexture(red_unit_textures[i]); + } + red_back_sprite.setTexture(red_back_texture); +} + +void GameView::update_players(Player *current, Player *other) { + current_player = current; + other_player = other; + current_player_turn = current_player->get_player_number(); +} + +void GameView::draw_grass(sf::RenderWindow &win) { + for (int row = 0; row < playerA.get_board().get_height(); ++row) { + int tile_y_pos = (row + 1) * TILE_SIZE; + for (int col = 0; col < playerA.get_board().get_width(); ++col) { + int tile_x_pos = (col + 1) * TILE_SIZE; + grass_light.setPosition(tile_x_pos, tile_y_pos); + grass_dark.setPosition(tile_x_pos, tile_y_pos); + if (col % 2) { + if (row % 2) { + win.draw(grass_light); + } else { + win.draw(grass_dark); } - for (size_t col = 6; col < 8; ++col) { - size_t obstacle_x_pos = TILE_SIZE * (col + 1); - obstacle_sprites[j].setPosition(obstacle_x_pos, obstacle_y_pos); - win.draw(obstacle_sprites[j]); - j++; + } else { + if (row % 2) { + win.draw(grass_dark); + } else { + win.draw(grass_light); } - } -} - -void GameView::draw_units_for_init(sf::RenderWindow& win, bool is_dragging, int selected_units_idx, const mouse_data& m_data) { + } + } + } +} + +void GameView::draw_obstacles(sf::RenderWindow &win) { + int i = 0; + int j = 4; + for (size_t row = 5; row < 7; ++row) { + int obstacle_y_pos = TILE_SIZE * (row + 1); + for (size_t col = 2; col < 4; ++col) { + size_t obstacle_x_pos = TILE_SIZE * (col + 1); + obstacle_sprites[i].setPosition(obstacle_x_pos, obstacle_y_pos); + win.draw(obstacle_sprites[i]); + i++; + } + for (size_t col = 6; col < 8; ++col) { + size_t obstacle_x_pos = TILE_SIZE * (col + 1); + obstacle_sprites[j].setPosition(obstacle_x_pos, obstacle_y_pos); + win.draw(obstacle_sprites[j]); + j++; + } + } +} + +void GameView::draw_units_for_init(sf::RenderWindow &win, bool is_dragging, + int selected_units_idx, + const mouse_data &m_data) { + if (current_player_turn == Turn::PlayerA) { + draw_red_init_units(win, is_dragging, selected_units_idx, m_data); + } else { + draw_blue_init_units(win, is_dragging, selected_units_idx, m_data); + } +} + +void GameView::draw_red_init_units(sf::RenderWindow &win, bool is_dragging, + int selected_unit_idx, + const mouse_data &m_data) { + const int x_denting = board_border.getGlobalBounds().width; + const int y_denting = TILE_SIZE; + int col_count = 0; + int row_count = 0; + for (size_t i = 0; i < red_units_sprites.size(); ++i) { + if (i != 0 && i % 4 == 0) { + col_count = 0; + row_count++; + } + red_units_sprites[i].setPosition(x_denting + 2 * col_count * TILE_SIZE, + y_denting + row_count * TILE_SIZE); + text.setPosition(x_denting + TILE_SIZE + 2 * col_count * TILE_SIZE, + y_denting + TILE_SIZE / 4 + row_count * TILE_SIZE); + text.setString("x" + + std::to_string(playerA.get_board().get_max_unit_count(i) - + playerA.get_units_count(i))); + if (is_dragging == true) { + red_units_sprites[selected_unit_idx].setPosition( + m_data.mouse_x - m_data.mouse_object_offset_x, + m_data.mouse_y - m_data.mouse_object_offset_y); + } + win.draw(red_units_sprites[i]); + win.draw(text); + col_count++; + } +} + +void GameView::draw_blue_init_units(sf::RenderWindow &win, bool is_dragging, + int selected_unit_idx, + const mouse_data &m_data) { + const int x_denting = board_border.getGlobalBounds().width; + const int y_denting = TILE_SIZE; + int col_count = 0; + int row_count = 0; + for (size_t i = 0; i < blue_units_sprites.size(); ++i) { + if (i != 0 && i % 4 == 0) { + col_count = 0; + row_count++; + } + blue_units_sprites[i].setPosition(x_denting + 2 * col_count * TILE_SIZE, + y_denting + row_count * TILE_SIZE); + text.setPosition(x_denting + TILE_SIZE + 2 * col_count * TILE_SIZE, + y_denting + TILE_SIZE / 4 + row_count * TILE_SIZE); + text.setString("x" + + std::to_string(playerB.get_board().get_max_unit_count(i) - + playerB.get_units_count(i))); + if (is_dragging == true) { + blue_units_sprites[selected_unit_idx].setPosition( + m_data.mouse_x - m_data.mouse_object_offset_x, + m_data.mouse_y - m_data.mouse_object_offset_y); + } + win.draw(blue_units_sprites[i]); + win.draw(text); + col_count++; + } +} + +void GameView::draw_done_button(sf::RenderWindow &win) { + const int x_denting = board_border.getGlobalBounds().width; + done_button.set_position( + x_denting + (X_ADDITIONAL_SPACE - done_button.get_width()) / 2, + TILE_SIZE * 6); + done_button.draw(win); +} +void GameView::draw_randomize_button(sf::RenderWindow &win) { + randomize_button.set_position(done_button.get_position().x, + done_button.get_position().y + + done_button.get_height() + TILE_SIZE); + randomize_button.draw(win); +} + +void GameView::draw_remove_button(sf::RenderWindow &win) { + remove_button.set_position(randomize_button.get_position().x, + randomize_button.get_position().y + + randomize_button.get_height() + TILE_SIZE); + remove_button.draw(win); +} + +void GameView::draw_end_turn_button(sf::RenderWindow &win) { + end_turn_button.set_position(done_button.get_position()); + end_turn_button.draw(win); +} + +void GameView::draw_info_box(sf::RenderWindow &win) { + info_box.set_text(other_player->get_player_name() + "'s turn!"); + info_box.set_position((win.getSize().x - info_box.get_width()) / 2, + (win.getSize().y - info_box.get_height()) / 2); + info_box.draw(win); +} + +void GameView::draw_attack_info_box(sf::RenderWindow &win, + const std::optional &attacker, + const std::optional &attacked) { + if (!clock_started) { + clock.restart(); + clock_started = true; + } + sf::Time time_past = clock.getElapsedTime(); + attack_info_box.set_position( + (window_size.x - attack_info_box.get_width()) / 2, + (window_size.y - attack_info_box.get_height()) / 2); + attack_info_box.set_attacking_unit(attacker); + attack_info_box.set_attacked_unit(attacked); + attack_info_box.draw(win); + if (time_past.asSeconds() > 1.5) { + clock_started = false; + } +} + +void GameView::draw_units(sf::RenderWindow &win) { + for (int row = 0; row < current_player->get_board().get_height(); ++row) { + const int object_y_pos = (row + 1) * TILE_SIZE; + for (int col = 0; col < current_player->get_board().get_width(); ++col) { + const int object_x_pos = (col + 1) * TILE_SIZE; + const auto &unit = current_player->get_board().get_unit(col, row); + int unit_idx = std::visit( + overloads{ + [](const RegularUnit &runit) { return runit.get_value() - 2; }, + [](const ScoutUnit &) { return 0; }, + [](const MinerUnit &) { return 1; }, + [](const BombUnit &) { return 9; }, + [](const FlagUnit &) { return 10; }, + [](const SpyUnit &) { return 11; }, + }, + unit.value()); + if (current_player->get_tile_info(col, row) == "enemy") { + unit_idx = 12; + } + draw_sprite(win, unit_idx, object_x_pos, object_y_pos); + } + } +} + +void GameView::draw_unit_highlight(sf::RenderWindow &win, + const Tile &active_unit) { + yellow_highlight_sprite.setPosition( + return_pixels(active_unit.x, active_unit.y)); + win.draw(yellow_highlight_sprite); +} + +void GameView::draw_sprite(sf::RenderWindow &win, int idx, int sprite_pos_x, + int sprite_pos_y) { + if (idx == 12) { if (current_player_turn == Turn::PlayerA) { - draw_red_init_units(win, is_dragging, selected_units_idx, m_data); + blue_back_sprite.setPosition(sprite_pos_x, sprite_pos_y); + win.draw(blue_back_sprite); } else { - draw_blue_init_units(win, is_dragging, selected_units_idx, m_data); - } - -} - -void GameView::draw_red_init_units(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data) { - const int x_denting = board_border.getGlobalBounds().width; - const int y_denting = TILE_SIZE; - int col_count = 0; - int row_count = 0; - for (size_t i = 0; i < red_units_sprites.size(); ++i) { - if (i != 0 && i % 4 == 0) { - col_count = 0; - row_count++; - } - red_units_sprites[i].setPosition(x_denting + 2 * col_count * TILE_SIZE, y_denting + row_count * TILE_SIZE); - text.setPosition(x_denting + TILE_SIZE + 2 * col_count * TILE_SIZE, y_denting + TILE_SIZE / 4 + row_count * TILE_SIZE); - text.setString("x" + std::to_string(playerA.get_board().get_max_unit_count(i) - playerA.get_units_count(i))); - if (is_dragging == true) { - red_units_sprites[selected_unit_idx].setPosition(m_data.mouse_x - m_data.mouse_object_offset_x, m_data.mouse_y - m_data.mouse_object_offset_y); - } - win.draw(red_units_sprites[i]); - win.draw(text); - col_count++; - } -} - -void GameView::draw_blue_init_units(sf::RenderWindow& win, bool is_dragging, int selected_unit_idx, const mouse_data& m_data) { - const int x_denting = board_border.getGlobalBounds().width; - const int y_denting = TILE_SIZE; - int col_count = 0; - int row_count = 0; - for (size_t i = 0; i < blue_units_sprites.size(); ++i) { - if (i != 0 && i % 4 == 0) { - col_count = 0; - row_count++; - } - blue_units_sprites[i].setPosition(x_denting + 2 * col_count * TILE_SIZE, y_denting + row_count * TILE_SIZE); - text.setPosition(x_denting + TILE_SIZE + 2 * col_count * TILE_SIZE, y_denting + TILE_SIZE / 4 + row_count * TILE_SIZE); - text.setString("x" + std::to_string(playerB.get_board().get_max_unit_count(i) - playerB.get_units_count(i))); - if (is_dragging == true) { - blue_units_sprites[selected_unit_idx].setPosition(m_data.mouse_x - m_data.mouse_object_offset_x, m_data.mouse_y - m_data.mouse_object_offset_y); - } - win.draw(blue_units_sprites[i]); - win.draw(text); - col_count++; - } -} - -void GameView::draw_done_button(sf::RenderWindow& win) { - const int x_denting = board_border.getGlobalBounds().width; - done_button.set_position(x_denting + (X_ADDITIONAL_SPACE - done_button.get_width()) / 2, TILE_SIZE * 6); - done_button.draw(win); -} -void GameView::draw_randomize_button(sf::RenderWindow& win) { - randomize_button.set_position(done_button.get_position().x, done_button.get_position().y + done_button.get_height() + TILE_SIZE); - randomize_button.draw(win); -} - -void GameView::draw_remove_button(sf::RenderWindow& win) { - remove_button.set_position(randomize_button.get_position().x, randomize_button.get_position().y + randomize_button.get_height() + TILE_SIZE); - remove_button.draw(win); -} - -void GameView::draw_end_turn_button(sf::RenderWindow& win) { - end_turn_button.set_position(done_button.get_position()); - end_turn_button.draw(win); -} - -void GameView::draw_info_box(sf::RenderWindow& win) { - info_box.set_text(other_player->get_player_name() + "'s turn!"); - info_box.set_position((win.getSize().x - info_box.get_width()) / 2, (win.getSize().y - info_box.get_height()) / 2); - info_box.draw(win); -} - -void GameView::draw_attack_info_box(sf::RenderWindow& win, const std::optional& attacker, const std::optional& attacked) { - if (!clock_started) { - clock.restart(); - clock_started = true; - } - sf::Time time_past = clock.getElapsedTime(); - attack_info_box.set_position((window_size.x - attack_info_box.get_width()) / 2, (window_size.y - attack_info_box.get_height()) / 2); - attack_info_box.set_attacking_unit(attacker); - attack_info_box.set_attacked_unit(attacked); - attack_info_box.draw(win); - if (time_past.asSeconds() > 1.5) { - clock_started = false; - } -} - -void GameView::draw_units(sf::RenderWindow& win) { - for (int row = 0; row < current_player->get_board().get_height(); ++row) { - const int object_y_pos = (row + 1) * TILE_SIZE; - for (int col = 0; col < current_player->get_board().get_width(); ++col) { - const int object_x_pos = (col + 1) * TILE_SIZE; - const auto& unit = current_player->get_board().get_unit(col, row); - int unit_idx = std::visit(overloads{ - [](const RegularUnit& runit){ return runit.get_value() - 2; }, - [](const ScoutUnit&){ return 0; }, - [](const MinerUnit&){ return 1; }, - [](const BombUnit&){ return 9; }, - [](const FlagUnit&){ return 10; }, - [](const SpyUnit&){ return 11; }, - }, unit.value()); - if (current_player->get_tile_info(col, row) == "enemy") { - unit_idx = 12; - } - draw_sprite(win, unit_idx, object_x_pos, object_y_pos); - } + red_back_sprite.setPosition(sprite_pos_x, sprite_pos_y); + win.draw(red_back_sprite); } -} - -void GameView::draw_unit_highlight(sf::RenderWindow& win, const Tile& active_unit) { - yellow_highlight_sprite.setPosition(return_pixels(active_unit.x, active_unit.y)); - win.draw(yellow_highlight_sprite); -} - -void GameView::draw_sprite(sf::RenderWindow& win, int idx, int sprite_pos_x, int sprite_pos_y) { - if (idx == 12) { - if (current_player_turn == Turn::PlayerA) { - blue_back_sprite.setPosition(sprite_pos_x, sprite_pos_y); - win.draw(blue_back_sprite); - } else { - red_back_sprite.setPosition(sprite_pos_x, sprite_pos_y); - win.draw(red_back_sprite); - } + } else { + if (current_player_turn == Turn::PlayerA) { + sprite_initial_position = red_units_sprites[idx].getPosition(); + red_units_sprites[idx].setPosition(sprite_pos_x, sprite_pos_y); + win.draw(red_units_sprites[idx]); + red_units_sprites[idx].setPosition(sprite_initial_position); } else { - if (current_player_turn == Turn::PlayerA) { - sprite_initial_position = red_units_sprites[idx].getPosition(); - red_units_sprites[idx].setPosition(sprite_pos_x, sprite_pos_y); - win.draw(red_units_sprites[idx]); - red_units_sprites[idx].setPosition(sprite_initial_position); - } else { - sprite_initial_position = blue_units_sprites[idx].getPosition(); - blue_units_sprites[idx].setPosition(sprite_pos_x, sprite_pos_y); - win.draw(blue_units_sprites[idx]); - blue_units_sprites[idx].setPosition(sprite_initial_position); - } - } -} - -void GameView::draw_possible_moves_for_active_unit(sf::RenderWindow& win, const Tile& active_unit) { - const auto& unit = current_player->get_board().get_unit(active_unit.x, active_unit.y); - if (!unit) { - return; - } - std::visit(overloads{ - [this, &win, &active_unit](const ScoutUnit&){ highlight_scout_moves(win, active_unit); }, - [this, &win, &active_unit](const auto&){ highlight_regular_moves(win, active_unit); }, - }, unit.value()); -} - -void GameView::highlight_regular_moves(sf::RenderWindow& win, const Tile& active_unit) { - highlight_tile(win, active_unit, active_unit.x - 1, active_unit.y); - highlight_tile(win, active_unit, active_unit.x + 1, active_unit.y); - highlight_tile(win, active_unit, active_unit.x, active_unit.y + 1); - highlight_tile(win, active_unit, active_unit.x, active_unit.y - 1); -} - -void GameView::highlight_scout_moves(sf::RenderWindow& win, const Tile& active_unit) { - for (int col = active_unit.x + 1; col < current_player->get_board().get_width(); ++col) { - if (!highlight_tile(win, active_unit, col, active_unit.y)) { - break; - } - } - for (int col = active_unit.x - 1; col >= 0; --col) { - if (!highlight_tile(win, active_unit, col, active_unit.y)) { - break; - } - } - for (int row = active_unit.y + 1; row < current_player->get_board().get_height(); ++row) { - if (!highlight_tile(win, active_unit, active_unit.x, row)) { - break; - } - } - for (int row = active_unit.y - 1; row >= 0; --row) { - if (!highlight_tile(win, active_unit, active_unit.x, row)) { - break; - } - } -} - -bool GameView::highlight_tile(sf::RenderWindow& win, const Tile& active_unit, int to_x, int to_y) { - if (check_if_viable(active_unit, to_x, to_y)) { - if (current_player->get_tile_info(to_x, to_y) == "enemy") { - red_highlight_sprite.setPosition(return_pixels(to_x, to_y)); - win.draw(red_highlight_sprite); - return false; - } else { - green_highlight_sprite.setPosition(return_pixels(to_x, to_y)); - win.draw(green_highlight_sprite); - } - return true; + sprite_initial_position = blue_units_sprites[idx].getPosition(); + blue_units_sprites[idx].setPosition(sprite_pos_x, sprite_pos_y); + win.draw(blue_units_sprites[idx]); + blue_units_sprites[idx].setPosition(sprite_initial_position); + } + } +} + +void GameView::draw_possible_moves_for_active_unit(sf::RenderWindow &win, + const Tile &active_unit) { + const auto &unit = + current_player->get_board().get_unit(active_unit.x, active_unit.y); + if (!unit) { + return; + } + std::visit(overloads{ + [this, &win, &active_unit](const ScoutUnit &) { + highlight_scout_moves(win, active_unit); + }, + [this, &win, &active_unit](const auto &) { + highlight_regular_moves(win, active_unit); + }, + }, + unit.value()); +} + +void GameView::highlight_regular_moves(sf::RenderWindow &win, + const Tile &active_unit) { + highlight_tile(win, active_unit, active_unit.x - 1, active_unit.y); + highlight_tile(win, active_unit, active_unit.x + 1, active_unit.y); + highlight_tile(win, active_unit, active_unit.x, active_unit.y + 1); + highlight_tile(win, active_unit, active_unit.x, active_unit.y - 1); +} + +void GameView::highlight_scout_moves(sf::RenderWindow &win, + const Tile &active_unit) { + for (int col = active_unit.x + 1; + col < current_player->get_board().get_width(); ++col) { + if (!highlight_tile(win, active_unit, col, active_unit.y)) { + break; + } + } + for (int col = active_unit.x - 1; col >= 0; --col) { + if (!highlight_tile(win, active_unit, col, active_unit.y)) { + break; + } + } + for (int row = active_unit.y + 1; + row < current_player->get_board().get_height(); ++row) { + if (!highlight_tile(win, active_unit, active_unit.x, row)) { + break; + } + } + for (int row = active_unit.y - 1; row >= 0; --row) { + if (!highlight_tile(win, active_unit, active_unit.x, row)) { + break; + } + } +} + +bool GameView::highlight_tile(sf::RenderWindow &win, const Tile &active_unit, + int to_x, int to_y) { + if (check_if_viable(active_unit, to_x, to_y)) { + if (current_player->get_tile_info(to_x, to_y) == "enemy") { + red_highlight_sprite.setPosition(return_pixels(to_x, to_y)); + win.draw(red_highlight_sprite); + return false; + } else { + green_highlight_sprite.setPosition(return_pixels(to_x, to_y)); + win.draw(green_highlight_sprite); } - return false; + return true; + } + return false; } bool GameView::check_if_viable(Tile from, int to_x, int to_y) { - return current_player->can_move(from, Tile(to_x, to_y)); + return current_player->can_move(from, Tile(to_x, to_y)); } -void GameView::draw_end_game_screen(sf::RenderWindow& win, const std::string& victorious_name) { - end_game_info_box.set_text("Congratulations " + victorious_name + " you won!\n"); - end_game_info_box.set_position(info_box.get_position()); - end_game_info_box.draw(win); +void GameView::draw_end_game_screen(sf::RenderWindow &win, + const std::string &victorious_name) { + end_game_info_box.set_text("Congratulations " + victorious_name + + " you won!\n"); + end_game_info_box.set_position(info_box.get_position()); + end_game_info_box.draw(win); } -void GameView::draw_board_border(sf::RenderWindow& win) { - win.draw(board_border); +void GameView::draw_board_border(sf::RenderWindow &win) { + win.draw(board_border); } sf::Vector2f GameView::return_pixels(int col, int row) const { - if (col < 0 && row < 0) { - return sf::Vector2f{-1, -1}; - } - return sf::Vector2f(TILE_SIZE * (col + 1), TILE_SIZE * (row + 1)); + if (col < 0 && row < 0) { + return sf::Vector2f{-1, -1}; + } + return sf::Vector2f(TILE_SIZE * (col + 1), TILE_SIZE * (row + 1)); } -Tile GameView::return_tile(const sf::Vector2f& coords) const { - return Tile((coords.x - TILE_SIZE) / TILE_SIZE, (coords.y - TILE_SIZE) / TILE_SIZE); +Tile GameView::return_tile(const sf::Vector2f &coords) const { + return Tile((coords.x - TILE_SIZE) / TILE_SIZE, + (coords.y - TILE_SIZE) / TILE_SIZE); } Tile GameView::return_tile(int x, int y) const { - if (x < 0 && y < 0) { - return Tile{-1, -1}; - } - return return_tile(sf::Vector2f(x, y)); + if (x < 0 && y < 0) { + return Tile{-1, -1}; + } + return return_tile(sf::Vector2f(x, y)); } void GameView::set_button_highlights(int mouse_x, int mouse_y) { - if (done_button.contains(mouse_x, mouse_y)) { - done_button.highlight_on(); - } else { - done_button.highlight_off(); - } - if (randomize_button.contains(mouse_x, mouse_y)) { - randomize_button.highlight_on(); - } else { - randomize_button.highlight_off(); - } - if (remove_button.contains(mouse_x, mouse_y)) { - remove_button.highlight_on(); - } else { - remove_button.highlight_off(); - } - if (end_turn_button.contains(mouse_x, mouse_y)) { - end_turn_button.highlight_on(); - } else { - end_turn_button.highlight_off(); - } - if (info_box.button_contains(mouse_x, mouse_y)) { - info_box.set_button_highlight_on(); - } else { - info_box.set_button_highlight_off(); - } - if (end_game_info_box.button_contains(mouse_x, mouse_y)) { - end_game_info_box.set_button_highlight_on(); - } else { - end_game_info_box.set_button_highlight_off(); - } + if (done_button.contains(mouse_x, mouse_y)) { + done_button.highlight_on(); + } else { + done_button.highlight_off(); + } + if (randomize_button.contains(mouse_x, mouse_y)) { + randomize_button.highlight_on(); + } else { + randomize_button.highlight_off(); + } + if (remove_button.contains(mouse_x, mouse_y)) { + remove_button.highlight_on(); + } else { + remove_button.highlight_off(); + } + if (end_turn_button.contains(mouse_x, mouse_y)) { + end_turn_button.highlight_on(); + } else { + end_turn_button.highlight_off(); + } + if (info_box.button_contains(mouse_x, mouse_y)) { + info_box.set_button_highlight_on(); + } else { + info_box.set_button_highlight_off(); + } + if (end_game_info_box.button_contains(mouse_x, mouse_y)) { + end_game_info_box.set_button_highlight_on(); + } else { + end_game_info_box.set_button_highlight_off(); + } } \ No newline at end of file diff --git a/src/MainMenu.cpp b/src/MainMenu.cpp index eb8d7d7..eeda44a 100644 --- a/src/MainMenu.cpp +++ b/src/MainMenu.cpp @@ -1,240 +1,247 @@ #include "MainMenu.hpp" -MainMenu::MainMenu(Player& pA, Player& pB) - : playerA(pA), - playerB(pB), - start_game_button("Start Game"), - game_rules_button("Game Rules"), - exit_button("Exit The Game"), - next("Next"), - prev("Previous"), - names_entered(false), - game_started_button_pressed(false), - rules_button_pressed(false), - exit_button_pressed(false), - next_button_pressed(false), - prev_button_pressed(false), - player_1_name_approved(false), - player_2_name_approved(false), - entering_from_menu(true), - path_to_textures("images/board/"), - idx(0) { - for (size_t i = 0; i < rules_textures.size(); ++i) { - if (!rules_textures[i].loadFromFile(path_to_textures + "rules#" + std::to_string(i + 1) + ".png")) { - std::cerr << "rules#" + std::to_string(i + 1) + " texture failed to load!\n"; - abort(); - } - rules_sprites[i].setTexture(rules_textures[i]); - } - if (!logo_texture.loadFromFile(path_to_textures + "stratego_logo.png")) { - std::cerr << "logo texture failed to load!\n"; - abort(); - } - logo_sprite.setTexture(logo_texture); +MainMenu::MainMenu(Player &pA, Player &pB) + : playerA(pA), playerB(pB), start_game_button("Start Game"), + game_rules_button("Game Rules"), exit_button("Exit The Game"), + next("Next"), prev("Previous"), names_entered(false), + game_started_button_pressed(false), rules_button_pressed(false), + exit_button_pressed(false), next_button_pressed(false), + prev_button_pressed(false), player_1_name_approved(false), + player_2_name_approved(false), entering_from_menu(true), + path_to_textures("images/board/"), idx(0) { + for (size_t i = 0; i < rules_textures.size(); ++i) { + if (!rules_textures[i].loadFromFile(path_to_textures + "rules#" + + std::to_string(i + 1) + ".png")) { + std::cerr << "rules#" + std::to_string(i + 1) + + " texture failed to load!\n"; + abort(); + } + rules_sprites[i].setTexture(rules_textures[i]); + } + if (!logo_texture.loadFromFile(path_to_textures + "stratego_logo.png")) { + std::cerr << "logo texture failed to load!\n"; + abort(); + } + logo_sprite.setTexture(logo_texture); } -std::string MainMenu::run(sf::RenderWindow& win) { - while (true) { - sf::Event event; - while (win.pollEvent(event)) { - if (event.type == sf::Event::Closed) { - return "exit"; //will exit the application in the main function - } - if (event.type == sf::Event::MouseButtonPressed) { - set_buttons_pressed(); - if (names_entered && game_started_button_pressed) { - game_started_button_pressed = false; - return "game"; - } - if (exit_button.is_highlighted() && exit_button_pressed) { - return "exit"; - } - } - if (event.type == sf::Event::MouseMoved) { - highlight_buttons(event.mouseMove.x, event.mouseMove.y); - } - enter_names(event); - } - win.clear(); - if (rules_button_pressed) { - draw_rules(win); - } - if (!game_started_button_pressed && !rules_button_pressed) { - draw_menu(win); - } - if (game_started_button_pressed) { - draw_names(win); +std::string MainMenu::run(sf::RenderWindow &win) { + while (true) { + sf::Event event; + while (win.pollEvent(event)) { + if (event.type == sf::Event::Closed) { + return "exit"; // will exit the application in the main function + } + if (event.type == sf::Event::MouseButtonPressed) { + set_buttons_pressed(); + if (names_entered && game_started_button_pressed) { + game_started_button_pressed = false; + return "game"; } - - win.display(); - } -} - -void MainMenu::set_buttons_pressed() { - if (start_game_button.is_highlighted() && !rules_button_pressed && !exit_button_pressed) { - game_started_button_pressed = true; - } - if (player_1_name.button_is_highlighted() && !player_1_name_approved) { - if (nickname.size() > 3) { - playerA.set_name(nickname); - nickname.clear(); - player_1_name_approved = true; + if (exit_button.is_highlighted() && exit_button_pressed) { + return "exit"; } + } + if (event.type == sf::Event::MouseMoved) { + highlight_buttons(event.mouseMove.x, event.mouseMove.y); + } + enter_names(event); } - if (player_2_name.button_is_highlighted() && !player_2_name_approved) { - if (nickname.size() > 3) { - playerB.set_name(nickname); - nickname.clear(); - player_2_name_approved = true; - names_entered = true; - } - } - if (game_rules_button.is_highlighted() && !game_started_button_pressed && !exit_button_pressed) { - rules_button_pressed = true; - } + win.clear(); if (rules_button_pressed) { - if (next.is_highlighted()) { - next_button_pressed = true; - } - if (prev.is_highlighted()) { - prev_button_pressed = true; - } + draw_rules(win); + } + if (!game_started_button_pressed && !rules_button_pressed) { + draw_menu(win); } - if (exit_button.is_highlighted() && !game_started_button_pressed && !rules_button_pressed) { - exit_button_pressed = true; + if (game_started_button_pressed) { + draw_names(win); } + + win.display(); + } } -void MainMenu::draw_menu(sf::RenderWindow& win) { - logo_sprite.setPosition((win.getSize().x - logo_sprite.getLocalBounds().width) / 2, - 0.8 * start_game_button.get_height()); - start_game_button.set_position((win.getSize().x - start_game_button.get_width()) / 2, - (logo_sprite.getPosition().y + 1.5 * start_game_button.get_height())); - game_rules_button.set_position(start_game_button.get_position().x, - start_game_button.get_position().y + 1.25 * game_rules_button.get_height()); - exit_button.set_position(game_rules_button.get_position().x, - game_rules_button.get_position().y + 1.25 * exit_button.get_height()); +void MainMenu::set_buttons_pressed() { + if (start_game_button.is_highlighted() && !rules_button_pressed && + !exit_button_pressed) { + game_started_button_pressed = true; + } + if (player_1_name.button_is_highlighted() && !player_1_name_approved) { + if (nickname.size() > 3) { + playerA.set_name(nickname); + nickname.clear(); + player_1_name_approved = true; + } + } + if (player_2_name.button_is_highlighted() && !player_2_name_approved) { + if (nickname.size() > 3) { + playerB.set_name(nickname); + nickname.clear(); + player_2_name_approved = true; + names_entered = true; + } + } + if (game_rules_button.is_highlighted() && !game_started_button_pressed && + !exit_button_pressed) { + rules_button_pressed = true; + } + if (rules_button_pressed) { + if (next.is_highlighted()) { + next_button_pressed = true; + } + if (prev.is_highlighted()) { + prev_button_pressed = true; + } + } + if (exit_button.is_highlighted() && !game_started_button_pressed && + !rules_button_pressed) { + exit_button_pressed = true; + } +} - win.draw(logo_sprite); - start_game_button.draw(win); - game_rules_button.draw(win); - exit_button.draw(win); +void MainMenu::draw_menu(sf::RenderWindow &win) { + logo_sprite.setPosition( + (win.getSize().x - logo_sprite.getLocalBounds().width) / 2, + 0.8 * start_game_button.get_height()); + start_game_button.set_position( + (win.getSize().x - start_game_button.get_width()) / 2, + (logo_sprite.getPosition().y + 1.5 * start_game_button.get_height())); + game_rules_button.set_position(start_game_button.get_position().x, + start_game_button.get_position().y + + 1.25 * game_rules_button.get_height()); + exit_button.set_position(game_rules_button.get_position().x, + game_rules_button.get_position().y + + 1.25 * exit_button.get_height()); + + win.draw(logo_sprite); + start_game_button.draw(win); + game_rules_button.draw(win); + exit_button.draw(win); } -void MainMenu::draw_names(sf::RenderWindow& win) { - if (!player_1_name_approved) { - player_1_name.set_text("Red Player's Name: " + nickname); - player_1_name.set_position((win.getSize().x - player_1_name.get_width()) / 2, - (win.getSize().y - player_1_name.get_height()) / 2); - player_1_name.draw(win); - } - if (player_1_name_approved && !player_2_name_approved) { - player_2_name.set_text("Blue Player's Name: " + nickname); - player_2_name.set_position(player_1_name.get_position()); - player_2_name.draw(win); - } +void MainMenu::draw_names(sf::RenderWindow &win) { + if (!player_1_name_approved) { + player_1_name.set_text("Red Player's Name: " + nickname); + player_1_name.set_position( + (win.getSize().x - player_1_name.get_width()) / 2, + (win.getSize().y - player_1_name.get_height()) / 2); + player_1_name.draw(win); + } + if (player_1_name_approved && !player_2_name_approved) { + player_2_name.set_text("Blue Player's Name: " + nickname); + player_2_name.set_position(player_1_name.get_position()); + player_2_name.draw(win); + } } -void MainMenu::draw_rules(sf::RenderWindow& win) { - if (entering_from_menu) { - entering_from_menu = false; - idx = 0; - prev.set_text("Menu"); - } - if (idx > 0) { - prev.set_text("Previous"); - } - if (idx == 0) { - prev.set_text("Menu"); - } - next.set_position(win.getSize().x - 1.25 * next.get_width(), win.getSize().y - 1.75 * next.get_height()); - prev.set_position(0.25 * next.get_width(), win.getSize().y - 1.75 * next.get_height()); - draw_rule(win, idx); - if (next_button_pressed) { - if (idx < 4) { - idx++; - } - next_button_pressed = false; - } - if (prev_button_pressed && prev.get_text() != "Menu") { - if (idx > 0) { - idx--; - } else if (idx == 0) { - prev.set_text("Menu"); - } - prev_button_pressed = false; - } - if (prev_button_pressed && prev.get_text() == "Menu") { - prev_button_pressed = false; - rules_button_pressed = false; - game_started_button_pressed = false; - entering_from_menu = true; - return; - } +void MainMenu::draw_rules(sf::RenderWindow &win) { + if (entering_from_menu) { + entering_from_menu = false; + idx = 0; + prev.set_text("Menu"); + } + if (idx > 0) { + prev.set_text("Previous"); + } + if (idx == 0) { + prev.set_text("Menu"); + } + next.set_position(win.getSize().x - 1.25 * next.get_width(), + win.getSize().y - 1.75 * next.get_height()); + prev.set_position(0.25 * next.get_width(), + win.getSize().y - 1.75 * next.get_height()); + draw_rule(win, idx); + if (next_button_pressed) { if (idx < 4) { - next.draw(win); + idx++; } - prev.draw(win); + next_button_pressed = false; + } + if (prev_button_pressed && prev.get_text() != "Menu") { + if (idx > 0) { + idx--; + } else if (idx == 0) { + prev.set_text("Menu"); + } + prev_button_pressed = false; + } + if (prev_button_pressed && prev.get_text() == "Menu") { + prev_button_pressed = false; + rules_button_pressed = false; + game_started_button_pressed = false; + entering_from_menu = true; + return; + } + if (idx < 4) { + next.draw(win); + } + prev.draw(win); } -void MainMenu::draw_rule(sf::RenderWindow& win, int idx) { - if (idx < 0) { - return; - } - int rules_x_pos = (win.getSize().x - rules_sprites[idx].getLocalBounds().width) / 2; - int rules_y_pos = (win.getSize().y - rules_sprites[idx].getLocalBounds().height) / 2; - rules_sprites[idx].setPosition(rules_x_pos, rules_y_pos); - win.draw(rules_sprites[idx]); +void MainMenu::draw_rule(sf::RenderWindow &win, int idx) { + if (idx < 0) { + return; + } + int rules_x_pos = + (win.getSize().x - rules_sprites[idx].getLocalBounds().width) / 2; + int rules_y_pos = + (win.getSize().y - rules_sprites[idx].getLocalBounds().height) / 2; + rules_sprites[idx].setPosition(rules_x_pos, rules_y_pos); + win.draw(rules_sprites[idx]); } void MainMenu::highlight_buttons(int mouse_x, int mouse_y) { - if (start_game_button.contains(mouse_x, mouse_y)) { - start_game_button.highlight_on(); - } else { - start_game_button.highlight_off(); - } - if (game_rules_button.contains(mouse_x, mouse_y)) { - game_rules_button.highlight_on(); - } else { - game_rules_button.highlight_off(); - } - if (exit_button.contains(mouse_x, mouse_y)) { - exit_button.highlight_on(); - } else { - exit_button.highlight_off(); - } - if (player_1_name.button_contains(mouse_x, mouse_y) && game_started_button_pressed) { - player_1_name.set_button_highlight_on(); - } else { - player_1_name.set_button_highlight_off(); - } - if (player_2_name.button_contains(mouse_x, mouse_y) && player_1_name_approved) { - player_2_name.set_button_highlight_on(); - } else { - player_2_name.set_button_highlight_off(); - } - if (next.contains(mouse_x, mouse_y)) { - next.highlight_on(); - } else { - next.highlight_off(); - } - if (prev.contains(mouse_x, mouse_y)) { - prev.highlight_on(); - } else { - prev.highlight_off(); - } + if (start_game_button.contains(mouse_x, mouse_y)) { + start_game_button.highlight_on(); + } else { + start_game_button.highlight_off(); + } + if (game_rules_button.contains(mouse_x, mouse_y)) { + game_rules_button.highlight_on(); + } else { + game_rules_button.highlight_off(); + } + if (exit_button.contains(mouse_x, mouse_y)) { + exit_button.highlight_on(); + } else { + exit_button.highlight_off(); + } + if (player_1_name.button_contains(mouse_x, mouse_y) && + game_started_button_pressed) { + player_1_name.set_button_highlight_on(); + } else { + player_1_name.set_button_highlight_off(); + } + if (player_2_name.button_contains(mouse_x, mouse_y) && + player_1_name_approved) { + player_2_name.set_button_highlight_on(); + } else { + player_2_name.set_button_highlight_off(); + } + if (next.contains(mouse_x, mouse_y)) { + next.highlight_on(); + } else { + next.highlight_off(); + } + if (prev.contains(mouse_x, mouse_y)) { + prev.highlight_on(); + } else { + prev.highlight_off(); + } } -void MainMenu::enter_names(sf::Event& event) { - if (!game_started_button_pressed) { - return; - } - if (event.type == sf::Event::TextEntered) { - if (event.text.unicode > 31 && event.text.unicode < 128 && nickname.size() < 21) { - nickname += event.text.unicode; - } - if (event.text.unicode == '\b' && !nickname.empty()) { - nickname.pop_back(); - } - } +void MainMenu::enter_names(sf::Event &event) { + if (!game_started_button_pressed) { + return; + } + if (event.type == sf::Event::TextEntered) { + if (event.text.unicode > 31 && event.text.unicode < 128 && + nickname.size() < 21) { + nickname += event.text.unicode; + } + if (event.text.unicode == '\b' && !nickname.empty()) { + nickname.pop_back(); + } + } } diff --git a/src/Player.cpp b/src/Player.cpp index 39a8397..15e41af 100644 --- a/src/Player.cpp +++ b/src/Player.cpp @@ -7,89 +7,87 @@ #include "unit/visit/GetOwner.hpp" void Player::set_unit(int col, int row, int choice) { - board.set_unit(col, row, player, choice); + board.set_unit(col, row, player, choice); } void Player::remove_unit(int col, int row) { - if (board.get_unit(col, row)) { - board.remove_unit(col, row); - } + if (board.get_unit(col, row)) { + board.remove_unit(col, row); + } } void Player::remove_unit(Tile chosen_unit) { - remove_unit(chosen_unit.x, chosen_unit.y); + remove_unit(chosen_unit.x, chosen_unit.y); } void Player::reverse_remove_unit(Tile unit) { - board.reverse_remove_unit(unit.x, unit.y); + board.reverse_remove_unit(unit.x, unit.y); } -bool Player::move_unit(Tile from, Tile to) { - return board.move_unit(from, to); -} +bool Player::move_unit(Tile from, Tile to) { return board.move_unit(from, to); } attack::Result Player::attack(Tile attacker, Tile attacked) { - // TODO: make the actual implementation a strategy (use dependency injection) - const auto& attacker_unit = board.get_unit(attacker); - const auto& attacked_unit = board.get_unit(attacked); - return std::visit(Attack{}, attacker_unit.value(), attacked_unit.value()); + // TODO: make the actual implementation a strategy (use dependency injection) + const auto &attacker_unit = board.get_unit(attacker); + const auto &attacked_unit = board.get_unit(attacked); + return std::visit(Attack{}, attacker_unit.value(), attacked_unit.value()); } void Player::reverse_move_unit(Tile from, Tile to) { - board.reverse_move_unit(from, to); + board.reverse_move_unit(from, to); } bool Player::can_move(Tile from, Tile to) { - if (board.get_tile_info(to.x, to.y, player) == "#") { - return false; - } - if (board.get_tile_info(to.x, to.y, player) == "O") { - return false; - } - if (board.get_unit(to.x, to.y)) { - if (std::visit(GetOwner{}, board.get_unit(to.x, to.y).value()) == player) { - return false; - } - } - if (!board.can_move(from, to)) { - return false; + if (board.get_tile_info(to.x, to.y, player) == "#") { + return false; + } + if (board.get_tile_info(to.x, to.y, player) == "O") { + return false; + } + if (board.get_unit(to.x, to.y)) { + if (std::visit(GetOwner{}, board.get_unit(to.x, to.y).value()) == player) { + return false; } + } + if (!board.can_move(from, to)) { + return false; + } - return true; + return true; } -void Player::update_board(const Board& other_player_board) { - board.update(other_player_board); +void Player::update_board(const Board &other_player_board) { + board.update(other_player_board); } std::string Player::get_tile_info(int col, int row) const { - return board.get_tile_info(col, row, player); + return board.get_tile_info(col, row, player); } std::string Player::get_tile_info(Tile tile) const { - return board.get_tile_info(tile, player); + return board.get_tile_info(tile, player); } int Player::get_units_count(int idx) { - switch (idx) { - case 0: - return ScoutUnit::get_count(); - case 1: - return MinerUnit::get_count(); - case 2: - case 3: - case 4: - case 5: - case 6: - case 7: - case 8: - return RegularUnit::get_count(idx + 2); - case 9: - return BombUnit::get_count(); - case 10: - return FlagUnit::get_count(); - case 11: - return SpyUnit::get_count(); - } - return -1; + switch (idx) { + case 0: + return ScoutUnit::get_count(); + case 1: + return MinerUnit::get_count(); + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + return RegularUnit::get_count(idx + 2); + case 9: + return BombUnit::get_count(); + case 10: + return FlagUnit::get_count(); + case 11: + return SpyUnit::get_count(); + } + return -1; } diff --git a/src/main.cpp b/src/main.cpp index e10991c..6e3cb8a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -8,21 +8,23 @@ #include "unit/RegularUnit.hpp" int main() { - Board board; - Player playerA("Red-A", Turn::PlayerA); - Player playerB("Blue-B", Turn::PlayerB); - GameView game_view(playerA, playerB); - GameController game_controller(playerA, playerB, game_view); - Game game(game_view, game_controller); - MainMenu menu(playerA, playerB); - std::map screens; - screens["menu"] = &menu; - screens["game"] = &game; - std::string screen = "menu"; - const unsigned int width = static_cast(game_view.get_window_size().x); - const unsigned int height = static_cast(game_view.get_window_size().y); - sf::RenderWindow window(sf::VideoMode(width, height), "stratego"); - while(screen != "exit") { - screen = screens[screen]->run(window); - } + Board board; + Player playerA("Red-A", Turn::PlayerA); + Player playerB("Blue-B", Turn::PlayerB); + GameView game_view(playerA, playerB); + GameController game_controller(playerA, playerB, game_view); + Game game(game_view, game_controller); + MainMenu menu(playerA, playerB); + std::map screens; + screens["menu"] = &menu; + screens["game"] = &game; + std::string screen = "menu"; + const unsigned int width = + static_cast(game_view.get_window_size().x); + const unsigned int height = + static_cast(game_view.get_window_size().y); + sf::RenderWindow window(sf::VideoMode(width, height), "stratego"); + while (screen != "exit") { + screen = screens[screen]->run(window); + } } diff --git a/src/unit/BombUnit.cpp b/src/unit/BombUnit.cpp index 1ba222c..f0a36dc 100644 --- a/src/unit/BombUnit.cpp +++ b/src/unit/BombUnit.cpp @@ -1,4 +1,3 @@ #include "unit/BombUnit.hpp" -BombUnit::BombUnit(Turn player) - : model_(-1, "bomb", player) {}; +BombUnit::BombUnit(Turn player) : model_(-1, "bomb", player) {}; diff --git a/src/unit/FlagUnit.cpp b/src/unit/FlagUnit.cpp index 63da6ae..d73cde0 100644 --- a/src/unit/FlagUnit.cpp +++ b/src/unit/FlagUnit.cpp @@ -1,4 +1,3 @@ #include "unit/FlagUnit.hpp" -FlagUnit::FlagUnit(Turn player) - : model_(-1, "flag", player) {}; +FlagUnit::FlagUnit(Turn player) : model_(-1, "flag", player) {}; diff --git a/src/unit/MinerUnit.cpp b/src/unit/MinerUnit.cpp index af1a6b3..3c39bff 100644 --- a/src/unit/MinerUnit.cpp +++ b/src/unit/MinerUnit.cpp @@ -1,5 +1,3 @@ #include "unit/MinerUnit.hpp" -MinerUnit::MinerUnit(Turn player) - : model_(3, "miner", player) {} - \ No newline at end of file +MinerUnit::MinerUnit(Turn player) : model_(3, "miner", player) {} diff --git a/src/unit/ScoutUnit.cpp b/src/unit/ScoutUnit.cpp index 88a4773..8b1fd80 100644 --- a/src/unit/ScoutUnit.cpp +++ b/src/unit/ScoutUnit.cpp @@ -1,4 +1,3 @@ #include "unit/ScoutUnit.hpp" -ScoutUnit::ScoutUnit(Turn player) - : model_(2, "scout", player) {}; +ScoutUnit::ScoutUnit(Turn player) : model_(2, "scout", player) {}; diff --git a/src/unit/SpyUnit.cpp b/src/unit/SpyUnit.cpp index c2dde45..fb37f14 100644 --- a/src/unit/SpyUnit.cpp +++ b/src/unit/SpyUnit.cpp @@ -1,4 +1,3 @@ #include "unit/SpyUnit.hpp" -SpyUnit::SpyUnit(Turn player) - : model_(1, "spy", player) {}; +SpyUnit::SpyUnit(Turn player) : model_(1, "spy", player) {}; diff --git a/src/unit/UnitCounter.cpp b/src/unit/UnitCounter.cpp index ab0091a..d22a7ef 100644 --- a/src/unit/UnitCounter.cpp +++ b/src/unit/UnitCounter.cpp @@ -1,48 +1,58 @@ -#pragma once +#pragma once -#include "unit/RegularUnit.hpp" #include "unit/UnitCounter.hpp" -#include #include +#include + +#include "unit/RegularUnit.hpp" std::unordered_map RegularUnitCounter::count_ = {}; struct RegularUnitMaxCount { - int operator()(int unit_value) { - switch (unit_value) { - case 4: - case 5: - case 6: - return 4; - case 7: - return 3; - case 8: - return 2; - case 9: - return 1; - case 10: - return 1; - default: - break; - } - std::cerr << "Unexpected unit value: " << unit_value << ", returning max count 0\n"; - return 0; + int operator()(int unit_value) { + switch (unit_value) { + case 4: + case 5: + case 6: + return 4; + case 7: + return 3; + case 8: + return 2; + case 9: + return 1; + case 10: + return 1; + default: + break; } + std::cerr << "Unexpected unit value: " << unit_value + << ", returning max count 0\n"; + return 0; + } }; -RegularUnitCounter::RegularUnitCounter(const int unit_value) : unit_value_(unit_value) { ++count_[unit_value]; } -RegularUnitCounter::RegularUnitCounter(const RegularUnitCounter& rhs) : RegularUnitCounter(rhs.unit_value_) {} -RegularUnitCounter& RegularUnitCounter::operator=(const RegularUnitCounter& rhs) { - if (this != &rhs) { - unit_value_ = rhs.unit_value_; - ++count_[unit_value_]; - } - return *this; +RegularUnitCounter::RegularUnitCounter(const int unit_value) + : unit_value_(unit_value) { + ++count_[unit_value]; +} +RegularUnitCounter::RegularUnitCounter(const RegularUnitCounter &rhs) + : RegularUnitCounter(rhs.unit_value_) {} +RegularUnitCounter & +RegularUnitCounter::operator=(const RegularUnitCounter &rhs) { + if (this != &rhs) { + unit_value_ = rhs.unit_value_; + ++count_[unit_value_]; + } + return *this; }; -RegularUnitCounter::RegularUnitCounter(RegularUnitCounter&&) = default; -RegularUnitCounter& RegularUnitCounter::operator=(RegularUnitCounter&&) = default; +RegularUnitCounter::RegularUnitCounter(RegularUnitCounter &&) = default; +RegularUnitCounter & +RegularUnitCounter::operator=(RegularUnitCounter &&) = default; RegularUnitCounter::~RegularUnitCounter() { --count_[unit_value_]; } int RegularUnitCounter::get_count(const int value) { return count_[value]; } -int RegularUnitCounter::get_max_count(const int value) { return RegularUnitMaxCount{}(value); } \ No newline at end of file +int RegularUnitCounter::get_max_count(const int value) { + return RegularUnitMaxCount{}(value); +} \ No newline at end of file diff --git a/src/unit/UnitModel.cpp b/src/unit/UnitModel.cpp index 57e45b1..fb8c7b1 100644 --- a/src/unit/UnitModel.cpp +++ b/src/unit/UnitModel.cpp @@ -1,12 +1,11 @@ #include "unit/UnitModel.hpp" -UnitModel::UnitModel(int value, std::string type, Turn player) -: value_(value), - type_(std::move(type)), - owner_(player) {} - +UnitModel::UnitModel(int value, std::string type, Turn player) + : value_(value), type_(std::move(type)), owner_(player) {} int UnitModel::get_value() const noexcept { return value_; } -[[deprecated("Future refactoring will remove get_type()")]] -std::string UnitModel::get_type() const noexcept { return type_; } +[[deprecated("Future refactoring will remove get_type()")]] +std::string UnitModel::get_type() const noexcept { + return type_; +} Turn UnitModel::get_owner() const noexcept { return owner_; } \ No newline at end of file From bf7e08b6e115b253f0aeb1c4311401ea5e5afd0e Mon Sep 17 00:00:00 2001 From: Wojciech Matusiak <62173407+WojtekMs@users.noreply.github.com> Date: Sun, 23 Mar 2025 17:27:55 +0100 Subject: [PATCH 07/11] Remove max count unit map in Board It is no longer needed after UnitCounter improvement --- include/Board.hpp | 1 - src/Board.cpp | 13 +------------ 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/include/Board.hpp b/include/Board.hpp index 4715c95..d8800dc 100644 --- a/include/Board.hpp +++ b/include/Board.hpp @@ -28,7 +28,6 @@ class Board { int unit_count{}; Array2D> units; std::array obstacles; - const std::map max_count_of_each_unit; void set_default_units(); void set_obstacles(); diff --git a/src/Board.cpp b/src/Board.cpp index be1d7bc..39c6a08 100644 --- a/src/Board.cpp +++ b/src/Board.cpp @@ -16,18 +16,7 @@ Board::Board() : height(12), width(10), current_state(State::Uninitialized), unit_count(0), - units(width, height), max_count_of_each_unit({{"flag", 1}, - {"scout", 8}, - {"miner", 5}, - {"bomb", 6}, - {"spy", 1}, - {"regular4", 4}, - {"regular5", 4}, - {"regular6", 4}, - {"regular7", 3}, - {"regular8", 2}, - {"regular9", 1}, - {"regular10", 1}}) { + units(width, height) { set_obstacles(); set_default_units(); } From c333ea051c3281dbab8147f864d76af378ceed17 Mon Sep 17 00:00:00 2001 From: Wojciech Matusiak <62173407+WojtekMs@users.noreply.github.com> Date: Sun, 23 Mar 2025 18:08:48 +0100 Subject: [PATCH 08/11] Fix compilation errors --- include/AttackInfoBox.hpp | 9 +++++---- include/Box.hpp | 8 ++++---- include/ButtonInterface.hpp | 2 +- include/unit/RegularUnit.hpp | 2 +- src/AttackInfoBox.cpp | 12 ++++++------ src/Box.cpp | 18 +++++++++--------- 6 files changed, 26 insertions(+), 25 deletions(-) diff --git a/include/AttackInfoBox.hpp b/include/AttackInfoBox.hpp index 8b00a08..b8d3665 100644 --- a/include/AttackInfoBox.hpp +++ b/include/AttackInfoBox.hpp @@ -2,15 +2,16 @@ #include #include +#include #include "unit/Unit.hpp" class AttackInfoBox { const std::string path_to_textures; - int attacking_unit_pos_x; - int attacking_unit_pos_y; - int attacked_unit_pos_x; - int attacked_unit_pos_y; + float attacking_unit_pos_x; + float attacking_unit_pos_y; + float attacked_unit_pos_x; + float attacked_unit_pos_y; std::array red_units_sprites_ptrs; std::array blue_units_sprites_ptrs; sf::Texture box_texture; diff --git a/include/Box.hpp b/include/Box.hpp index faf8f9d..356ab5f 100644 --- a/include/Box.hpp +++ b/include/Box.hpp @@ -9,10 +9,10 @@ class Box { const std::string path_to_textures; size_t max_char_count_inside_box; size_t max_number_of_text_lines_inside_box; - int box_text_x_pos; - int box_text_y_pos; - int button_x_pos; - int button_y_pos; + float box_text_x_pos; + float box_text_y_pos; + float button_x_pos; + float button_y_pos; Button button; sf::Font font; sf::Text box_text; diff --git a/include/ButtonInterface.hpp b/include/ButtonInterface.hpp index 191f98e..4fad1f2 100644 --- a/include/ButtonInterface.hpp +++ b/include/ButtonInterface.hpp @@ -26,7 +26,7 @@ class ButtonInterface { float get_height() const { return button.getGlobalBounds().height; }; float get_width() const { return button.getGlobalBounds().width; }; bool contains(int x, int y) const { - return button.getGlobalBounds().contains(x, y); + return button.getGlobalBounds().contains(static_cast(x), static_cast(y)); }; void highlight_on() { highlighted = true; }; void highlight_off() { highlighted = false; }; diff --git a/include/unit/RegularUnit.hpp b/include/unit/RegularUnit.hpp index d904c09..dc346e6 100644 --- a/include/unit/RegularUnit.hpp +++ b/include/unit/RegularUnit.hpp @@ -19,6 +19,6 @@ class RegularUnit { Turn get_owner() const noexcept { return model_.get_owner(); } static int get_count(int value) { RegularUnitCounter::get_count(value); } static int get_max_count(int value) { - RegularUnitCounter::get_max_count(value); + return RegularUnitCounter::get_max_count(value); } }; diff --git a/src/AttackInfoBox.cpp b/src/AttackInfoBox.cpp index d5f002b..f220738 100644 --- a/src/AttackInfoBox.cpp +++ b/src/AttackInfoBox.cpp @@ -10,9 +10,9 @@ AttackInfoBox::AttackInfoBox(std::array &red_units_sprites, std::array &blue_units_sprites, sf::Sprite &winning_unit_highlight) - : path_to_textures("images/board/"), attacking_unit_pos_x(-1), - attacking_unit_pos_y(-1), attacked_unit_pos_x(-1), - attacked_unit_pos_y(-1), attacking_unit{}, attacked_unit{}, + : path_to_textures("images/board/"), attacking_unit_pos_x(-1.0f), + attacking_unit_pos_y(-1.0f), attacked_unit_pos_x(-1.0f), + attacked_unit_pos_y(-1.0f), attacking_unit{}, attacked_unit{}, attacker_ptr{}, attacked_ptr{}, winner_highlight(winning_unit_highlight) { for (int i = 0; i < red_units_sprites_ptrs.size(); ++i) { red_units_sprites_ptrs[i] = &red_units_sprites[i]; @@ -60,7 +60,7 @@ int AttackInfoBox::get_unit_sprite_idx(const Unit &unit) { } void AttackInfoBox::set_position(int x, int y) { - box_sprite.setPosition(x, y); + box_sprite.setPosition(static_cast(x), static_cast(y)); update_attacking_unit_pos(); update_attacked_unit_pos(); update_box_text_pos(); @@ -149,7 +149,7 @@ void AttackInfoBox::draw_winner_highlight(sf::RenderWindow &win) { if (!get_winner()) { return; } - winner_highlight.setScale(1.5, 1.5); + winner_highlight.setScale(1.5f, 1.5f); win.draw(winner_highlight); - winner_highlight.setScale(1, 1); + winner_highlight.setScale(1.0f, 1.0f); } \ No newline at end of file diff --git a/src/Box.cpp b/src/Box.cpp index 5e0192f..23c2acb 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -5,8 +5,8 @@ Box::Box(const std::string &text) : path_to_textures("images/board/"), max_char_count_inside_box(12), - max_number_of_text_lines_inside_box(3), box_text_x_pos(-1), - box_text_y_pos(-1), button_x_pos(-1), button_y_pos(-1) { + max_number_of_text_lines_inside_box(3), box_text_x_pos(-1.0f), + box_text_y_pos(-1.0f), button_x_pos(-1.0f), button_y_pos(-1.0f) { load_box_texture(); load_font(); set_default_text(text); @@ -43,16 +43,16 @@ void Box::update_text_pos() { (box_sprite.getGlobalBounds().width - box_text.getLocalBounds().width) / 2); box_text_y_pos = - (box_sprite.getPosition().y + 2 * box_text.getCharacterSize()); + static_cast(box_sprite.getPosition().y + 2 * box_text.getCharacterSize()); box_text.setPosition(box_text_x_pos, box_text_y_pos); } void Box::update_button_pos() { button_x_pos = box_sprite.getPosition().x + (box_sprite.getGlobalBounds().width - button.get_width()) / 2; - button_y_pos = box_sprite.getPosition().y + + button_y_pos = static_cast(box_sprite.getPosition().y + box_sprite.getGlobalBounds().height - - 2 * box_text.getCharacterSize() - button.get_height(); + 2 * box_text.getCharacterSize() - button.get_height()); button.set_position(button_x_pos, button_y_pos); } @@ -83,8 +83,8 @@ void Box::draw(sf::RenderWindow &win) { } void Box::update_max_char_count() { - int max_chars_per_line = - box_sprite.getLocalBounds().width / box_text.getCharacterSize(); + int max_chars_per_line = static_cast( + box_sprite.getLocalBounds().width / box_text.getCharacterSize()); max_char_count_inside_box = max_chars_per_line * max_number_of_text_lines_inside_box; } @@ -115,14 +115,14 @@ void Box::break_text_into_lines() { char_count_inside_line = 0; } else { char_count_that_will_fit_in_line = - box_sprite.getLocalBounds().width - + static_cast(box_sprite.getLocalBounds().width) - char_count_inside_line * box_text.getCharacterSize(); if (char_count_of_next_word > char_count_that_will_fit_in_line || i == words.size() - 2) { float denting = (box_sprite.getLocalBounds().width - char_count_inside_line * box_text.getCharacterSize()) / 2; - int spaces = (denting / box_text.getCharacterSize() + 0.5); + int spaces = static_cast(denting / box_text.getCharacterSize() + 0.5); temp_text.insert(idx_of_the_first_char_in_new_line, spaces, ' '); } temp_text += (words[i] + " "); From 028ee282748623e6a38872242aced262a41af071 Mon Sep 17 00:00:00 2001 From: Wojciech Matusiak <62173407+WojtekMs@users.noreply.github.com> Date: Sun, 23 Mar 2025 18:13:13 +0100 Subject: [PATCH 09/11] Fix code formatting --- include/AttackInfoBox.hpp | 2 +- include/ButtonInterface.hpp | 3 ++- src/Box.cpp | 17 +++++++++-------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/include/AttackInfoBox.hpp b/include/AttackInfoBox.hpp index b8d3665..841432e 100644 --- a/include/AttackInfoBox.hpp +++ b/include/AttackInfoBox.hpp @@ -1,8 +1,8 @@ #pragma once #include -#include #include +#include #include "unit/Unit.hpp" diff --git a/include/ButtonInterface.hpp b/include/ButtonInterface.hpp index 4fad1f2..d29731f 100644 --- a/include/ButtonInterface.hpp +++ b/include/ButtonInterface.hpp @@ -26,7 +26,8 @@ class ButtonInterface { float get_height() const { return button.getGlobalBounds().height; }; float get_width() const { return button.getGlobalBounds().width; }; bool contains(int x, int y) const { - return button.getGlobalBounds().contains(static_cast(x), static_cast(y)); + return button.getGlobalBounds().contains(static_cast(x), + static_cast(y)); }; void highlight_on() { highlighted = true; }; void highlight_off() { highlighted = false; }; diff --git a/src/Box.cpp b/src/Box.cpp index 23c2acb..1441669 100644 --- a/src/Box.cpp +++ b/src/Box.cpp @@ -42,17 +42,17 @@ void Box::update_text_pos() { (box_sprite.getPosition().x + (box_sprite.getGlobalBounds().width - box_text.getLocalBounds().width) / 2); - box_text_y_pos = - static_cast(box_sprite.getPosition().y + 2 * box_text.getCharacterSize()); + box_text_y_pos = static_cast(box_sprite.getPosition().y + + 2 * box_text.getCharacterSize()); box_text.setPosition(box_text_x_pos, box_text_y_pos); } void Box::update_button_pos() { button_x_pos = box_sprite.getPosition().x + (box_sprite.getGlobalBounds().width - button.get_width()) / 2; - button_y_pos = static_cast(box_sprite.getPosition().y + - box_sprite.getGlobalBounds().height - - 2 * box_text.getCharacterSize() - button.get_height()); + button_y_pos = static_cast( + box_sprite.getPosition().y + box_sprite.getGlobalBounds().height - + 2 * box_text.getCharacterSize() - button.get_height()); button.set_position(button_x_pos, button_y_pos); } @@ -83,8 +83,8 @@ void Box::draw(sf::RenderWindow &win) { } void Box::update_max_char_count() { - int max_chars_per_line = static_cast( - box_sprite.getLocalBounds().width / box_text.getCharacterSize()); + int max_chars_per_line = static_cast(box_sprite.getLocalBounds().width / + box_text.getCharacterSize()); max_char_count_inside_box = max_chars_per_line * max_number_of_text_lines_inside_box; } @@ -122,7 +122,8 @@ void Box::break_text_into_lines() { float denting = (box_sprite.getLocalBounds().width - char_count_inside_line * box_text.getCharacterSize()) / 2; - int spaces = static_cast(denting / box_text.getCharacterSize() + 0.5); + int spaces = + static_cast(denting / box_text.getCharacterSize() + 0.5); temp_text.insert(idx_of_the_first_char_in_new_line, spaces, ' '); } temp_text += (words[i] + " "); From 00e94b5b09638fd0a165ec82c751c3440def9ae1 Mon Sep 17 00:00:00 2001 From: Wojciech Matusiak <62173407+WojtekMs@users.noreply.github.com> Date: Sun, 23 Mar 2025 18:36:52 +0100 Subject: [PATCH 10/11] Add formatting script and hook --- README.md | 22 +++++++++++++ infra/hooks/pre-commit | 55 +++++++++++++++++++++++++++++++ infra/scripts/check_formatting.sh | 21 ++++++++++++ 3 files changed, 98 insertions(+) create mode 100644 infra/hooks/pre-commit create mode 100644 infra/scripts/check_formatting.sh diff --git a/README.md b/README.md index 0ed2ee3..09de674 100644 --- a/README.md +++ b/README.md @@ -51,3 +51,25 @@ Created with the help of SFML documentation and sources: - [Setting The Board](https://user-images.githubusercontent.com/62173407/85401972-2f64ad80-b55b-11ea-81bb-2f78c8d047ed.png) - [Scout Move](https://user-images.githubusercontent.com/62173407/85402027-44d9d780-b55b-11ea-9de2-3ff096b19e8b.png) - [Attack Info Box](https://user-images.githubusercontent.com/62173407/85402062-5622e400-b55b-11ea-9d96-9cd896a91d29.png) + + +## Contributing +In case you would like to contribue, please make sure that you format code. + +1. Make sure you are in repo root +2. Install clang-format using pip: +```bash +python3 -m venv env +source env/bin/activate +pip install -r requirements.txt +``` + +3. Now use the formatting script: +```bash +bash infra/scripts/check_formatting.sh . +``` + +4. You can also install pre-commit hook that will automatically check for correct code-formatting: +```bash +cp infra/hooks/pre-commit .git/hooks/pre-commit +``` diff --git a/infra/hooks/pre-commit b/infra/hooks/pre-commit new file mode 100644 index 0000000..629a96a --- /dev/null +++ b/infra/hooks/pre-commit @@ -0,0 +1,55 @@ +#!/bin/bash +# +# An example hook script to verify what is about to be committed. +# Called by "git commit" with no arguments. The hook should +# exit with non-zero status after issuing an appropriate message if +# it wants to stop the commit. +# +# To enable this hook, rename this file to "pre-commit". + + +if git rev-parse --verify HEAD >/dev/null 2>&1 +then + against=HEAD +else + # Initial commit: diff against an empty tree object + against=$(git hash-object -t tree /dev/null) +fi + +# If you want to allow non-ASCII filenames set this variable to true. +allownonascii=$(git config --type=bool hooks.allownonascii) + +# Redirect output to stderr. +exec 1>&2 +# Cross platform projects tend to avoid non-ASCII filenames; prevent +# them from being added to the repository. We exploit the fact that the +# printable range starts at the space character and ends with tilde. +if [ "$allownonascii" != "true" ] && + # Note that the use of brackets around a tr range is ok here, (it's + # even required, for portability to Solaris 10's /usr/bin/tr), since + # the square bracket bytes happen to fall in the designated range. + test $(git diff --cached --name-only --diff-filter=A -z $against | + LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0 +then + cat < Date: Sun, 23 Mar 2025 18:41:06 +0100 Subject: [PATCH 11/11] Fix compilation issues #2 Add new script to apply_formatting --- README.md | 2 +- include/unit/RegularUnit.hpp | 4 +++- infra/scripts/apply_formatting.sh | 21 +++++++++++++++++++++ 3 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 infra/scripts/apply_formatting.sh diff --git a/README.md b/README.md index 09de674..acaa251 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ pip install -r requirements.txt 3. Now use the formatting script: ```bash -bash infra/scripts/check_formatting.sh . +bash infra/scripts/apply_formatting.sh . ``` 4. You can also install pre-commit hook that will automatically check for correct code-formatting: diff --git a/include/unit/RegularUnit.hpp b/include/unit/RegularUnit.hpp index dc346e6..806289d 100644 --- a/include/unit/RegularUnit.hpp +++ b/include/unit/RegularUnit.hpp @@ -17,7 +17,9 @@ class RegularUnit { return model_.get_type(); } Turn get_owner() const noexcept { return model_.get_owner(); } - static int get_count(int value) { RegularUnitCounter::get_count(value); } + static int get_count(int value) { + return RegularUnitCounter::get_count(value); + } static int get_max_count(int value) { return RegularUnitCounter::get_max_count(value); } diff --git a/infra/scripts/apply_formatting.sh b/infra/scripts/apply_formatting.sh new file mode 100644 index 0000000..889ec86 --- /dev/null +++ b/infra/scripts/apply_formatting.sh @@ -0,0 +1,21 @@ +#!/bin/bash + +if [[ $# -ne 1 ]]; then + echo "GIT_DIR is missing" + echo "usage: ${0} GIT_DIR" + exit 1 +fi +GIT_DIR="${1}" +GIT_DIR=$(realpath $GIT_DIR) +cd $GIT_DIR +if [[ ! -d .git ]]; then + echo "GIT_DIR must be set to repo root, .git is missing in $GIT_DIR" + exit 1 +fi + +echo "Applying code formatting..." +. env/bin/activate && find src/ include/ -regex ".*\.\(hpp\|cpp\|c\|h\)$" -execdir clang-format --style=LLVM -i {} + ; +FORMATTING_EC=$? +if [[ $FORMATTING_EC -ne 0 ]]; then + exit 1 +fi