diff --git a/src/obpf/include/obpf/simulator.h b/src/obpf/include/obpf/simulator.h index 4d511e2..6fbb57f 100644 --- a/src/obpf/include/obpf/simulator.h +++ b/src/obpf/include/obpf/simulator.h @@ -16,10 +16,7 @@ extern "C" { typedef struct { uint8_t count; - uint8_t first; - uint8_t second; - uint8_t third; - uint8_t fourth; + uint8_t lines[4]; uint64_t countdown; uint64_t delay; } ObpfLineClearDelayState; @@ -65,12 +62,12 @@ extern "C" { OBPF_EXPORT uint64_t obpf_tetrion_get_next_frame(struct ObpfTetrion const* tetrion); OBPF_EXPORT void obpf_tetrion_simulate_next_frame(struct ObpfTetrion* tetrion, ObpfKeyState key_state); OBPF_EXPORT void obpf_destroy_tetrion(struct ObpfTetrion const* tetrion); - OBPF_EXPORT struct ObpfMatrix const* obpf_tetrion_matrix(struct ObpfTetrion const* tetrion); OBPF_EXPORT uint8_t obpf_tetrion_width(void); OBPF_EXPORT uint8_t obpf_tetrion_height(void); + OBPF_EXPORT uint8_t obpf_tetrion_num_invisible_lines(void); // Matrix - OBPF_EXPORT ObpfTetrominoType obpf_matrix_get(struct ObpfMatrix const* matrix, ObpfVec2 position); + OBPF_EXPORT ObpfTetrominoType obpf_tetrion_matrix_get(const struct ObpfTetrion* tetrion, ObpfVec2 position); // clang-format on diff --git a/src/obpf/simulator.cpp b/src/obpf/simulator.cpp index 794c208..731c5ff 100644 --- a/src/obpf/simulator.cpp +++ b/src/obpf/simulator.cpp @@ -48,10 +48,12 @@ ObpfLineClearDelayState obpf_tetrion_get_line_clear_delay_state(ObpfTetrion cons } return ObpfLineClearDelayState{ .count = gsl::narrow(original_size), - .first = lines.at(0), - .second = lines.at(1), - .third = lines.at(2), - .fourth = lines.at(3), + .lines{ + lines.at(0), + lines.at(1), + lines.at(2), + lines.at(3), + }, .countdown = countdown, .delay = LineClearDelay::delay, }; @@ -77,15 +79,6 @@ void obpf_destroy_tetrion(ObpfTetrion const* const tetrion) { delete tetrion; } -ObpfMatrix const* obpf_tetrion_matrix(ObpfTetrion const* const tetrion) { - return reinterpret_cast(std::addressof(tetrion->matrix())); -} - -ObpfTetrominoType obpf_matrix_get(ObpfMatrix const* const matrix, ObpfVec2 const position) { - auto const pos = Vec2{ position.x, position.y }; - return static_cast((*reinterpret_cast(matrix))[pos]); -} - uint8_t obpf_tetrion_width() { return uint8_t{ Matrix::width }; } @@ -94,6 +87,15 @@ uint8_t obpf_tetrion_height() { return uint8_t{ Matrix::height }; } +uint8_t obpf_tetrion_num_invisible_lines() { + return uint8_t{ Matrix::num_invisible_lines }; +} + +ObpfTetrominoType obpf_tetrion_matrix_get(ObpfTetrion const* const tetrion, ObpfVec2 const position) { + auto const pos = Vec2{ position.x, position.y }; + return static_cast(tetrion->matrix()[pos]); +} + ObpfPreviewPieces obpf_tetrion_get_preview_pieces(ObpfTetrion const* tetrion) { auto const preview_tetrominos = tetrion->get_preview_tetrominos(); ObpfPreviewPieces result{}; diff --git a/src/simulator/include/simulator/matrix.hpp b/src/simulator/include/simulator/matrix.hpp index 2ff6817..626b029 100644 --- a/src/simulator/include/simulator/matrix.hpp +++ b/src/simulator/include/simulator/matrix.hpp @@ -10,6 +10,7 @@ class Matrix final { public: static constexpr auto width = std::size_t{ 10 }; static constexpr auto height = std::size_t{ 22 }; + static constexpr auto num_invisible_lines = std::size_t{ 2 }; private: std::array m_minos{}; diff --git a/src/simulator/include/simulator/tetrion.hpp b/src/simulator/include/simulator/tetrion.hpp index 45da692..6192c1b 100644 --- a/src/simulator/include/simulator/tetrion.hpp +++ b/src/simulator/include/simulator/tetrion.hpp @@ -83,6 +83,7 @@ struct ObpfTetrion final { private: void freeze_and_destroy_active_tetromino(); + [[nodiscard]] bool is_tetromino_completely_visible(Tetromino const& tetromino) const; [[nodiscard]] bool is_tetromino_position_valid(Tetromino const& tetromino) const; [[nodiscard]] bool is_active_tetromino_position_valid() const; void spawn_next_tetromino(); diff --git a/src/simulator/tetrion.cpp b/src/simulator/tetrion.cpp index 75a93f1..582b351 100644 --- a/src/simulator/tetrion.cpp +++ b/src/simulator/tetrion.cpp @@ -131,6 +131,20 @@ void ObpfTetrion::freeze_and_destroy_active_tetromino() { m_active_tetromino = std::nullopt; } +[[nodiscard]] bool ObpfTetrion::is_tetromino_completely_visible(Tetromino const& tetromino) const { + if (not is_tetromino_position_valid(tetromino)) { + return false; + } + + for (auto const& position : get_mino_positions(tetromino)) { + if (position.y < gsl::narrow(Matrix::num_invisible_lines)) { + return false; + } + } + + return true; +} + [[nodiscard]] bool ObpfTetrion::is_tetromino_position_valid(Tetromino const& tetromino) const { auto const mino_positions = get_mino_positions(tetromino); for (auto const position : mino_positions) { @@ -170,6 +184,21 @@ void ObpfTetrion::spawn_next_tetromino() { m_is_hold_possible = true; } + // todo: check game over state here + + // clang-format off + for ( + auto i = std::size_t{ 0 }; + not is_tetromino_completely_visible(active_tetromino().value()) and i < Matrix::num_invisible_lines; + ++i + ) { // clang-format on + m_active_tetromino->position.y += 1; + if (not is_active_tetromino_position_valid()) { + m_active_tetromino->position.y -= 1; + break; + } + } + m_is_soft_dropping = false; m_next_gravity_frame = m_next_frame + gravity_delay_by_level(level()); }