From 1090f31a775466c8dcef026329801c17706cac67 Mon Sep 17 00:00:00 2001 From: Michael Gerhold Date: Sat, 24 Aug 2024 14:54:00 +0200 Subject: [PATCH] add `obpf_tetrion_try_get_active_tetromino_transform()` function to retrieve meta information about the currently active tetromino --- src/CMakeLists.txt | 1 + src/common/CMakeLists.txt | 3 ++ .../include/common/common.h} | 2 + src/obpf/CMakeLists.txt | 2 +- src/obpf/include/obpf/rotation.h | 22 ++++++--- src/obpf/include/obpf/simulator.h | 10 +++-- src/obpf/simulator.cpp | 30 +++++++++++-- src/simulator/CMakeLists.txt | 2 + src/simulator/include/simulator/tetrion.hpp | 10 ++--- src/simulator/tetrion.cpp | 10 +++-- test/tetrion_tests.cpp | 45 ++++++++++--------- 11 files changed, 93 insertions(+), 44 deletions(-) create mode 100644 src/common/CMakeLists.txt rename src/{obpf/include/obpf/action.h => common/include/common/common.h} (83%) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 925137f..7268557 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,3 +1,4 @@ +add_subdirectory(common) add_subdirectory(network) add_subdirectory(obpf) add_subdirectory(server) diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt new file mode 100644 index 0000000..82328c9 --- /dev/null +++ b/src/common/CMakeLists.txt @@ -0,0 +1,3 @@ +add_library(common INTERFACE include/common/common.h) + +target_include_directories(common INTERFACE include) diff --git a/src/obpf/include/obpf/action.h b/src/common/include/common/common.h similarity index 83% rename from src/obpf/include/obpf/action.h rename to src/common/include/common/common.h index 85ed6d2..7fbd52f 100644 --- a/src/obpf/include/obpf/action.h +++ b/src/common/include/common/common.h @@ -16,6 +16,8 @@ extern "C" { OBPF_ACTION_ALL_CLEAR, } ObpfAction; + typedef void (*ObpfActionHandler)(ObpfAction action, void* user_data); + #ifdef __cplusplus } #endif diff --git a/src/obpf/CMakeLists.txt b/src/obpf/CMakeLists.txt index 2161e3c..e65d825 100644 --- a/src/obpf/CMakeLists.txt +++ b/src/obpf/CMakeLists.txt @@ -16,7 +16,6 @@ add_library(obpf lobby.cpp include/obpf/rotation.h include/obpf/stats.h - include/obpf/action.h ) target_compile_definitions(obpf PRIVATE "simulator_EXPORTS") @@ -28,6 +27,7 @@ target_link_libraries(obpf simulator network spdlog::spdlog + common ) target_include_directories(obpf diff --git a/src/obpf/include/obpf/rotation.h b/src/obpf/include/obpf/rotation.h index adef98c..06a9823 100644 --- a/src/obpf/include/obpf/rotation.h +++ b/src/obpf/include/obpf/rotation.h @@ -1,9 +1,17 @@ #pragma once -typedef enum { - OBPF_ROTATION_NORTH = 0, - OBPF_ROTATION_EAST, - OBPF_ROTATION_SOUTH, - OBPF_ROTATION_WEST, - OBPF_ROTATION_LAST_ROTATION = OBPF_ROTATION_WEST, -} ObpfRotation; +#ifdef __cplusplus +extern "C" { +#endif + + typedef enum { + OBPF_ROTATION_NORTH = 0, + OBPF_ROTATION_EAST, + OBPF_ROTATION_SOUTH, + OBPF_ROTATION_WEST, + OBPF_ROTATION_LAST_ROTATION = OBPF_ROTATION_WEST, + } ObpfRotation; + +#ifdef __cplusplus +} +#endif diff --git a/src/obpf/include/obpf/simulator.h b/src/obpf/include/obpf/simulator.h index 085352e..2b06667 100644 --- a/src/obpf/include/obpf/simulator.h +++ b/src/obpf/include/obpf/simulator.h @@ -6,9 +6,9 @@ extern "C" { #endif +#include #include #include -#include "action.h" #include "input.h" #include "rotation.h" #include "stats.h" @@ -35,8 +35,6 @@ extern "C" { uint8_t bitmask; } ObpfKeyState; - typedef void (*ObpfActionHandler)(ObpfAction action, void* user_data); - // clang-format off // Tetrion @@ -64,6 +62,12 @@ extern "C" { struct ObpfTetrion const* tetrion, struct ObpfTetromino* out_tetromino ); + OBPF_EXPORT bool obpf_tetrion_try_get_active_tetromino_transform( + struct ObpfTetrion const* tetrion, + ObpfTetrominoType* out_type, + ObpfRotation* out_rotation, + ObpfVec2* out_position + ); OBPF_EXPORT bool obpf_tetrion_try_get_ghost_tetromino( struct ObpfTetrion const* tetrion, struct ObpfTetromino* out_tetromino diff --git a/src/obpf/simulator.cpp b/src/obpf/simulator.cpp index 589bfb7..f1abd6c 100644 --- a/src/obpf/simulator.cpp +++ b/src/obpf/simulator.cpp @@ -63,6 +63,31 @@ bool obpf_tetrion_try_get_active_tetromino(ObpfTetrion const* const tetrion, Obp return try_get_tetromino(tetrion, out_tetromino, TetrominoSelection::ActiveTetromino); } +bool obpf_tetrion_try_get_active_tetromino_transform( + struct ObpfTetrion const* const tetrion, + ObpfTetrominoType* const out_type, + ObpfRotation* const out_rotation, + ObpfVec2* const out_position +) { + auto const tetromino = tetrion->active_tetromino(); + if (not tetromino.has_value()) { + return false; + } + if (out_type != nullptr) { + *out_type = static_cast(tetromino->type); + } + if (out_rotation != nullptr) { + *out_rotation = static_cast(tetromino->rotation); + } + if (out_position != nullptr) { + *out_position = ObpfVec2{ + gsl::narrow(tetromino->position.x), + gsl::narrow(tetromino->position.y), + }; + } + return true; +} + bool obpf_tetrion_try_get_ghost_tetromino(ObpfTetrion const* tetrion, ObpfTetromino* out_tetromino) { return try_get_tetromino(tetrion, out_tetromino, TetrominoSelection::GhostTetromino); } @@ -123,8 +148,7 @@ ObpfMinoPositions obpf_tetromino_get_mino_positions(ObpfTetrominoType const type } ObpfTetrominoType obpf_tetrion_get_hold_piece(ObpfTetrion const* const tetrion) { - auto const hold_piece = tetrion->hold_piece(); - if (hold_piece.has_value()) { + if (auto const hold_piece = tetrion->hold_piece(); hold_piece.has_value()) { return static_cast(hold_piece.value()); } return OBPF_TETROMINO_TYPE_EMPTY; @@ -158,5 +182,5 @@ bool obpf_tetrion_is_game_over(ObpfTetrion const* const tetrion) { } void obpf_tetrion_set_action_handler(ObpfTetrion* const tetrion, ObpfActionHandler const handler, void* const user_data) { - tetrion->set_action_handler(reinterpret_cast(handler), user_data); + tetrion->set_action_handler(handler, user_data); } diff --git a/src/simulator/CMakeLists.txt b/src/simulator/CMakeLists.txt index 12b06e6..46d972f 100644 --- a/src/simulator/CMakeLists.txt +++ b/src/simulator/CMakeLists.txt @@ -26,6 +26,8 @@ target_include_directories(simulator ) target_link_libraries(simulator + PUBLIC + common PRIVATE obpf_simulator_project_options ) diff --git a/src/simulator/include/simulator/tetrion.hpp b/src/simulator/include/simulator/tetrion.hpp index ec12841..9b9f2c7 100644 --- a/src/simulator/include/simulator/tetrion.hpp +++ b/src/simulator/include/simulator/tetrion.hpp @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -19,14 +20,11 @@ #include "tetromino.hpp" struct ObpfTetrion final { -public: - using ActionHandler = void (*)(Action action, void* user_data); - private: static constexpr auto spawn_position = Vec2{ 3, 0 }; static constexpr auto spawn_rotation = Rotation::North; - ActionHandler m_action_handler = nullptr; + ObpfActionHandler m_action_handler = nullptr; void* m_action_handler_user_data = nullptr; Matrix m_matrix; std::optional m_active_tetromino; @@ -67,7 +65,7 @@ struct ObpfTetrion final { static_assert(std::same_as, c2k::Random::Seed>); m_lock_delay_state.set_on_touch_handler([this] { if (m_action_handler) { - m_action_handler(Action::Touch, m_action_handler_user_data); + m_action_handler(static_cast(Action::Touch), m_action_handler_user_data); } }); spawn_next_tetromino(); @@ -78,7 +76,7 @@ struct ObpfTetrion final { ObpfTetrion& operator=(ObpfTetrion const& other) = delete; ObpfTetrion& operator=(ObpfTetrion&& other) noexcept = default; - void set_action_handler(ActionHandler const handler, void* const user_data) { + void set_action_handler(ObpfActionHandler const handler, void* const user_data) { m_action_handler = handler; m_action_handler_user_data = user_data; } diff --git a/src/simulator/tetrion.cpp b/src/simulator/tetrion.cpp index 6a142d0..05d33cb 100644 --- a/src/simulator/tetrion.cpp +++ b/src/simulator/tetrion.cpp @@ -355,7 +355,9 @@ void ObpfTetrion::rotate(RotationDirection const direction) { m_lock_delay_state.on_tetromino_moved(LockDelayMovementType::NotMovedDown); if (m_action_handler != nullptr) { m_action_handler( - direction == RotationDirection::Clockwise ? Action::RotateCW : Action::RotateCCW, + static_cast( + direction == RotationDirection::Clockwise ? Action::RotateCW : Action::RotateCCW + ), m_action_handler_user_data ); } @@ -391,7 +393,7 @@ void ObpfTetrion::hard_drop() { m_lock_delay_state.on_hard_drop_lock(); if (m_action_handler != nullptr) { - m_action_handler(Action::HardDrop, m_action_handler_user_data); + m_action_handler(static_cast(Action::HardDrop), m_action_handler_user_data); } } @@ -424,7 +426,7 @@ void ObpfTetrion::determine_lines_to_clear() { m_line_clear_delay.start(lines_to_clear); if (m_action_handler) { m_action_handler( - static_cast(std::to_underlying(Action::Clear1) + lines_to_clear.size() - 1), + static_cast(std::to_underlying(Action::Clear1) + lines_to_clear.size() - 1), m_action_handler_user_data ); } @@ -450,7 +452,7 @@ void ObpfTetrion::clear_lines(c2k::StaticVector const lines) { } m_num_lines_cleared += gsl::narrow(lines.size()); if (m_matrix.is_empty() and m_action_handler != nullptr) { - m_action_handler(Action::AllClear, m_action_handler_user_data); + m_action_handler(static_cast(Action::AllClear), m_action_handler_user_data); } } diff --git a/test/tetrion_tests.cpp b/test/tetrion_tests.cpp index 1b80fe1..8b75133 100644 --- a/test/tetrion_tests.cpp +++ b/test/tetrion_tests.cpp @@ -1,23 +1,25 @@ #include +#include #include static constexpr u64 seed_for_tetromino_type(TetrominoType const type) { switch (type) { - case TetrominoType::I: + using enum TetrominoType; + case I: return 13; - case TetrominoType::J: + case J: return 10; - case TetrominoType::L: + case L: return 11; - case TetrominoType::O: + case O: return 1; - case TetrominoType::S: + case S: return 0; - case TetrominoType::T: + case T: return 22; - case TetrominoType::Z: + case Z: return 4; - case TetrominoType::Empty: + case Empty: throw std::runtime_error{ "Empty type cannot be spawned" }; } throw std::runtime_error{ "Invalid TetrominoType" }; @@ -25,21 +27,22 @@ static constexpr u64 seed_for_tetromino_type(TetrominoType const type) { static constexpr char to_char(TetrominoType const type) { switch (type) { - case TetrominoType::Empty: + using enum TetrominoType; + case Empty: return ' '; - case TetrominoType::I: + case I: return 'I'; - case TetrominoType::J: + case J: return 'J'; - case TetrominoType::L: + case L: return 'L'; - case TetrominoType::O: + case O: return 'O'; - case TetrominoType::S: + case S: return 'S'; - case TetrominoType::T: + case T: return 'T'; - case TetrominoType::Z: + case Z: return 'Z'; } throw std::runtime_error{ "Invalid TetrominoType" }; @@ -49,6 +52,9 @@ static constexpr char to_char(TetrominoType const type) { auto const active_minos = tetrion.active_tetromino().transform([](Tetromino const& tetromino) { return get_mino_positions(tetromino); }); + using std::ranges::views::cartesian_product; + using std::ranges::views::iota; + for (auto row = usize{ 0 }; row < Matrix::height; ++row) { for (auto column = usize{ 0 }; column < Matrix::width; ++column) { if (active_minos.has_value()) { @@ -60,8 +66,7 @@ static constexpr char to_char(TetrominoType const type) { } } std::cout << to_char(tetrion.matrix()[Vec2{ static_cast(column), static_cast(row) }]); -next_column: // 👈(゚ヮ゚👈) - (void)1; +next_column:; // 👈(゚ヮ゚👈) } std::cout << '\n'; } @@ -71,8 +76,8 @@ TEST(TetrionTests, AllClear) { auto tetrion = ObpfTetrion{ seed_for_tetromino_type(TetrominoType::I) }; auto called_count = usize{ 0 }; tetrion.set_action_handler( - [](Action const action, void* user_data) { - if (action == Action::AllClear) { + [](ObpfAction const action, void* user_data) { + if (action == static_cast(Action::AllClear)) { *static_cast(user_data) = true; } },