Working line iterator, and mostly working flood iterator that should be good enough for world gen.
This commit is contained in:
		
							parent
							
								
									1295e9631d
								
							
						
					
					
						commit
						d4b6c35120
					
				
					 5 changed files with 91 additions and 39 deletions
				
			
		|  | @ -20,7 +20,7 @@ namespace lighting { | |||
| 
 | ||||
|     const int wall_light = source.strength + WALL_LIGHT_LEVEL; | ||||
|     for(auto point : has_light) { | ||||
|       for(matrix::in_box it{$lightmap, point.x, point.y, 1}; it.next();) { | ||||
|       for(matrix::compass it{$lightmap, point.x, point.y}; it.next();) { | ||||
|         if($paths.$paths[it.y][it.x] == WALL_PATH_LIMIT) { | ||||
|             $lightmap[it.y][it.x] = light_level(wall_light, point.x, point.y); | ||||
|         } | ||||
|  |  | |||
							
								
								
									
										41
									
								
								matrix.cpp
									
										
									
									
									
								
							
							
						
						
									
										41
									
								
								matrix.cpp
									
										
									
									
									
								
							|  | @ -2,6 +2,8 @@ | |||
| #include "constants.hpp" | ||||
| #include "dbc.hpp" | ||||
| #include <fmt/core.h> | ||||
| #include <cmath> | ||||
| #include <cstdlib> | ||||
| 
 | ||||
| using namespace fmt; | ||||
| using std::min, std::max; | ||||
|  | @ -114,7 +116,7 @@ namespace matrix { | |||
| 
 | ||||
|   flood::flood(Matrix &mat, Point start, int old_val, int new_val) : | ||||
|     mat(mat), start(start), old_val(old_val), new_val(new_val), | ||||
|     dirs{mat, start.x, start.y} | ||||
|      x(start.x), y(start.y), dirs{mat, start.x, start.y} | ||||
|   { | ||||
|     dbc::check(old_val != new_val, "what you doing?"); | ||||
|     current_loc = start; | ||||
|  | @ -133,8 +135,8 @@ namespace matrix { | |||
|       } | ||||
| 
 | ||||
|       // get the next thing
 | ||||
|       if(mat[dirs.y][dirs.x] == old_val) { | ||||
|         mat[dirs.y][dirs.x] += new_val; | ||||
|       if(mat[dirs.y][dirs.x] <= old_val) { | ||||
|         mat[dirs.y][dirs.x] = new_val; | ||||
|         x = dirs.x; | ||||
|         y = dirs.y; | ||||
| 
 | ||||
|  | @ -147,20 +149,30 @@ namespace matrix { | |||
|     } | ||||
|   } | ||||
| 
 | ||||
|   bool flood::next_working() { | ||||
|     if(!q.empty()) { | ||||
|       auto current_loc = q.front(); | ||||
|       q.pop(); | ||||
|   line::line(Point start, Point end) : | ||||
|       x(start.x), y(start.y), | ||||
|       x1(end.x), y1(end.y) | ||||
|   { | ||||
|     dx = std::abs(x1 - x); | ||||
|     sx = x < x1 ? 1 : -1; | ||||
|     dy = std::abs(y1 - y) * -1; | ||||
|     sy = y < y1 ? 1 : -1; | ||||
|     error = dx + dy; | ||||
|   } | ||||
| 
 | ||||
|       for(matrix::in_box box{mat, current_loc.x, current_loc.y, 1}; | ||||
|           box.next();) | ||||
|       { | ||||
|         if(mat[box.y][box.x] == old_val) { | ||||
|           mat[box.y][box.x] += new_val; | ||||
|           q.push({.x=box.x, .y=box.y}); | ||||
|         } | ||||
|   bool line::next() { | ||||
|     if(x != x1 || y != y1) { | ||||
|       int e2 = 2 * error; | ||||
| 
 | ||||
|       if(e2 >= dy) { | ||||
|         error = error + dy; | ||||
|         x = x + sx; | ||||
|       } | ||||
| 
 | ||||
|       if(e2 <= dx) { | ||||
|         error = error + dx; | ||||
|         y = y + sy; | ||||
|       } | ||||
|       return true; | ||||
|     } else { | ||||
|       return false; | ||||
|  | @ -186,5 +198,4 @@ namespace matrix { | |||
|       if(it.row) print("\n"); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
							
								
								
									
										14
									
								
								matrix.hpp
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								matrix.hpp
									
										
									
									
									
								
							|  | @ -94,4 +94,18 @@ namespace matrix { | |||
|     bool next_working(); | ||||
|   }; | ||||
| 
 | ||||
|   struct line { | ||||
|     int x; | ||||
|     int y; | ||||
|     int x1; | ||||
|     int y1; | ||||
|     int sx; | ||||
|     int sy; | ||||
|     int dx; | ||||
|     int dy; | ||||
|     int error; | ||||
| 
 | ||||
|     line(Point start, Point end); | ||||
|     bool next(); | ||||
|   }; | ||||
| } | ||||
|  |  | |||
|  | @ -35,7 +35,10 @@ TEST_CASE("lighting a map works", "[lighting]") { | |||
|     lr.clear_light_target(light1); | ||||
|     lr.clear_light_target(light2); | ||||
| 
 | ||||
|     const auto &lighting = lr.lighting(); | ||||
|     Matrix &lighting = lr.lighting(); | ||||
| 
 | ||||
|     matrix::dump("WALLS=====", map.walls()); | ||||
|     matrix::dump("LIGHT PATHS======", lr.$paths.$paths); | ||||
| 
 | ||||
|     // confirm light is set at least at and around the two points
 | ||||
|     REQUIRE(lighting[light1.y][light1.x] == lighting::LEVELS[source1.strength]); | ||||
|  |  | |||
|  | @ -163,7 +163,7 @@ TEST_CASE("thrash compass iterators", "[matrix:compass]") { | |||
| } | ||||
| 
 | ||||
| TEST_CASE("prototype flood algorithm", "[matrix:flood]") { | ||||
|   for(int count = 0; count < 1; count++) { | ||||
|   for(int count = 0; count < 1000; count++) { | ||||
|     size_t width = Random::uniform<size_t>(10, 25); | ||||
|     size_t height = Random::uniform<size_t>(10, 33); | ||||
| 
 | ||||
|  | @ -171,32 +171,56 @@ TEST_CASE("prototype flood algorithm", "[matrix:flood]") { | |||
|     WorldBuilder builder(map); | ||||
|     builder.generate(); | ||||
| 
 | ||||
|     REQUIRE(map.room_count() > 0); | ||||
|     if(map.room_count() < 2) continue; | ||||
| 
 | ||||
|     Point start = map.place_entity(map.room_count() / 2); | ||||
|     map.set_target(start); | ||||
|     map.make_paths(); | ||||
|     Matrix result = map.paths(); | ||||
| 
 | ||||
|     // BUG: place_entity should not put things in walls
 | ||||
|     map.$walls[start.y][start.x] = 0; | ||||
|     // matrix::dump("WALLS BEFORE FLOOD", result, start.x, start.y);
 | ||||
| 
 | ||||
|     matrix::dump("WALLS BEFORE FLOOD", map.walls(), start.x, start.y); | ||||
| 
 | ||||
|     /*
 | ||||
|     for(matrix::flood it{map.$walls, start, 0, 10}; it.next_working(); tick++) { | ||||
|       println("TEST WORKING"); | ||||
|     } | ||||
|     */ | ||||
| 
 | ||||
|     for(matrix::flood it{map.$walls, start, 0, 15}; it.next();) { | ||||
|       REQUIRE(matrix::inbounds(map.$walls, it.x, it.y)); | ||||
|       map.$walls[it.y][it.x] = 15; | ||||
|     for(matrix::flood it{result, start, 3, 15}; it.next();) { | ||||
|       REQUIRE(matrix::inbounds(result, it.x, it.y)); | ||||
|       result[it.y][it.x] = 15; | ||||
|     } | ||||
| 
 | ||||
|     matrix::dump("WALLS AFTER FLOOD", map.walls(), start.x, start.y); | ||||
| 
 | ||||
|     // confirm that everything is 1 or 2 which confirms
 | ||||
|     // every cell possible is visited and nothing is visited twice
 | ||||
|     for(matrix::each_cell it{map.$walls}; it.next();) { | ||||
|       REQUIRE(map.$walls[it.y][it.x] <= 15); | ||||
|     } | ||||
|     // matrix::dump("WALLS AFTER FLOOD", result, start.x, start.y);
 | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| TEST_CASE("prototype line algorithm", "[matrix:line]") { | ||||
|   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}; | ||||
| 
 | ||||
|   for(matrix::in_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::line it{start, end}; it.next();) | ||||
|     { | ||||
|       REQUIRE(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; | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     REQUIRE(f_found); | ||||
|   } | ||||
| } | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Zed A. Shaw
						Zed A. Shaw