/* Self-referencing function that explores the maze recursively returning 1/0 on success/failure */ int explore(int x, int y, max_maze array, maze_dimensions dims){ // Bounds check (avoid seg fault) if (x >= dims.width || y >= dims.height || y < 0 || x < 0){ return 0; } // Base case: cell is THE exit if ( onEdge(x,y,dims) && array[y][x] == ' '){ array[y][x]='.'; return 1; } // Base case: cell is wall OR the cell we just came from if (array[y][x] == '#' || array[y][x] == '.'){ return 0; } // Cell is neither exit nor wall. Drop a breadcrumb and keep going. array[y][x] = '.'; // Try going EAST-WEST-NORTH-SOUTH... if (explore(x+1, y, array, dims)) {return 1;} if (explore(x-1, y, array, dims)) {return 1;} if (explore(x, y-1, array, dims)) {return 1;} if (explore(x, y+1, array, dims)) {return 1;} // Dead ends all around us, pick up the breadcrumb and return 0 array[y][x] = ' '; return 0; }
/** * Principal function. It creates Nodes and Edges to put in the Graph, * from the given BBHG * @param bhg source BBHG */ void BBHGDrawer::make() { if(_made) { return; } ASSERT(_bhg); ASSERT(_graph); // Construct the Graph HashTable<void*, display::Node*> map; for(BBHG::Iterator bb(_bhg); bb; bb++) { display::Node *node = _graph->newNode(); map.put(*bb, node); onNode(*bb, node); } for(BBHG::Iterator bb(_bhg); bb; bb++) { display::Node *node = map.get(*bb); for(BBHG::OutIterator succ(bb); succ; succ++) { BBHGEdge* edge = succ; display::Edge *display_edge; display_edge = _graph->newEdge(node,map.get(edge->target())); onEdge(edge, display_edge); } } onEnd(_graph); _made = true; }
inline bool within(const Point & point, const Poly & poly, const Mapping & mapping, const S & ieps) { auto i = std::lower_bound(mapping.begin(), mapping.end(), point.y, detail::CmpY<decltype(*mapping.begin())>()); if(i == mapping.begin()) { if(ieps < 0 || point.y < i->y - ieps) return false; return onEdge(point, poly, i->edges, ieps); } if(i == mapping.end()) { if(ieps < 0) return false; --i; if(point.y > i->y + ieps) return false; if(!i->edges.empty() && onEdge(point, poly, i->edges, ieps)) return true; --i; return onEdge(point, poly, i->edges, ieps); } S eps = std::abs(ieps); if(i->y - point.y < eps) { if(onEdge(point, poly, i->edges, eps)) return ieps > 0; } --i; if(onEdge(point, poly, i->edges, eps)) return ieps > 0; bool result = false; for(auto j = i->edges.begin(), jend = i->edges.end(); j != jend; ++j) { auto & p1 = poly[*j]; auto & p2 = *j == 0 ? poly.back() : poly[*j - 1]; auto d = p2.y - p1.y; if(std::abs(d) > eps) { auto t = (point.y - p1.y) / d; if(point.x + eps > p1.x + (p2.x - p1.x) * t) result = !result; } } return result; }
inline bool onEdge(const Point & point, const Poly & poly, const Edges & edges, const S & eps) { for(auto j = edges.begin(), jend = edges.end(); j != jend; ++j) { auto & p1 = poly[*j]; auto & p2 = *j == 0 ? poly.back() : poly[*j - 1]; if(onEdge(point, p1, p2, eps)) return true; } return false; }
/* Random maze generation. */ void random_maze(max_maze array, maze_dimensions dims){ // Need initial set of dummy dimensions to pass to divide func: maze_dimensions c_dims; // Border the maze with a wall before beginning for (int i = 0; i < dims.width; ++i){ for (int j = 0; j < dims.height; ++j){ if(onEdge( j, i, dims)){ array[i][j] = '#'; } } } // Divide the remaining chamber in four if( chamber_divide(array, dims, c_dims, 1, 1) ){ printf("Generation finished\n"); } }
/* Return coords of opening in maze nearest to 0,0 */ maze_entrance findEntrance(max_maze array, maze_dimensions dims){ int dist, ent_candidate, i, j; maze_entrance ent; ent.x = OUT_OF_BOUNDS; // Initialise to some impossible coord ent.y = OUT_OF_BOUNDS; ent_candidate = dims.width + dims.height; // Furthest point (worst case) for (i = 0; i < dims.height; ++i){ for (j = 0; j < dims.width; ++j){ // if cell is on edge, and empty: if( onEdge( j, i, dims) && array[i][j] == ' '){ dist = i + j; // Sum of coords used as metric for distance to origin if (dist < ent_candidate){ ent_candidate = dist; ent.y = i; ent.x = j; } } } } // If the coords haven't been found if (ent.x == OUT_OF_BOUNDS || ent.y == OUT_OF_BOUNDS) { printf("No entrance found!\n"); display_Terminal(array, dims); exit(1); } else { array[ent.y][ent.x] = 'E'; // Mark with an E to distinguish from the exit/goal } return ent; }
Edge *Subdivision::spoke(Vec2& x, Edge *e) { Triangle *new_faces[4]; int facedex = 0; // // NOTE: e is the edge returned by locate(x) // if ( (x == e->Org()) || (x == e->Dest()) ) { // point is already in the mesh // #ifdef _INC_IOSTREAM std::cerr << "WARNING: Tried to reinsert point: " << x << std::endl; std::cerr << " org: " << e->Org() << std::endl; std::cerr << " dest: " << e->Dest() << std::endl; #endif return NULL; } Edge *boundary_edge = NULL; Triangle *lface = e->Lface(); lface->dontAnchor(e); new_faces[facedex++] = lface; if( onEdge(x,e) ) { if( ccwBoundary(e) ) { // // e lies on the boundary // Defer deletion until after new edges are added. boundary_edge = e; } else { Triangle *sym_lface = e->Sym()->Lface(); new_faces[facedex++] = sym_lface; sym_lface->dontAnchor(e->Sym()); e = e->Oprev(); deleteEdge(e->Onext()); } } else { // x lies within the Lface of e } Edge *base = makeEdge(e->Org(), x.clone()); splice(base, e); startingEdge = base; do { base = connect(e, base->Sym()); e = base->Oprev(); } while( e->Lnext() != startingEdge ); if( boundary_edge ) deleteEdge(boundary_edge); // Update all the faces in our new spoked polygon. // If point x on perimeter, then don't add an exterior face base = boundary_edge ? startingEdge->Rprev() : startingEdge->Sym(); do { if( facedex ) new_faces[--facedex]->reshape(base); else makeFace(base); base = base->Onext(); } while( base != startingEdge->Sym() ); return startingEdge; }