Skip to content

Commit

Permalink
Merge pull request #37 from OpenBrickProtocolFoundation/33-implement-…
Browse files Browse the repository at this point in the history
…possibility-to-query-position-and-rotation-of-the-currently-active-tetromino

add `obpf_tetrion_try_get_active_tetromino_transform()` function to retrieve meta information about the currently active tetromino
  • Loading branch information
mgerhold authored Aug 24, 2024
2 parents 5597f70 + 1090f31 commit e279c6b
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 44 deletions.
1 change: 1 addition & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
add_subdirectory(common)
add_subdirectory(network)
add_subdirectory(obpf)
add_subdirectory(server)
Expand Down
3 changes: 3 additions & 0 deletions src/common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
add_library(common INTERFACE include/common/common.h)

target_include_directories(common INTERFACE include)
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ extern "C" {
OBPF_ACTION_ALL_CLEAR,
} ObpfAction;

typedef void (*ObpfActionHandler)(ObpfAction action, void* user_data);

#ifdef __cplusplus
}
#endif
2 changes: 1 addition & 1 deletion src/obpf/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -28,6 +27,7 @@ target_link_libraries(obpf
simulator
network
spdlog::spdlog
common
)

target_include_directories(obpf
Expand Down
22 changes: 15 additions & 7 deletions src/obpf/include/obpf/rotation.h
Original file line number Diff line number Diff line change
@@ -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
10 changes: 7 additions & 3 deletions src/obpf/include/obpf/simulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
extern "C" {
#endif

#include <common/common.h>
#include <stdbool.h>
#include <stdint.h>
#include "action.h"
#include "input.h"
#include "rotation.h"
#include "stats.h"
Expand All @@ -35,8 +35,6 @@ extern "C" {
uint8_t bitmask;
} ObpfKeyState;

typedef void (*ObpfActionHandler)(ObpfAction action, void* user_data);

// clang-format off

// Tetrion
Expand Down Expand Up @@ -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
Expand Down
30 changes: 27 additions & 3 deletions src/obpf/simulator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ObpfTetrominoType>(tetromino->type);
}
if (out_rotation != nullptr) {
*out_rotation = static_cast<ObpfRotation>(tetromino->rotation);
}
if (out_position != nullptr) {
*out_position = ObpfVec2{
gsl::narrow<std::uint8_t>(tetromino->position.x),
gsl::narrow<std::uint8_t>(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);
}
Expand Down Expand Up @@ -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<ObpfTetrominoType>(hold_piece.value());
}
return OBPF_TETROMINO_TYPE_EMPTY;
Expand Down Expand Up @@ -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<ObpfTetrion::ActionHandler>(handler), user_data);
tetrion->set_action_handler(handler, user_data);
}
2 changes: 2 additions & 0 deletions src/simulator/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ target_include_directories(simulator
)

target_link_libraries(simulator
PUBLIC
common
PRIVATE
obpf_simulator_project_options
)
Expand Down
10 changes: 4 additions & 6 deletions src/simulator/include/simulator/tetrion.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#pragma once

#include <common/common.h>
#include <array>
#include <cstdint>
#include <lib2k/random.hpp>
Expand All @@ -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<Tetromino> m_active_tetromino;
Expand Down Expand Up @@ -67,7 +65,7 @@ struct ObpfTetrion final {
static_assert(std::same_as<std::remove_const_t<decltype(seed)>, 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<ObpfAction>(Action::Touch), m_action_handler_user_data);
}
});
spawn_next_tetromino();
Expand All @@ -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;
}
Expand Down
10 changes: 6 additions & 4 deletions src/simulator/tetrion.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ObpfAction>(
direction == RotationDirection::Clockwise ? Action::RotateCW : Action::RotateCCW
),
m_action_handler_user_data
);
}
Expand Down Expand Up @@ -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<ObpfAction>(Action::HardDrop), m_action_handler_user_data);
}
}

Expand Down Expand Up @@ -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<Action>(std::to_underlying(Action::Clear1) + lines_to_clear.size() - 1),
static_cast<ObpfAction>(std::to_underlying(Action::Clear1) + lines_to_clear.size() - 1),
m_action_handler_user_data
);
}
Expand All @@ -450,7 +452,7 @@ void ObpfTetrion::clear_lines(c2k::StaticVector<u8, 4> const lines) {
}
m_num_lines_cleared += gsl::narrow<decltype(m_num_lines_cleared)>(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<ObpfAction>(Action::AllClear), m_action_handler_user_data);
}
}

Expand Down
45 changes: 25 additions & 20 deletions test/tetrion_tests.cpp
Original file line number Diff line number Diff line change
@@ -1,45 +1,48 @@
#include <gtest/gtest.h>
#include <ranges>
#include <simulator/tetrion.hpp>

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" };
}

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" };
Expand All @@ -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()) {
Expand All @@ -60,8 +66,7 @@ static constexpr char to_char(TetrominoType const type) {
}
}
std::cout << to_char(tetrion.matrix()[Vec2{ static_cast<i32>(column), static_cast<i32>(row) }]);
next_column: // 👈(゚ヮ゚👈)
(void)1;
next_column:; // 👈(゚ヮ゚👈)
}
std::cout << '\n';
}
Expand All @@ -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<ObpfAction>(Action::AllClear)) {
*static_cast<usize*>(user_data) = true;
}
},
Expand Down

0 comments on commit e279c6b

Please sign in to comment.