From 857cd2f91040573ff52a20aea9319c425c8b65ee Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Wed, 25 Dec 2024 01:15:33 -0500 Subject: [PATCH] Circle iterator now compensates for the matrix size and won't overflow. --- lights.cpp | 10 +++------- matrix.cpp | 15 +++++++++------ matrix.hpp | 4 +++- tests/matrix.cpp | 13 ++++++++----- worldbuilder.cpp | 6 ++---- 5 files changed, 25 insertions(+), 23 deletions(-) diff --git a/lights.cpp b/lights.cpp index 6b86c62..d3c70b3 100644 --- a/lights.cpp +++ b/lights.cpp @@ -7,14 +7,10 @@ using std::vector; namespace lighting { void LightRender::render_circle_light(LightSource source, Point at, PointList &has_light) { - for(matrix::circle it{at, source.distance + 1}; it.next();) { + for(matrix::circle it{$lightmap, at, source.distance + 1}; it.next();) { for(int x = it.left; x < it.right; x++) { - if(matrix::inbounds($paths.$paths, x, it.y) && - $paths.$paths[it.y][x] != WALL_PATH_LIMIT) - { - $lightmap[it.y][x] = light_level(source.strength, x, it.y); - has_light.push_back({(size_t)x, (size_t)it.y}); - } + $lightmap[it.y][x] = light_level(source.strength, x, it.y); + has_light.push_back({(size_t)x, (size_t)it.y}); } } } diff --git a/matrix.cpp b/matrix.cpp index 0a4e6d6..edc4681 100644 --- a/matrix.cpp +++ b/matrix.cpp @@ -180,21 +180,24 @@ namespace matrix { } - circle::circle(Point center, int radius) : + circle::circle(Matrix &mat, Point center, int radius) : center(center), radius(radius) { - top = max(center.y - radius, size_t(0)); - bottom = center.y + radius; + width = matrix::width(mat); + height = matrix::height(mat); + top = max(int(center.y - radius), 0); + bottom = min(int(center.y + radius), height); + y = top; } bool circle::next() { y++; - if(y <= bottom) { + if(y < bottom) { dy = y - center.y; dx = floor(sqrt(radius * radius - dy * dy)); - left = center.x - dx; - right = center.x + dx; + left = max(0, int(center.x - dx)); + right = min(width, int(center.x + dx)); return true; } else { return false; diff --git a/matrix.hpp b/matrix.hpp index b1715bf..710a1ef 100644 --- a/matrix.hpp +++ b/matrix.hpp @@ -127,8 +127,10 @@ namespace matrix { int right = 0; int top = 0; int bottom = 0; + int width = 0; + int height = 0; - circle(Point center, int radius); + circle(Matrix &mat, Point center, int radius); void update(); bool next(); }; diff --git a/tests/matrix.cpp b/tests/matrix.cpp index 1e2421b..5ff10ff 100644 --- a/tests/matrix.cpp +++ b/tests/matrix.cpp @@ -226,7 +226,7 @@ TEST_CASE("prototype line algorithm", "[matrix:line]") { } TEST_CASE("prototype circle algorithm", "[matrix:circle]") { - for(int count = 0; count < 20; count++) { + for(int count = 0; count < 2000; count++) { size_t width = Random::uniform(10, 13); size_t height = Random::uniform(10, 15); int pos_mod = Random::uniform(-3,3); @@ -238,12 +238,15 @@ TEST_CASE("prototype circle algorithm", "[matrix:circle]") { // use an empty map Matrix result = map.walls(); - for(matrix::circle it{start, radius}; it.next();) { + 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); - if(matrix::inbounds(result, x, it.y)) { - result[it.y][x] += 1; - } + // 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; } } diff --git a/worldbuilder.cpp b/worldbuilder.cpp index 6c0d666..25bef4b 100644 --- a/worldbuilder.cpp +++ b/worldbuilder.cpp @@ -142,11 +142,9 @@ void WorldBuilder::generate() { $map.load_tiles(); Point center = $map.place_entity(1); - for(matrix::circle it{center, 3}; it.next();) { + for(matrix::circle it{$map.$walls, center, 3}; it.next();) { for(int x = it.left; x < it.right; x++) { - if($map.inmap(x, it.y) && !$map.iswall(x, it.y)) { - $map.$tiles.set_tile(x, it.y, "WATER_TILE"); - } + $map.$tiles.set_tile(x, it.y, "WATER_TILE"); } } }