More tests converted to fuc2.
This commit is contained in:
parent
b8b42d5681
commit
903cf00661
10 changed files with 671 additions and 556 deletions
|
|
@ -1,4 +1,4 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <string>
|
||||
#include "gui/event_router.hpp"
|
||||
|
|
@ -7,51 +7,61 @@ using namespace fmt;
|
|||
using namespace gui;
|
||||
using enum gui::routing::Event;
|
||||
using enum gui::routing::State;
|
||||
using namespace fuc2;
|
||||
|
||||
using EventScript = std::vector<routing::Event>;
|
||||
namespace event_router_tests {
|
||||
using EventScript = std::vector<routing::Event>;
|
||||
|
||||
void run_script(routing::Router& router, routing::State expected, EventScript script) {
|
||||
for(auto ev : script) {
|
||||
router.event(ev);
|
||||
void run_script(routing::Router& router, routing::State expected, EventScript script) {
|
||||
for(auto ev : script) {
|
||||
router.event(ev);
|
||||
}
|
||||
|
||||
CHECK(router.in_state(expected));
|
||||
}
|
||||
|
||||
REQUIRE(router.in_state(expected));
|
||||
}
|
||||
|
||||
TEST_CASE("basic router operations test", "[event_router]") {
|
||||
routing::Router router;
|
||||
|
||||
// start goes to idle
|
||||
run_script(router, IDLE, {
|
||||
STARTED
|
||||
});
|
||||
|
||||
// simulate drag and drop
|
||||
run_script(router, IDLE, {
|
||||
MOUSE_DOWN,
|
||||
MOUSE_MOVE,
|
||||
MOUSE_UP,
|
||||
KEY_PRESS
|
||||
});
|
||||
|
||||
// moving the mouse outside dnd
|
||||
run_script(router, IDLE, {
|
||||
MOUSE_MOVE,
|
||||
KEY_PRESS,
|
||||
MOUSE_MOVE
|
||||
});
|
||||
|
||||
// regular mouse click
|
||||
run_script(router, IDLE, {
|
||||
MOUSE_DOWN,
|
||||
MOUSE_UP
|
||||
});
|
||||
|
||||
// possible bad key press in a move?
|
||||
run_script(router, IDLE, {
|
||||
MOUSE_DOWN,
|
||||
MOUSE_MOVE,
|
||||
KEY_PRESS,
|
||||
MOUSE_UP,
|
||||
});
|
||||
void test_basic_router_operations_test() {
|
||||
routing::Router router;
|
||||
|
||||
// start goes to idle
|
||||
run_script(router, IDLE, {
|
||||
STARTED
|
||||
});
|
||||
|
||||
// simulate drag and drop
|
||||
run_script(router, IDLE, {
|
||||
MOUSE_DOWN,
|
||||
MOUSE_MOVE,
|
||||
MOUSE_UP,
|
||||
KEY_PRESS
|
||||
});
|
||||
|
||||
// moving the mouse outside dnd
|
||||
run_script(router, IDLE, {
|
||||
MOUSE_MOVE,
|
||||
KEY_PRESS,
|
||||
MOUSE_MOVE
|
||||
});
|
||||
|
||||
// regular mouse click
|
||||
run_script(router, IDLE, {
|
||||
MOUSE_DOWN,
|
||||
MOUSE_UP
|
||||
});
|
||||
|
||||
// possible bad key press in a move?
|
||||
run_script(router, IDLE, {
|
||||
MOUSE_DOWN,
|
||||
MOUSE_MOVE,
|
||||
KEY_PRESS,
|
||||
MOUSE_UP,
|
||||
});
|
||||
}
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="event_router",
|
||||
.tests={
|
||||
TEST(test_basic_router_operations_test),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
119
tests/fsm.cpp
119
tests/fsm.cpp
|
|
@ -1,67 +1,78 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <string>
|
||||
#include "algos/simplefsm.hpp"
|
||||
|
||||
using namespace fmt;
|
||||
using std::string;
|
||||
using namespace fuc2;
|
||||
|
||||
enum class MyState {
|
||||
START, RUNNING, END
|
||||
};
|
||||
namespace fsm_tests {
|
||||
enum class MyState {
|
||||
START, RUNNING, END
|
||||
};
|
||||
|
||||
enum class MyEvent {
|
||||
STARTED, PUSH, QUIT
|
||||
};
|
||||
enum class MyEvent {
|
||||
STARTED, PUSH, QUIT
|
||||
};
|
||||
|
||||
class MyFSM : public DeadSimpleFSM<MyState, MyEvent> {
|
||||
public:
|
||||
void event(MyEvent ev, string data="") {
|
||||
switch($state) {
|
||||
FSM_STATE(MyState, START, ev);
|
||||
FSM_STATE(MyState, RUNNING, ev, data);
|
||||
FSM_STATE(MyState, END, ev);
|
||||
}
|
||||
class MyFSM : public DeadSimpleFSM<MyState, MyEvent> {
|
||||
public:
|
||||
void event(MyEvent ev, string data="") {
|
||||
switch($state) {
|
||||
FSM_STATE(MyState, START, ev);
|
||||
FSM_STATE(MyState, RUNNING, ev, data);
|
||||
FSM_STATE(MyState, END, ev);
|
||||
}
|
||||
}
|
||||
|
||||
void START(MyEvent ev) {
|
||||
println("<<< START {}", (int)ev);
|
||||
state(MyState::RUNNING);
|
||||
}
|
||||
|
||||
void RUNNING(MyEvent ev, string &data) {
|
||||
if(ev == MyEvent::QUIT) {
|
||||
println("<<< QUITTING {}", data);
|
||||
state(MyState::END);
|
||||
} else {
|
||||
println("<<< RUN: {}", data);
|
||||
state(MyState::RUNNING);
|
||||
}
|
||||
}
|
||||
|
||||
void END(MyEvent ev) {
|
||||
println("<<< STOP {}", (int)ev);
|
||||
state(MyState::END);
|
||||
}
|
||||
};
|
||||
|
||||
void test_confirm_fsm_works_with_optional_data() {
|
||||
MyFSM fsm;
|
||||
|
||||
CHECK(fsm.in_state(MyState::START));
|
||||
|
||||
fsm.event(MyEvent::STARTED);
|
||||
CHECK(fsm.in_state(MyState::RUNNING));
|
||||
|
||||
fsm.event(MyEvent::PUSH);
|
||||
CHECK(fsm.in_state(MyState::RUNNING));
|
||||
|
||||
fsm.event(MyEvent::PUSH);
|
||||
CHECK(fsm.in_state(MyState::RUNNING));
|
||||
|
||||
fsm.event(MyEvent::PUSH);
|
||||
CHECK(fsm.in_state(MyState::RUNNING));
|
||||
|
||||
fsm.event(MyEvent::QUIT, "DONE!");
|
||||
CHECK(fsm.in_state(MyState::END));
|
||||
}
|
||||
|
||||
void START(MyEvent ev) {
|
||||
println("<<< START {}", (int)ev);
|
||||
state(MyState::RUNNING);
|
||||
}
|
||||
|
||||
void RUNNING(MyEvent ev, string &data) {
|
||||
if(ev == MyEvent::QUIT) {
|
||||
println("<<< QUITTING {}", data);
|
||||
state(MyState::END);
|
||||
} else {
|
||||
println("<<< RUN: {}", data);
|
||||
state(MyState::RUNNING);
|
||||
}
|
||||
}
|
||||
|
||||
void END(MyEvent ev) {
|
||||
println("<<< STOP {}", (int)ev);
|
||||
state(MyState::END);
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE("confirm fsm works with optional data", "[utils]") {
|
||||
MyFSM fsm;
|
||||
|
||||
REQUIRE(fsm.in_state(MyState::START));
|
||||
|
||||
fsm.event(MyEvent::STARTED);
|
||||
REQUIRE(fsm.in_state(MyState::RUNNING));
|
||||
|
||||
fsm.event(MyEvent::PUSH);
|
||||
REQUIRE(fsm.in_state(MyState::RUNNING));
|
||||
|
||||
fsm.event(MyEvent::PUSH);
|
||||
REQUIRE(fsm.in_state(MyState::RUNNING));
|
||||
|
||||
fsm.event(MyEvent::PUSH);
|
||||
REQUIRE(fsm.in_state(MyState::RUNNING));
|
||||
|
||||
fsm.event(MyEvent::QUIT, "DONE!");
|
||||
REQUIRE(fsm.in_state(MyState::END));
|
||||
fuc2::Set TESTS{
|
||||
.name="fsm",
|
||||
.tests={
|
||||
TEST(test_confirm_fsm_works_with_optional_data),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,52 +1,63 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <string>
|
||||
#include "game/inventory.hpp"
|
||||
|
||||
using namespace fmt;
|
||||
using namespace fuc2;
|
||||
|
||||
TEST_CASE("base test", "[inventory]") {
|
||||
return;
|
||||
inventory::Model inv;
|
||||
DinkyECS::Entity test_ent = 1;
|
||||
namespace inventory_tests {
|
||||
void test_base_test() {
|
||||
return;
|
||||
inventory::Model inv;
|
||||
DinkyECS::Entity test_ent = 1;
|
||||
|
||||
bool good = inv.add("hand_l", test_ent);
|
||||
inv.invariant();
|
||||
REQUIRE(good);
|
||||
bool good = inv.add("hand_l", test_ent);
|
||||
inv.invariant();
|
||||
CHECK(good);
|
||||
|
||||
auto& slot = inv.get(test_ent);
|
||||
REQUIRE(slot == "hand_l");
|
||||
auto& slot = inv.get(test_ent);
|
||||
CHECK(slot == "hand_l");
|
||||
|
||||
// confirm that we get false when trying to do it again
|
||||
// BUG: this dies
|
||||
good = inv.add("hand_l", test_ent);
|
||||
REQUIRE(!good);
|
||||
// confirm that we get false when trying to do it again
|
||||
// BUG: this dies
|
||||
good = inv.add("hand_l", test_ent);
|
||||
CHECK(!good);
|
||||
|
||||
auto ent = inv.get(slot);
|
||||
REQUIRE(ent == test_ent);
|
||||
auto ent = inv.get(slot);
|
||||
CHECK(ent == test_ent);
|
||||
|
||||
REQUIRE(inv.has(ent));
|
||||
REQUIRE(inv.has(slot));
|
||||
CHECK(inv.has(ent));
|
||||
CHECK(inv.has(slot));
|
||||
|
||||
// test base remove
|
||||
inv.remove(ent);
|
||||
REQUIRE(!inv.has(slot));
|
||||
REQUIRE(!inv.has(ent));
|
||||
}
|
||||
|
||||
TEST_CASE("test swapping items", "[inventory]") {
|
||||
inventory::Model inv;
|
||||
DinkyECS::Entity hand_l_ent = 10;
|
||||
DinkyECS::Entity hand_r_ent = 20;
|
||||
|
||||
inv.add("hand_l", hand_l_ent);
|
||||
inv.add("hand_r", hand_r_ent);
|
||||
REQUIRE(inv.count() == 2);
|
||||
|
||||
inv.swap(hand_l_ent, hand_r_ent);
|
||||
|
||||
REQUIRE(inv.get("hand_l") == hand_r_ent);
|
||||
REQUIRE(inv.get("hand_r") == hand_l_ent);
|
||||
|
||||
REQUIRE(inv.count() == 2);
|
||||
// test base remove
|
||||
inv.remove(ent);
|
||||
CHECK(!inv.has(slot));
|
||||
CHECK(!inv.has(ent));
|
||||
}
|
||||
|
||||
void test_test_swapping_items() {
|
||||
inventory::Model inv;
|
||||
DinkyECS::Entity hand_l_ent = 10;
|
||||
DinkyECS::Entity hand_r_ent = 20;
|
||||
|
||||
inv.add("hand_l", hand_l_ent);
|
||||
inv.add("hand_r", hand_r_ent);
|
||||
CHECK(inv.count() == 2);
|
||||
|
||||
inv.swap(hand_l_ent, hand_r_ent);
|
||||
|
||||
CHECK(inv.get("hand_l") == hand_r_ent);
|
||||
CHECK(inv.get("hand_r") == hand_l_ent);
|
||||
|
||||
CHECK(inv.count() == 2);
|
||||
}
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="inventory",
|
||||
.tests={
|
||||
TEST(test_base_test),
|
||||
TEST(test_test_swapping_items),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
|
|
@ -8,35 +8,47 @@
|
|||
#include "algos/point.hpp"
|
||||
|
||||
using namespace lighting;
|
||||
using namespace fuc2;
|
||||
|
||||
TEST_CASE("lighting a map works", "[lighting]") {
|
||||
GameDB::init();
|
||||
auto& level = GameDB::current_level();
|
||||
auto& map = *level.map;
|
||||
namespace lighting_tests {
|
||||
|
||||
Point light1, light2;
|
||||
void test_lighting_a_map_works() {
|
||||
GameDB::init();
|
||||
auto& level = GameDB::current_level();
|
||||
auto& map = *level.map;
|
||||
|
||||
REQUIRE(map.place_entity(0, light1));
|
||||
REQUIRE(map.place_entity(0, light1));
|
||||
Point light1, light2;
|
||||
|
||||
LightSource source1{6, 1.0};
|
||||
LightSource source2{4,3};
|
||||
CHECK(map.place_entity(0, light1));
|
||||
CHECK(map.place_entity(0, light1));
|
||||
|
||||
LightRender lr(map.walls());
|
||||
LightSource source1{6, 1.0};
|
||||
LightSource source2{4,3};
|
||||
|
||||
lr.reset_light();
|
||||
LightRender lr(map.walls());
|
||||
|
||||
lr.set_light_target(light1);
|
||||
lr.set_light_target(light2);
|
||||
lr.reset_light();
|
||||
|
||||
lr.path_light(map.walls());
|
||||
lr.set_light_target(light1);
|
||||
lr.set_light_target(light2);
|
||||
|
||||
lr.render_light(source1, light1);
|
||||
lr.render_light(source2, light2);
|
||||
lr.path_light(map.walls());
|
||||
|
||||
lr.clear_light_target(light1);
|
||||
lr.clear_light_target(light2);
|
||||
lr.render_light(source1, light1);
|
||||
lr.render_light(source2, light2);
|
||||
|
||||
Matrix &lighting = lr.lighting();
|
||||
(void)lighting;
|
||||
lr.clear_light_target(light1);
|
||||
lr.clear_light_target(light2);
|
||||
|
||||
Matrix &lighting = lr.lighting();
|
||||
(void)lighting;
|
||||
}
|
||||
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="lighting",
|
||||
.tests={
|
||||
TEST(test_lighting_a_map_works),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <string>
|
||||
#include "game/components.hpp"
|
||||
|
|
@ -6,16 +6,26 @@
|
|||
|
||||
using namespace fmt;
|
||||
using namespace components;
|
||||
using namespace fuc2;
|
||||
|
||||
TEST_CASE("test the loot ui", "[loot]") {
|
||||
auto items = settings::get("assets/items.json");
|
||||
DinkyECS::World world;
|
||||
auto torch = world.entity();
|
||||
auto& data = items["TORCH_BAD"];
|
||||
namespace loot_tests {
|
||||
void test_test_the_loot_ui() {
|
||||
auto items = settings::get("assets/items.json");
|
||||
DinkyECS::World world;
|
||||
auto torch = world.entity();
|
||||
auto& data = items["TORCH_BAD"];
|
||||
|
||||
components::init();
|
||||
components::configure_entity(world, torch, data["components"]);
|
||||
components::init();
|
||||
components::configure_entity(world, torch, data["components"]);
|
||||
|
||||
auto& torch_sprite = world.get<Sprite>(torch);
|
||||
REQUIRE(torch_sprite.name == "torch_horizontal_floor");
|
||||
auto& torch_sprite = world.get<Sprite>(torch);
|
||||
CHECK(torch_sprite.name == "torch_horizontal_floor");
|
||||
}
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="loot",
|
||||
.tests={
|
||||
TEST(test_test_the_loot_ui),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,13 @@ TEST_SET(component_tests);
|
|||
TEST_SET(config_tests);
|
||||
TEST_SET(dbc_tests);
|
||||
TEST_SET(dinkyecs_tests);
|
||||
TEST_SET(event_router_tests);
|
||||
TEST_SET(inventory_tests);
|
||||
TEST_SET(lighting_tests);
|
||||
TEST_SET(loot_tests);
|
||||
TEST_SET(map_tests);
|
||||
TEST_SET(matrix_tests);
|
||||
TEST_SET(mazes_tests);
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
run(ai_tests::TESTS);
|
||||
|
|
@ -22,4 +29,11 @@ int main(int argc, char* argv[]) {
|
|||
run(config_tests::TESTS);
|
||||
run(dbc_tests::TESTS);
|
||||
run(dinkyecs_tests::TESTS);
|
||||
run(event_router_tests::TESTS);
|
||||
run(inventory_tests::TESTS);
|
||||
run(lighting_tests::TESTS);
|
||||
run(loot_tests::TESTS);
|
||||
run(map_tests::TESTS);
|
||||
run(matrix_tests::TESTS);
|
||||
run(mazes_tests::TESTS);
|
||||
}
|
||||
|
|
|
|||
108
tests/map.cpp
108
tests/map.cpp
|
|
@ -1,4 +1,4 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <fstream>
|
||||
|
|
@ -12,74 +12,86 @@
|
|||
using namespace fmt;
|
||||
using namespace nlohmann;
|
||||
using std::string;
|
||||
using namespace fuc2;
|
||||
|
||||
json load_test_data(const string &fname) {
|
||||
std::ifstream infile(fname);
|
||||
return json::parse(infile);
|
||||
}
|
||||
namespace map_tests {
|
||||
json load_test_data(const string &fname) {
|
||||
std::ifstream infile(fname);
|
||||
return json::parse(infile);
|
||||
}
|
||||
|
||||
TEST_CASE("camera control", "[map]") {
|
||||
GameDB::init();
|
||||
void test_camera_control() {
|
||||
GameDB::init();
|
||||
|
||||
auto& level = GameDB::current_level();
|
||||
auto& map = *level.map;
|
||||
auto& level = GameDB::current_level();
|
||||
auto& map = *level.map;
|
||||
|
||||
Point center = map.center_camera({10,10}, 5, 5);
|
||||
Point center = map.center_camera({10,10}, 5, 5);
|
||||
|
||||
// map.dump(center.x, center.y);
|
||||
REQUIRE(center.x == 8);
|
||||
REQUIRE(center.y == 8);
|
||||
// map.dump(center.x, center.y);
|
||||
CHECK(center.x == 8);
|
||||
CHECK(center.y == 8);
|
||||
|
||||
Point translation = map.map_to_camera({10,10}, center);
|
||||
Point translation = map.map_to_camera({10,10}, center);
|
||||
|
||||
REQUIRE(translation.x == 2);
|
||||
REQUIRE(translation.y == 2);
|
||||
}
|
||||
CHECK(translation.x == 2);
|
||||
CHECK(translation.y == 2);
|
||||
}
|
||||
|
||||
TEST_CASE("map placement test", "[map-fail]") {
|
||||
GameDB::init();
|
||||
void test_map_placement_test() {
|
||||
GameDB::init();
|
||||
|
||||
for(int i = 0; i < 10; i++) {
|
||||
auto& level = GameDB::create_level();
|
||||
for(int i = 0; i < 10; i++) {
|
||||
auto& level = GameDB::create_level();
|
||||
|
||||
for(size_t rnum = 0; rnum < level.map->room_count(); rnum++) {
|
||||
Point pos;
|
||||
for(size_t rnum = 0; rnum < level.map->room_count(); rnum++) {
|
||||
Point pos;
|
||||
|
||||
REQUIRE(level.map->place_entity(rnum, pos));
|
||||
CHECK(level.map->place_entity(rnum, pos));
|
||||
|
||||
REQUIRE(!level.map->iswall(pos.x, pos.y));
|
||||
REQUIRE(level.map->inmap(pos.x, pos.y));
|
||||
CHECK(!level.map->iswall(pos.x, pos.y));
|
||||
CHECK(level.map->inmap(pos.x, pos.y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("map image test", "[map]") {
|
||||
GameDB::init();
|
||||
void test_map_image_test() {
|
||||
GameDB::init();
|
||||
|
||||
auto& level = GameDB::current_level();
|
||||
Matrix map_tiles = matrix::make(7,7);
|
||||
EntityGrid entity_map;
|
||||
auto& level = GameDB::current_level();
|
||||
Matrix map_tiles = matrix::make(7,7);
|
||||
EntityGrid entity_map;
|
||||
|
||||
auto render = std::make_shared<sf::RenderTexture>();
|
||||
sf::Sprite sprite{render->getTexture()};
|
||||
auto player = level.world->get_the<components::Player>();
|
||||
auto& player_pos = level.world->get<components::Position>(player.entity);
|
||||
auto player_display = level.world->get<components::Tile>(player.entity).display;
|
||||
auto render = std::make_shared<sf::RenderTexture>();
|
||||
sf::Sprite sprite{render->getTexture()};
|
||||
auto player = level.world->get_the<components::Player>();
|
||||
auto& player_pos = level.world->get<components::Position>(player.entity);
|
||||
auto player_display = level.world->get<components::Tile>(player.entity).display;
|
||||
|
||||
for(matrix::each_row it{level.map->walls()}; it.next();) {
|
||||
player_pos.location.x = it.x;
|
||||
player_pos.location.y = it.y;
|
||||
System::draw_map(map_tiles, entity_map);
|
||||
System::render_map(map_tiles, entity_map, *render, 2, player_display);
|
||||
for(matrix::each_row it{level.map->walls()}; it.next();) {
|
||||
player_pos.location.x = it.x;
|
||||
player_pos.location.y = it.y;
|
||||
System::draw_map(map_tiles, entity_map);
|
||||
System::render_map(map_tiles, entity_map, *render, 2, player_display);
|
||||
|
||||
// randomly test about 80% of them
|
||||
if(Random::uniform(0, 100) < 20) break;
|
||||
// randomly test about 80% of them
|
||||
if(Random::uniform(0, 100) < 20) break;
|
||||
|
||||
#ifdef TEST_RENDER
|
||||
// confirm we get two different maps
|
||||
auto out_img = render->getTexture().copyToImage();
|
||||
bool worked = out_img.saveToFile(fmt::format("tmp/map_render{}{}.png", it.x, it.y));
|
||||
REQUIRE(worked);
|
||||
// confirm we get two different maps
|
||||
auto out_img = render->getTexture().copyToImage();
|
||||
bool worked = out_img.saveToFile(fmt::format("tmp/map_render{}{}.png", it.x, it.y));
|
||||
CHECK(worked);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="map",
|
||||
.tests={
|
||||
TEST(test_camera_control),
|
||||
TEST(test_map_placement_test),
|
||||
TEST(test_map_image_test),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
434
tests/matrix.cpp
434
tests/matrix.cpp
|
|
@ -1,4 +1,4 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <string>
|
||||
#include "game/config.hpp"
|
||||
|
|
@ -13,265 +13,283 @@
|
|||
|
||||
using namespace nlohmann;
|
||||
using namespace fmt;
|
||||
using namespace fuc2;
|
||||
using std::string, std::shared_ptr;
|
||||
using matrix::Matrix;
|
||||
|
||||
std::shared_ptr<Map> make_map() {
|
||||
GameDB::init();
|
||||
return GameDB::current_level().map;
|
||||
}
|
||||
|
||||
// BUG: create a test that randomizes a map then does matrix ops on it
|
||||
|
||||
inline void random_matrix(Matrix &out) {
|
||||
for(size_t y = 0; y < out.size(); y++) {
|
||||
for(size_t x = 0; x < out[0].size(); x++) {
|
||||
out[y][x] = Random::uniform<int>(-10,10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("thrash matrix iterators", "[matrix]") {
|
||||
for(int count = 0; count < 5; count++) {
|
||||
size_t width = Random::uniform<size_t>(1, 100);
|
||||
size_t height = Random::uniform<size_t>(1, 100);
|
||||
|
||||
Matrix test(height, matrix::Row(width));
|
||||
random_matrix(test);
|
||||
|
||||
// first make a randomized matrix
|
||||
matrix::each_cell cells{test};
|
||||
cells.next(); // kick off the other iterator
|
||||
|
||||
for(matrix::each_row it{test};
|
||||
it.next(); cells.next())
|
||||
{
|
||||
REQUIRE(test[cells.y][cells.x] == test[it.y][it.x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("thrash box distance iterators", "[matrix]") {
|
||||
size_t width = Random::uniform<size_t>(10, 21);
|
||||
size_t height = Random::uniform<size_t>(10, 25);
|
||||
|
||||
Matrix result(height, matrix::Row(width));
|
||||
matrix::assign(result, 0);
|
||||
|
||||
size_t size = Random::uniform<int>(4, 10);
|
||||
|
||||
Point target{width/2, height/2};
|
||||
matrix::box box{result, target.x, target.y, size};
|
||||
while(box.next()) {
|
||||
result[box.y][box.x] = box.distance();
|
||||
namespace matrix_tests {
|
||||
std::shared_ptr<Map> make_map() {
|
||||
GameDB::init();
|
||||
return GameDB::current_level().map;
|
||||
}
|
||||
|
||||
// matrix::dump(format("MAP {}x{} @ {},{}; BOX {}x{}; size: {}",
|
||||
// matrix::width(result), matrix::height(result),
|
||||
// target.x, target.y, box.right - box.left, box.bottom - box.top, size),
|
||||
// result, target.x, target.y);
|
||||
}
|
||||
// BUG: create a test that randomizes a map then does matrix ops on it
|
||||
|
||||
TEST_CASE("thrash box iterators", "[matrix]") {
|
||||
for(int count = 0; count < 5; count++) {
|
||||
size_t width = Random::uniform<size_t>(1, 25);
|
||||
size_t height = Random::uniform<size_t>(1, 33);
|
||||
|
||||
Matrix test(height, matrix::Row(width));
|
||||
random_matrix(test);
|
||||
|
||||
// this will be greater than the random_matrix cells
|
||||
int test_i = Random::uniform<size_t>(20,30);
|
||||
|
||||
// go through every cell
|
||||
for(matrix::each_cell target{test}; target.next();) {
|
||||
PointList result;
|
||||
// make a random size box
|
||||
size_t size = Random::uniform<int>(1, 33);
|
||||
matrix::box box{test, target.x, target.y, size};
|
||||
|
||||
while(box.next()) {
|
||||
test[box.y][box.x] = test_i;
|
||||
result.push_back({box.x, box.y});
|
||||
}
|
||||
|
||||
for(auto point : result) {
|
||||
REQUIRE(test[point.y][point.x] == test_i);
|
||||
test[point.y][point.x] = 10; // kind of reset it for another try
|
||||
inline void random_matrix(Matrix &out) {
|
||||
for(size_t y = 0; y < out.size(); y++) {
|
||||
for(size_t x = 0; x < out[0].size(); x++) {
|
||||
out[y][x] = Random::uniform<int>(-10,10);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("thrash compass iterators", "[matrix]") {
|
||||
for(int count = 0; count < 5; count++) {
|
||||
size_t width = Random::uniform<size_t>(1, 25);
|
||||
size_t height = Random::uniform<size_t>(1, 33);
|
||||
void test_thrash_matrix_iterators() {
|
||||
for(int count = 0; count < 5; count++) {
|
||||
size_t width = Random::uniform<size_t>(1, 100);
|
||||
size_t height = Random::uniform<size_t>(1, 100);
|
||||
|
||||
Matrix test(height, matrix::Row(width));
|
||||
random_matrix(test);
|
||||
Matrix test(height, matrix::Row(width));
|
||||
random_matrix(test);
|
||||
|
||||
// this will be greater than the random_matrix cells
|
||||
int test_i = Random::uniform<size_t>(20,30);
|
||||
// first make a randomized matrix
|
||||
matrix::each_cell cells{test};
|
||||
cells.next(); // kick off the other iterator
|
||||
|
||||
// go through every cell
|
||||
for(matrix::each_cell target{test}; target.next();) {
|
||||
PointList result;
|
||||
// make a random size box
|
||||
matrix::compass compass{test, target.x, target.y};
|
||||
|
||||
while(compass.next()) {
|
||||
test[compass.y][compass.x] = test_i;
|
||||
result.push_back({compass.x, compass.y});
|
||||
}
|
||||
|
||||
for(auto point : result) {
|
||||
REQUIRE(test[point.y][point.x] == test_i);
|
||||
test[point.y][point.x] = 10; // kind of reset it for another try
|
||||
for(matrix::each_row it{test};
|
||||
it.next(); cells.next())
|
||||
{
|
||||
CHECK(test[cells.y][cells.x] == test[it.y][it.x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("prototype line algorithm", "[matrix]") {
|
||||
size_t width = Random::uniform<size_t>(10, 12);
|
||||
size_t height = Random::uniform<size_t>(10, 15);
|
||||
Map map(width,height);
|
||||
// create a target for the paths
|
||||
Point start{.x=map.width() / 2, .y=map.height()/2};
|
||||
void test_thrash_box_distance_iterators() {
|
||||
size_t width = Random::uniform<size_t>(10, 21);
|
||||
size_t height = Random::uniform<size_t>(10, 25);
|
||||
|
||||
for(matrix::box box{map.walls(), start.x, start.y, 3};
|
||||
box.next();)
|
||||
{
|
||||
Matrix result = map.walls();
|
||||
result[start.y][start.x] = 1;
|
||||
Point end{.x=box.x, .y=box.y};
|
||||
Matrix result(height, matrix::Row(width));
|
||||
matrix::assign(result, 0);
|
||||
|
||||
for(matrix::line it{start, end}; it.next();)
|
||||
{
|
||||
REQUIRE(map.inmap(it.x, it.y));
|
||||
result[it.y][it.x] = 15;
|
||||
size_t size = Random::uniform<int>(4, 10);
|
||||
|
||||
Point target{width/2, height/2};
|
||||
matrix::box box{result, target.x, target.y, size};
|
||||
while(box.next()) {
|
||||
result[box.y][box.x] = box.distance();
|
||||
}
|
||||
|
||||
result[start.y][start.x] = 15;
|
||||
// matrix::dump(format("MAP {}x{} @ {},{}; BOX {}x{}; size: {}",
|
||||
// matrix::width(result), matrix::height(result),
|
||||
// target.x, target.y, box.right - box.left, box.bottom - box.top, size),
|
||||
// result, target.x, target.y);
|
||||
}
|
||||
|
||||
// matrix::dump("RESULT AFTER LINE", result, end.x, end.y);
|
||||
void test_thrash_box_iterators() {
|
||||
for(int count = 0; count < 5; count++) {
|
||||
size_t width = Random::uniform<size_t>(1, 25);
|
||||
size_t height = Random::uniform<size_t>(1, 33);
|
||||
|
||||
bool f_found = false;
|
||||
for(matrix::each_cell it{result}; it.next();) {
|
||||
if(result[it.y][it.x] == 15) {
|
||||
f_found = true;
|
||||
break;
|
||||
Matrix test(height, matrix::Row(width));
|
||||
random_matrix(test);
|
||||
|
||||
// this will be greater than the random_matrix cells
|
||||
int test_i = Random::uniform<size_t>(20,30);
|
||||
|
||||
// go through every cell
|
||||
for(matrix::each_cell target{test}; target.next();) {
|
||||
PointList result;
|
||||
// make a random size box
|
||||
size_t size = Random::uniform<int>(1, 33);
|
||||
matrix::box box{test, target.x, target.y, size};
|
||||
|
||||
while(box.next()) {
|
||||
test[box.y][box.x] = test_i;
|
||||
result.push_back({box.x, box.y});
|
||||
}
|
||||
|
||||
for(auto point : result) {
|
||||
CHECK(test[point.y][point.x] == test_i);
|
||||
test[point.y][point.x] = 10; // kind of reset it for another try
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(f_found);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("prototype circle algorithm", "[matrix]") {
|
||||
for(int count = 0; count < 5; count++) {
|
||||
size_t width = Random::uniform<size_t>(10, 13);
|
||||
void test_thrash_compass_iterators() {
|
||||
for(int count = 0; count < 5; count++) {
|
||||
size_t width = Random::uniform<size_t>(1, 25);
|
||||
size_t height = Random::uniform<size_t>(1, 33);
|
||||
|
||||
Matrix test(height, matrix::Row(width));
|
||||
random_matrix(test);
|
||||
|
||||
// this will be greater than the random_matrix cells
|
||||
int test_i = Random::uniform<size_t>(20,30);
|
||||
|
||||
// go through every cell
|
||||
for(matrix::each_cell target{test}; target.next();) {
|
||||
PointList result;
|
||||
// make a random size box
|
||||
matrix::compass compass{test, target.x, target.y};
|
||||
|
||||
while(compass.next()) {
|
||||
test[compass.y][compass.x] = test_i;
|
||||
result.push_back({compass.x, compass.y});
|
||||
}
|
||||
|
||||
for(auto point : result) {
|
||||
CHECK(test[point.y][point.x] == test_i);
|
||||
test[point.y][point.x] = 10; // kind of reset it for another try
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_prototype_line_algorithm() {
|
||||
size_t width = Random::uniform<size_t>(10, 12);
|
||||
size_t height = Random::uniform<size_t>(10, 15);
|
||||
int pos_mod = Random::uniform<int>(-3,3);
|
||||
Map map(width,height);
|
||||
|
||||
// create a target for the paths
|
||||
Point start{.x=map.width() / 2 + pos_mod, .y=map.height()/2 + pos_mod};
|
||||
Point start{.x=map.width() / 2, .y=map.height()/2};
|
||||
|
||||
for(float radius = 1.0f; radius < 4.0f; radius += 0.1f) {
|
||||
// use an empty map
|
||||
for(matrix::box box{map.walls(), start.x, start.y, 3};
|
||||
box.next();)
|
||||
{
|
||||
Matrix result = map.walls();
|
||||
result[start.y][start.x] = 1;
|
||||
Point end{.x=box.x, .y=box.y};
|
||||
|
||||
for(matrix::circle it{result, start, radius}; it.next();) {
|
||||
for(int x = it.left; x < it.right; x++) {
|
||||
// println("top={}, bottom={}, center.y={}, dy={}, left={}, right={}, x={}, y={}", it.top, it.bottom, it.center.y, it.dy, it.left, it.right, x, it.y);
|
||||
// println("RESULT {},{}", matrix::width(result), matrix::height(result));
|
||||
REQUIRE(it.y >= 0);
|
||||
REQUIRE(x >= 0);
|
||||
REQUIRE(it.y < int(matrix::height(result)));
|
||||
REQUIRE(x < int(matrix::width(result)));
|
||||
result[it.y][x] += 1;
|
||||
for(matrix::line it{start, end}; it.next();)
|
||||
{
|
||||
CHECK(map.inmap(it.x, it.y));
|
||||
result[it.y][it.x] = 15;
|
||||
}
|
||||
|
||||
result[start.y][start.x] = 15;
|
||||
|
||||
// matrix::dump("RESULT AFTER LINE", result, end.x, end.y);
|
||||
|
||||
bool f_found = false;
|
||||
for(matrix::each_cell it{result}; it.next();) {
|
||||
if(result[it.y][it.x] == 15) {
|
||||
f_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// matrix::dump(format("RESULT AFTER CIRCLE radius {}", radius), result, start.x, start.y);
|
||||
CHECK(f_found);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("viewport iterator", "[matrix]") {
|
||||
components::init();
|
||||
textures::init();
|
||||
GameDB::init();
|
||||
size_t width = Random::uniform<size_t>(20, 22);
|
||||
size_t height = Random::uniform<size_t>(21, 25);
|
||||
shared_ptr<Map> map = make_map();
|
||||
void test_prototype_circle_algorithm() {
|
||||
for(int count = 0; count < 5; count++) {
|
||||
size_t width = Random::uniform<size_t>(10, 13);
|
||||
size_t height = Random::uniform<size_t>(10, 15);
|
||||
int pos_mod = Random::uniform<int>(-3,3);
|
||||
Map map(width,height);
|
||||
|
||||
size_t view_width = width/2;
|
||||
size_t view_height = height/2;
|
||||
Point player;
|
||||
REQUIRE(map->place_entity(1, player));
|
||||
Point start = map->center_camera(player, view_width, view_height);
|
||||
// create a target for the paths
|
||||
Point start{.x=map.width() / 2 + pos_mod, .y=map.height()/2 + pos_mod};
|
||||
|
||||
size_t end_x = std::min(view_width, map->width() - start.x);
|
||||
size_t end_y = std::min(view_height, map->height() - start.y);
|
||||
for(float radius = 1.0f; radius < 4.0f; radius += 0.1f) {
|
||||
// use an empty map
|
||||
Matrix result = map.walls();
|
||||
|
||||
matrix::viewport it{map->walls(), start, int(view_width), int(view_height)};
|
||||
for(matrix::circle it{result, start, radius}; it.next();) {
|
||||
for(int x = it.left; x < it.right; x++) {
|
||||
// println("top={}, bottom={}, center.y={}, dy={}, left={}, right={}, x={}, y={}", it.top, it.bottom, it.center.y, it.dy, it.left, it.right, x, it.y);
|
||||
// println("RESULT {},{}", matrix::width(result), matrix::height(result));
|
||||
CHECK(it.y >= 0);
|
||||
CHECK(x >= 0);
|
||||
CHECK(it.y < int(matrix::height(result)));
|
||||
CHECK(x < int(matrix::width(result)));
|
||||
result[it.y][x] += 1;
|
||||
}
|
||||
}
|
||||
|
||||
for(size_t y = 0; y < end_y; ++y) {
|
||||
for(size_t x = 0; x < end_x && it.next(); ++x) {
|
||||
// still working on this
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("random rectangle", "[matrix]") {
|
||||
components::init();
|
||||
for(int i = 0; i < 5; i++) {
|
||||
shared_ptr<Map> map = make_map();
|
||||
map->invert_space();
|
||||
auto wall_copy = map->walls();
|
||||
|
||||
for(size_t rnum = 0; rnum < map->room_count(); rnum++) {
|
||||
Room &room = map->room(rnum);
|
||||
Point pos;
|
||||
|
||||
for(matrix::rando_rect it{map->walls(), room.x, room.y, room.width, room.height}; it.next();)
|
||||
{
|
||||
REQUIRE(size_t(it.x) >= room.x);
|
||||
REQUIRE(size_t(it.y) >= room.y);
|
||||
REQUIRE(size_t(it.x) <= room.x + room.width);
|
||||
REQUIRE(size_t(it.y) <= room.y + room.height);
|
||||
|
||||
wall_copy[it.y][it.x] = wall_copy[it.y][it.x] + 5;
|
||||
// matrix::dump(format("RESULT AFTER CIRCLE radius {}", radius), result, start.x, start.y);
|
||||
}
|
||||
}
|
||||
// matrix::dump("WALLS FILLED", wall_copy);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("standard rectangle", "[matrix]") {
|
||||
components::init();
|
||||
for(int i = 0; i < 5; i++) {
|
||||
void test_viewport_iterator() {
|
||||
components::init();
|
||||
textures::init();
|
||||
GameDB::init();
|
||||
size_t width = Random::uniform<size_t>(20, 22);
|
||||
size_t height = Random::uniform<size_t>(21, 25);
|
||||
shared_ptr<Map> map = make_map();
|
||||
auto wall_copy = map->walls();
|
||||
|
||||
for(size_t rnum = 0; rnum < map->room_count(); rnum++) {
|
||||
Room &room = map->room(rnum);
|
||||
Point pos;
|
||||
size_t view_width = width/2;
|
||||
size_t view_height = height/2;
|
||||
Point player;
|
||||
CHECK(map->place_entity(1, player));
|
||||
Point start = map->center_camera(player, view_width, view_height);
|
||||
|
||||
for(matrix::rectangle it{map->walls(), room.x, room.y, room.width, room.height}; it.next();)
|
||||
{
|
||||
REQUIRE(size_t(it.x) >= room.x);
|
||||
REQUIRE(size_t(it.y) >= room.y);
|
||||
REQUIRE(size_t(it.x) <= room.x + room.width);
|
||||
REQUIRE(size_t(it.y) <= room.y + room.height);
|
||||
size_t end_x = std::min(view_width, map->width() - start.x);
|
||||
size_t end_y = std::min(view_height, map->height() - start.y);
|
||||
|
||||
wall_copy[it.y][it.x] = wall_copy[it.y][it.x] + 5;
|
||||
matrix::viewport it{map->walls(), start, int(view_width), int(view_height)};
|
||||
|
||||
for(size_t y = 0; y < end_y; ++y) {
|
||||
for(size_t x = 0; x < end_x && it.next(); ++x) {
|
||||
// still working on this
|
||||
}
|
||||
}
|
||||
|
||||
// matrix::dump("WALLS FILLED", wall_copy);
|
||||
}
|
||||
|
||||
void test_random_rectangle() {
|
||||
components::init();
|
||||
for(int i = 0; i < 5; i++) {
|
||||
shared_ptr<Map> map = make_map();
|
||||
map->invert_space();
|
||||
auto wall_copy = map->walls();
|
||||
|
||||
for(size_t rnum = 0; rnum < map->room_count(); rnum++) {
|
||||
Room &room = map->room(rnum);
|
||||
Point pos;
|
||||
|
||||
for(matrix::rando_rect it{map->walls(), room.x, room.y, room.width, room.height}; it.next();)
|
||||
{
|
||||
CHECK(size_t(it.x) >= room.x);
|
||||
CHECK(size_t(it.y) >= room.y);
|
||||
CHECK(size_t(it.x) <= room.x + room.width);
|
||||
CHECK(size_t(it.y) <= room.y + room.height);
|
||||
|
||||
wall_copy[it.y][it.x] = wall_copy[it.y][it.x] + 5;
|
||||
}
|
||||
}
|
||||
// matrix::dump("WALLS FILLED", wall_copy);
|
||||
}
|
||||
}
|
||||
|
||||
void test_standard_rectangle() {
|
||||
components::init();
|
||||
for(int i = 0; i < 5; i++) {
|
||||
shared_ptr<Map> map = make_map();
|
||||
auto wall_copy = map->walls();
|
||||
|
||||
for(size_t rnum = 0; rnum < map->room_count(); rnum++) {
|
||||
Room &room = map->room(rnum);
|
||||
Point pos;
|
||||
|
||||
for(matrix::rectangle it{map->walls(), room.x, room.y, room.width, room.height}; it.next();)
|
||||
{
|
||||
CHECK(size_t(it.x) >= room.x);
|
||||
CHECK(size_t(it.y) >= room.y);
|
||||
CHECK(size_t(it.x) <= room.x + room.width);
|
||||
CHECK(size_t(it.y) <= room.y + room.height);
|
||||
|
||||
wall_copy[it.y][it.x] = wall_copy[it.y][it.x] + 5;
|
||||
}
|
||||
}
|
||||
|
||||
// matrix::dump("WALLS FILLED", wall_copy);
|
||||
}
|
||||
}
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="matrix",
|
||||
.tests={
|
||||
TEST(test_thrash_matrix_iterators),
|
||||
TEST(test_thrash_box_distance_iterators),
|
||||
TEST(test_thrash_box_iterators),
|
||||
TEST(test_thrash_compass_iterators),
|
||||
TEST(test_prototype_line_algorithm),
|
||||
TEST(test_prototype_circle_algorithm),
|
||||
TEST(test_viewport_iterator),
|
||||
TEST(test_random_rectangle),
|
||||
TEST(test_standard_rectangle),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
265
tests/mazes.cpp
265
tests/mazes.cpp
|
|
@ -1,4 +1,4 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
#include <fuc2/testing.hpp>
|
||||
#include <fmt/core.h>
|
||||
#include <string>
|
||||
#include "algos/matrix.hpp"
|
||||
|
|
@ -11,150 +11,152 @@
|
|||
|
||||
using std::string;
|
||||
using matrix::Matrix;
|
||||
using namespace fuc2;
|
||||
|
||||
TEST_CASE("hunt-and-kill", "[mazes]") {
|
||||
Map map(21, 21);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.hunt_and_kill();
|
||||
REQUIRE(maze.repair() == true);
|
||||
|
||||
if(DUMP) maze.dump("BASIC MAZE");
|
||||
|
||||
maze.randomize_rooms(ROOM_SIZE);
|
||||
maze.hunt_and_kill();
|
||||
maze.place_doors();
|
||||
REQUIRE(maze.repair() == true);
|
||||
|
||||
if(DUMP) maze.dump("ROOM MAZE");
|
||||
|
||||
REQUIRE(map.$dead_ends.size() > 0);
|
||||
REQUIRE(map.$rooms.size() > 0);
|
||||
}
|
||||
|
||||
TEST_CASE("hunt-and-kill box", "[mazes]") {
|
||||
for(int i = 25; i < 65; i += 2) {
|
||||
Map map(i, i);
|
||||
namespace mazes_tests {
|
||||
void test_hunt_and_kill() {
|
||||
Map map(21, 21);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.hunt_and_kill();
|
||||
maze.clear();
|
||||
maze.inner_box(6, 4);
|
||||
CHECK(maze.repair() == true);
|
||||
|
||||
if(DUMP) maze.dump("BASIC MAZE");
|
||||
|
||||
maze.randomize_rooms(ROOM_SIZE);
|
||||
|
||||
maze.hunt_and_kill();
|
||||
maze.open_box(6);
|
||||
maze.place_doors();
|
||||
auto valid = maze.repair();
|
||||
|
||||
if(i == 41 && DUMP) {
|
||||
maze.dump(valid ? "INNER BOX" : "FAILED BOX");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("hunt-and-kill ring", "[mazes]") {
|
||||
Map map(21, 21);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.inner_donut(5.5, 3.5);
|
||||
maze.hunt_and_kill();
|
||||
REQUIRE(maze.repair() == true);
|
||||
|
||||
if(DUMP) maze.dump("INNER RING");
|
||||
|
||||
REQUIRE(maze.$rooms.size() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("hunt-and-kill fissure", "[mazes]") {
|
||||
Map map(21, 21);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.divide({3,3}, {19,18});
|
||||
maze.hunt_and_kill();
|
||||
REQUIRE(maze.repair() == true);
|
||||
|
||||
if(DUMP) maze.dump("FISSURE MAZE");
|
||||
|
||||
REQUIRE(maze.$rooms.size() == 0);
|
||||
}
|
||||
|
||||
TEST_CASE("hunt-and-kill no-dead-ends", "[mazes]") {
|
||||
Map map(21, 21);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.hunt_and_kill();
|
||||
maze.remove_dead_ends();
|
||||
REQUIRE(maze.repair() == true);
|
||||
|
||||
if(DUMP) maze.dump("NO DEAD ENDS");
|
||||
}
|
||||
|
||||
TEST_CASE("hunt-and-kill too much", "[mazes]") {
|
||||
for(int i = 25; i < 65; i += 2) {
|
||||
Map map(i, i);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.hunt_and_kill();
|
||||
maze.randomize_rooms(ROOM_SIZE);
|
||||
maze.clear();
|
||||
maze.inner_donut(9, 4);
|
||||
maze.divide({3,3}, {15,16});
|
||||
maze.hunt_and_kill();
|
||||
maze.place_doors();
|
||||
auto valid = maze.repair();
|
||||
CHECK(maze.repair() == true);
|
||||
|
||||
if(i == 41 && DUMP && valid) {
|
||||
maze.dump("COMBINED");
|
||||
}
|
||||
if(DUMP) maze.dump("ROOM MAZE");
|
||||
|
||||
CHECK(map.$dead_ends.size() > 0);
|
||||
CHECK(map.$rooms.size() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("hunt-and-kill validator", "[mazes]") {
|
||||
bool valid = true;
|
||||
Stats mofm;
|
||||
|
||||
for(int i = 0; i < 10; i++) {
|
||||
Stats door_prob;
|
||||
|
||||
do {
|
||||
Map map(33, 33);
|
||||
void test_hunt_and_kill_box() {
|
||||
for(int i = 25; i < 65; i += 2) {
|
||||
Map map(i, i);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.hunt_and_kill();
|
||||
maze.clear();
|
||||
maze.inner_box(6, 4);
|
||||
maze.randomize_rooms(ROOM_SIZE);
|
||||
|
||||
maze.hunt_and_kill();
|
||||
maze.open_box(6);
|
||||
maze.place_doors();
|
||||
valid = maze.repair();
|
||||
auto valid = maze.repair();
|
||||
|
||||
if(i == 9 && DUMP) {
|
||||
maze.dump(valid ? "VALIDATED" : "FAILED!");
|
||||
if(i == 41 && DUMP) {
|
||||
maze.dump(valid ? "INNER BOX" : "FAILED BOX");
|
||||
}
|
||||
door_prob.sample(valid);
|
||||
} while(!valid);
|
||||
|
||||
if(DUMP) door_prob.dump();
|
||||
mofm.sample(door_prob.mean());
|
||||
}
|
||||
}
|
||||
|
||||
if(DUMP) {
|
||||
fmt::println("FINAL m-of-m");
|
||||
mofm.dump();
|
||||
void test_hunt_and_kill_ring() {
|
||||
Map map(21, 21);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.inner_donut(5.5, 3.5);
|
||||
maze.hunt_and_kill();
|
||||
CHECK(maze.repair() == true);
|
||||
|
||||
if(DUMP) maze.dump("INNER RING");
|
||||
|
||||
CHECK(maze.$rooms.size() == 0);
|
||||
}
|
||||
|
||||
REQUIRE(mofm.mean() > 0.20);
|
||||
}
|
||||
void test_hunt_and_kill_fissure() {
|
||||
Map map(21, 21);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.divide({3,3}, {19,18});
|
||||
maze.hunt_and_kill();
|
||||
CHECK(maze.repair() == true);
|
||||
|
||||
if(DUMP) maze.dump("FISSURE MAZE");
|
||||
|
||||
CHECK(maze.$rooms.size() == 0);
|
||||
}
|
||||
|
||||
void test_hunt_and_kill_no_dead_ends() {
|
||||
Map map(21, 21);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.hunt_and_kill();
|
||||
maze.remove_dead_ends();
|
||||
CHECK(maze.repair() == true);
|
||||
|
||||
if(DUMP) maze.dump("NO DEAD ENDS");
|
||||
}
|
||||
|
||||
void test_hunt_and_kill_too_much() {
|
||||
for(int i = 25; i < 65; i += 2) {
|
||||
Map map(i, i);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.hunt_and_kill();
|
||||
maze.randomize_rooms(ROOM_SIZE);
|
||||
maze.clear();
|
||||
maze.inner_donut(9, 4);
|
||||
maze.divide({3,3}, {15,16});
|
||||
maze.hunt_and_kill();
|
||||
maze.place_doors();
|
||||
auto valid = maze.repair();
|
||||
|
||||
if(i == 41 && DUMP && valid) {
|
||||
maze.dump("COMBINED");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_hunt_and_kill_validator() {
|
||||
bool valid = true;
|
||||
Stats mofm;
|
||||
|
||||
for(int i = 0; i < 10; i++) {
|
||||
Stats door_prob;
|
||||
|
||||
do {
|
||||
Map map(33, 33);
|
||||
maze::Builder maze(map);
|
||||
|
||||
maze.hunt_and_kill();
|
||||
maze.clear();
|
||||
maze.inner_box(6, 4);
|
||||
maze.randomize_rooms(ROOM_SIZE);
|
||||
maze.hunt_and_kill();
|
||||
maze.open_box(6);
|
||||
maze.place_doors();
|
||||
valid = maze.repair();
|
||||
|
||||
if(i == 9 && DUMP) {
|
||||
maze.dump(valid ? "VALIDATED" : "FAILED!");
|
||||
}
|
||||
door_prob.sample(valid);
|
||||
} while(!valid);
|
||||
|
||||
if(DUMP) door_prob.dump();
|
||||
mofm.sample(door_prob.mean());
|
||||
}
|
||||
|
||||
if(DUMP) {
|
||||
fmt::println("FINAL m-of-m");
|
||||
mofm.dump();
|
||||
}
|
||||
|
||||
CHECK(mofm.mean() > 0.20);
|
||||
}
|
||||
|
||||
|
||||
TEST_CASE("hunt-and-kill scripting", "[mazes]") {
|
||||
using namespace nlohmann::literals;
|
||||
void test_hunt_and_kill_scripting() {
|
||||
using namespace nlohmann::literals;
|
||||
|
||||
// go up by 2 to keep odd
|
||||
for(int i = 0; i < 20; i+=2) {
|
||||
auto script = R"(
|
||||
// go up by 2 to keep odd
|
||||
for(int i = 0; i < 20; i+=2) {
|
||||
auto script = R"(
|
||||
[
|
||||
{"action": "hunt_and_kill"},
|
||||
{"action": "clear"},
|
||||
|
|
@ -169,14 +171,29 @@ TEST_CASE("hunt-and-kill scripting", "[mazes]") {
|
|||
]
|
||||
)"_json;
|
||||
|
||||
Map map(23+i, 23+i);
|
||||
auto [maze, valid] = maze::script(map, script);
|
||||
Map map(23+i, 23+i);
|
||||
auto [maze, valid] = maze::script(map, script);
|
||||
|
||||
if(valid) {
|
||||
REQUIRE(maze.validate() == true);
|
||||
REQUIRE(map.INVARIANT() == true);
|
||||
if(valid) {
|
||||
CHECK(maze.validate() == true);
|
||||
CHECK(map.INVARIANT() == true);
|
||||
}
|
||||
|
||||
if(DUMP) maze.dump(valid ? "SCRIPTED" : "SCRIPTED FAIL!");
|
||||
}
|
||||
|
||||
if(DUMP) maze.dump(valid ? "SCRIPTED" : "SCRIPTED FAIL!");
|
||||
}
|
||||
|
||||
fuc2::Set TESTS{
|
||||
.name="mazes",
|
||||
.tests={
|
||||
TEST(test_hunt_and_kill_scripting),
|
||||
TEST(test_hunt_and_kill_validator),
|
||||
TEST(test_hunt_and_kill_too_much),
|
||||
TEST(test_hunt_and_kill_no_dead_ends),
|
||||
TEST(test_hunt_and_kill_fissure),
|
||||
TEST(test_hunt_and_kill_ring),
|
||||
TEST(test_hunt_and_kill_box),
|
||||
TEST(test_hunt_and_kill),
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,4 @@
|
|||
tests = files(
|
||||
'event_router.cpp',
|
||||
'fsm.cpp',
|
||||
'inventory.cpp',
|
||||
'lighting.cpp',
|
||||
'loot.cpp',
|
||||
'map.cpp',
|
||||
'matrix.cpp',
|
||||
'mazes.cpp',
|
||||
'palette.cpp',
|
||||
'pathing.cpp',
|
||||
'rituals.cpp',
|
||||
|
|
@ -19,6 +11,14 @@ tests = files(
|
|||
)
|
||||
|
||||
fuc2_tests = files(
|
||||
'mazes.cpp',
|
||||
'matrix.cpp',
|
||||
'map.cpp',
|
||||
'loot.cpp',
|
||||
'lighting.cpp',
|
||||
'inventory.cpp',
|
||||
'fsm.cpp',
|
||||
'event_router.cpp',
|
||||
'dinkyecs.cpp',
|
||||
'dbc.cpp',
|
||||
'ai.cpp',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue