More cleanups of the tests and fixes to the room and door positioning.

This commit is contained in:
Zed A. Shaw 2026-03-15 22:53:00 -04:00
parent 8e2a691337
commit 02d23bb77d
11 changed files with 75 additions and 78 deletions

View file

@ -1,6 +1,6 @@
ROOT_DIR := $(dir $(realpath $(lastword $(MAKEFILE_LIST))))
all: build test
all: build
reset:
ifeq '$(OS)' 'Windows_NT'
@ -37,7 +37,7 @@ tracy_build:
meson compile -j 10 -C builddir
test: build
./builddir/runtests -d yes "[map-fail]"
./builddir/runtests -d yes
run: build test
ifeq '$(OS)' 'Windows_NT'
@ -60,7 +60,7 @@ clean:
meson compile --clean -C builddir
debug_test: build
gdb --nx -x .gdbinit --ex run --ex bt --ex q --args builddir/runtests "[map-fail]"
gdb --nx -x .gdbinit --ex run --ex bt --ex q --args builddir/runtests
win_installer:
powershell 'start "C:\Program Files (x86)\solicus\InstallForge\bin\ifbuilderenvx86.exe" scripts\win_installer.ifp'

View file

@ -9,16 +9,6 @@ using std::string;
using matrix::Matrix;
namespace maze {
inline size_t rand(size_t i, size_t j) {
if(i < j) {
return Random::uniform(i, j);
} else if(j < i) {
return Random::uniform(j, i);
} else {
return i;
}
}
inline bool complete(Matrix& maze, size_t width, size_t height) {
for(size_t row = 1; row < height; row += 2) {
for(size_t col = 1; col < width; col += 2) {
@ -89,8 +79,9 @@ namespace maze {
}
bool Builder::room_should_exist(Room& room, bool allow_dupes) {
if(!matrix::inbounds($walls, room.x, room.y) ||
!matrix::inbounds($walls, room.x + room.width, room.y + room.height))
// padding by 1 for the perimeter wall
if(!matrix::inbounds($walls, room.x - 1, room.y - 1) ||
!matrix::inbounds($walls, room.x + room.width + 2, room.y + room.height + 2))
{
return false;
}
@ -187,7 +178,7 @@ namespace maze {
$walls[row][col] = 0;
} else {
// found neighbors, pick random one
auto nb = n[rand(size_t(0), n.size() - 1)];
auto nb = n[Random::abs(size_t(0), n.size() - 1)];
$walls[nb.y][nb.x] = 0;
size_t row = (nb.y + on.y) / 2;
@ -196,12 +187,14 @@ namespace maze {
on = nb;
}
}
if($rooms.size() > 0) place_rooms();
}
void Builder::place_rooms() {
for(auto& room : $rooms) {
for(matrix::rectangle it{$walls, room.x, room.y, room.width, room.height}; it.next();) {
$walls[it.y][it.x] = 0;
$walls[it.y][it.x] = SPACE_VALUE;
}
}
}
@ -239,7 +232,7 @@ namespace maze {
}
void Builder::dump(const std::string& msg, bool path_too) {
auto wall_copy = $walls;
Matrix wall_copy = $walls;
// mark the rooms too, but not if pathing
if(!path_too) {
@ -307,6 +300,11 @@ namespace maze {
}
}
bool Builder::valid_door(size_t x, size_t y) {
return (space_available(x, y - 1) && space_available(x, y + 1)) // north south
|| (space_available(x - 1, y) && space_available(x + 1, y));
}
void Builder::place_doors() {
for(auto room : $rooms) {
int best_longest = 0;
@ -319,17 +317,14 @@ namespace maze {
// can't path out of the room, so now punch a hole until it can
matrix::perimeter it{room.x - 1, room.y - 1, room.width + 2, room.height + 2};
while(it.next()) {
// don't use corners
if((it.x == room.x - 1 && it.y == room.y - 1) ||
(it.x == room.x - 1 && it.y == room.y + 2) ||
(it.x == room.width + 2 && it.y == room.y + 2) ||
(it.x == room.width + 2 && it.y == room.y - 1)) {
continue;
}
while(it.next()) {
if($walls[it.y][it.x] == WALL_VALUE) {
// valid doors are free north/south or east/west
if(!valid_door(it.x, it.y)) continue;
$walls[it.y][it.x] = SPACE_VALUE;
longest = compute_paths(room.x, room.y);
// keep track of the best door so far, which is the one with the longest path
@ -348,8 +343,6 @@ namespace maze {
$walls[best_door.y][best_door.x] = SPACE_VALUE;
$doors.insert_or_assign(best_door, true);
}
fmt::println("map valid after doors? {}", validate());
}
void Builder::inner_box(size_t outer_size, size_t inner_size) {
@ -408,7 +401,7 @@ namespace maze {
// initial path test can just use one room then look for
// any cells that are empty in the walls map but unpathed in the paths
Room test_room = $rooms.at(rand(0, $rooms.size() - 1));
Room test_room = $rooms.at(Random::abs(size_t(0), $rooms.size() - 1));
compute_paths(test_room.x, test_room.y);
for(matrix::each_cell it{$walls}; it.next();) {
@ -422,10 +415,10 @@ namespace maze {
}
bool Builder::space_available(size_t x, size_t y) {
bool in_bounds = matrix::inbounds($walls, x, y);
bool is_space = $walls[y][x] == SPACE_VALUE;
bool not_perimeter = x > 0 && y > 0 && x < $width - 2 && y < $height - 2;
return in_bounds && is_space && not_perimeter;
return (matrix::inbounds($walls, x, y) && // in bounds
$walls[y][x] == SPACE_VALUE && // is a space
!$doors.contains({x, y}) && // no door there
(x > 0 && y > 0 && x < $width - 2 && y < $height - 2)); // not perimeter;
}
void Builder::punch_dead_end(size_t at_x, size_t at_y, size_t x, size_t y) {

View file

@ -47,6 +47,7 @@ namespace maze {
void punch_dead_end(size_t at_x, size_t at_y, size_t x, size_t y);
bool space_available(size_t x, size_t y);
int compute_paths(size_t x, size_t y);
bool valid_door(size_t x, size_t y);
};
std::pair<Builder, bool> script(Map& map, nlohmann::json& config);

View file

@ -9,5 +9,4 @@ namespace Random {
int tick = Random::uniform_real(float(from), float(to));
return std::chrono::milliseconds{tick};
}
}

View file

@ -27,5 +27,15 @@ namespace Random {
return rand(GENERATOR);
}
auto abs(auto i, auto j) {
if(i < j) {
return Random::uniform(i, j);
} else if(j < i) {
return Random::uniform(j, i);
} else {
return i;
}
}
std::chrono::milliseconds milliseconds(int from, int to);
}

View file

@ -30,11 +30,6 @@ namespace combat {
for(auto& [entity, enemy] : $combatants) {
if(enemy.combat->ap < enemy.combat->max_ap) {
int new_ap = std::min(enemy.combat->max_ap, enemy.combat->ap_delta + enemy.combat->ap);
// only add up to the max
fmt::println("enemy {} get more ap {}->{}",
entity, enemy.combat->ap, new_ap);
enemy.combat->ap = new_ap;
}
}

View file

@ -3,39 +3,39 @@
#include <string>
#include <array>
constexpr const int INV_SLOTS=16;
constexpr const int TEXTURE_WIDTH=256;
constexpr const int TEXTURE_HEIGHT=256;
constexpr const int RAY_VIEW_WIDTH=900;
constexpr const int RAY_VIEW_HEIGHT=600;
constexpr const int SCREEN_WIDTH=1280;
constexpr const int SCREEN_HEIGHT=720;
constexpr const int RAY_VIEW_X=(SCREEN_WIDTH - RAY_VIEW_WIDTH);
constexpr const int RAY_VIEW_Y=0;
constexpr const int GLOW_LIMIT=220;
constexpr const int LIGHT_MULTIPLIER=2.5;
constexpr const float AIMED_AT_BRIGHTNESS=0.2f;
constexpr const int MAP_TILE_DIM=64;
constexpr const int ICONGEN_MAP_TILE_DIM=64;
constexpr const int PLAYER_SPRITE_DIR_CORRECTION=270;
constexpr const int RENDER_DISTANCE=500;
constexpr const int ROOM_SIZE=3;
constexpr int INV_SLOTS=16;
constexpr int TEXTURE_WIDTH=256;
constexpr int TEXTURE_HEIGHT=256;
constexpr int RAY_VIEW_WIDTH=900;
constexpr int RAY_VIEW_HEIGHT=600;
constexpr int SCREEN_WIDTH=1280;
constexpr int SCREEN_HEIGHT=720;
constexpr int RAY_VIEW_X=(SCREEN_WIDTH - RAY_VIEW_WIDTH);
constexpr int RAY_VIEW_Y=0;
constexpr int GLOW_LIMIT=220;
constexpr int LIGHT_MULTIPLIER=2.5;
constexpr float AIMED_AT_BRIGHTNESS=0.2f;
constexpr int MAP_TILE_DIM=64;
constexpr int ICONGEN_MAP_TILE_DIM=64;
constexpr int PLAYER_SPRITE_DIR_CORRECTION=270;
constexpr int RENDER_DISTANCE=500;
constexpr int ROOM_SIZE=3;
constexpr const int BOSS_VIEW_WIDTH=1080;
constexpr const int BOSS_VIEW_HEIGHT=SCREEN_HEIGHT;
constexpr const int BOSS_VIEW_X=SCREEN_WIDTH - BOSS_VIEW_WIDTH;
constexpr const int BOSS_VIEW_Y=0;
constexpr int BOSS_VIEW_WIDTH=1080;
constexpr int BOSS_VIEW_HEIGHT=SCREEN_HEIGHT;
constexpr int BOSS_VIEW_X=SCREEN_WIDTH - BOSS_VIEW_WIDTH;
constexpr int BOSS_VIEW_Y=0;
constexpr const bool VSYNC=false;
constexpr const int FRAME_LIMIT=60;
constexpr const int NUM_SPRITES=1;
constexpr const int MAX_LOG_MESSAGES=17;
constexpr bool VSYNC=true;
constexpr int FRAME_LIMIT=60;
constexpr int NUM_SPRITES=1;
constexpr int MAX_LOG_MESSAGES=17;
#ifdef NDEBUG
constexpr const bool DEBUG_BUILD=false;
constexpr bool DEBUG_BUILD=false;
#else
constexpr const bool DEBUG_BUILD=true;
constexpr bool DEBUG_BUILD=true;
#endif

View file

@ -152,11 +152,11 @@ namespace gui {
try_move(1, true);
break;
case ROTATE_LEFT:
$main_ui.plan_rotate(-1, 0.25f);
$main_ui.plan_rotate(-1, DEFAULT_ROTATE);
state(State::ROTATING);
break;
case ROTATE_RIGHT:
$main_ui.plan_rotate(1, 0.25f);
$main_ui.plan_rotate(1, DEFAULT_ROTATE);
state(State::ROTATING);
break;
case MAP_OPEN:

View file

@ -65,18 +65,17 @@ TEST_CASE("battle operations fantasy", "[combat-battle]") {
while(auto act = battle.next()) {
auto& [enemy, wants_to, cost, enemy_state] = *act;
fmt::println(">>>>> entity: {} wants to {} cost={}; has {} HP; {} ap",
enemy.entity, wants_to,
cost, enemy.combat->hp,
enemy.combat->ap);
// fmt::println(">>>>> entity: {} wants to {} cost={}; has {} HP; {} ap",
// enemy.entity, wants_to,
// cost, enemy.combat->hp,
// enemy.combat->ap);
switch(enemy_state) {
case BattleHostState::agree:
fmt::println("HOST and PLAYER requests match {}, doing it.",
wants_to);
// fmt::println("HOST and PLAYER requests match {}, doing it.", wants_to);
break;
case BattleHostState::disagree:
fmt::println("REBELIOUS ACT: {}", wants_to);
// fmt::println("REBELIOUS ACT: {}", wants_to);
battle.clear_requests();
REQUIRE(battle.$player_requests.size() == 0);
break;
@ -86,7 +85,7 @@ TEST_CASE("battle operations fantasy", "[combat-battle]") {
}
break;
case BattleHostState::out_of_ap:
fmt::println("ENEMY OUT OF AP");
// fmt::println("ENEMY OUT OF AP");
break;
}
}

View file

@ -25,7 +25,7 @@ TEST_CASE("camera control", "[map]") {
Point center = map.center_camera({10,10}, 5, 5);
map.dump(center.x, center.y);
// map.dump(center.x, center.y);
REQUIRE(center.x == 8);
REQUIRE(center.y == 8);

View file

@ -7,7 +7,7 @@
#include "algos/maze.hpp"
#include "algos/stats.hpp"
#define DUMP 1
#define DUMP 0
using std::string;
using matrix::Matrix;