Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add obpf_tetrion_try_get_active_tetromino_transform() function to retrieve meta information about the currently active tetromino #37

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading