termaze

maze generation and pathfinding visualizer
git clone git://git.yotsev.xyz/termaze.git
Log | Files | Refs | README | LICENSE

commit 7f726056c97d57832700bab60ec2fa5e066fb348
parent 0ea9faa789276b5134c3e6fed00aa093a7ab3d0c
Author: Petar Yotsev <petar@yotsev.xyz>
Date:   Wed, 23 Sep 2020 14:06:55 +0100

Add missed changes and binary tree algorithm

Diffstat:
MMakefile | 42+++++++++++++++++-------------------------
MREADME.md | 2+-
Mmain.cpp | 37+++++++++++++++++--------------------
Mmaze_gen.cpp | 190++++++++++++++++++++++++++++++++++++++++++++++---------------------------------
Mmaze_gen.hpp | 1+
Mpathfinding.cpp | 60++++++++++++++++++++++++++++++------------------------------
Mstate.cpp | 2+-
Mstate.hpp | 42++++++++++++++----------------------------
Mtimer.cpp | 8++++----
Mui.cpp | 88++++++++++++++++++++++++++++++++++++++++----------------------------------------
10 files changed, 239 insertions(+), 233 deletions(-)

diff --git a/Makefile b/Makefile @@ -1,41 +1,33 @@ -# WITH FLAGS CC = g++ -CC_FLAGS = -lpanel -lncurses -std=c++11 -pthread -O2 +CC_FLAGS = -g -O3 -lpanel -lncurses -std=c++11 -pthread EXEC = termaze +OBJECTS = main.o maze_gen.o pathfinding.o ui.o timer.o state.o -$(EXEC): main.o ui.o maze_gen.o pathfinding.o - $(CC) $(CC_FLAGS) main.o maze_gen.o pathfinding.o ui.o timer.o -o $(EXEC) +$(EXEC): $(OBJECTS) + $(CC) $(CC_FLAGS) $(OBJECTS) -o $(EXEC) -main.o: main.cpp maze_gen.o pathfinding.o ui.o timer.o state.hpp vec2.hpp colors.hpp - $(CC) -c $(CC_FLAGS) maze_gen.o pathfinding.o ui.o main.cpp +main.o: maze_gen.o pathfinding.o ui.o timer.o \ + state.o vec2.hpp colors.hpp main.cpp + $(CC) -c $(CC_FLAGS) main.cpp -ui.o: ui.cpp maze_gen.o pathfinding.o state.hpp colors.hpp - $(CC) -c $(CC_FLAGS) maze_gen.o pathfinding.o ui.cpp +ui.o: maze_gen.o pathfinding.o state.o colors.hpp ui.?pp + $(CC) -c $(CC_FLAGS) ui.cpp -maze_gen.o: maze_gen.cpp vec2.hpp timer.o state.hpp colors.hpp +maze_gen.o: timer.o vec2.hpp state.o colors.hpp maze_gen.?pp $(CC) -c $(CC_FLAGS) maze_gen.cpp -pathfinding.o: pathfinding.cpp timer.o vec2.hpp state.hpp colors.hpp +pathfinding.o: timer.o vec2.hpp state.o colors.hpp pathfinding.?pp $(CC) -c $(CC_FLAGS) pathfinding.cpp -timer.o: timer.cpp state.hpp - $(CC) -c timer.cpp +timer.o: state.hpp timer.?pp + $(CC) -c $(CC_FLAGS) timer.cpp -# to do: figure out hot to use precompiled heeaders +state.o: state.?pp + $(CC) -c $(CC_FLAGS) state.cpp -# state.hpp: state.hpp -# $(CC) -c state.hpp - -# vec2.hpp: vec2.hpp -# $(CC) -c vec2.hpp - -# colors.hpp: colors.hpp -# $(CC) -c colors.hpp - -# CLI11.hpp: CLI11.hpp -# $(CC) -c CLI11.hpp +.PHONY : clean clean: - rm -f $(EXEC) *.o *.gch + -rm -f $(EXEC) $(OBJECTS) *.gch diff --git a/README.md b/README.md @@ -17,7 +17,7 @@ the terminal. * [X] Modified Prim's algorithm - weighted graph * [ ] Growing tree * [X] Wilson's random walk algorithm - * [ ] Binary tree + * [X] Binary tree * [ ] Eller's algorithm * [ ] Sidewinder * Pathfinding algorithms diff --git a/main.cpp b/main.cpp @@ -107,9 +107,6 @@ void GetGridMap(const bool* field, node* grid, const int& width, const int& heig } } -// initializes the state class that holds the configuration of the program -state& s = state::GetInstance(); - int main(int argc, char** argv) { @@ -182,7 +179,7 @@ int main(int argc, char** argv) field[i] = false; // setting the background to white - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(white)); for (int y = 0; y < height; ++y) { for (int x = 0; x < width; ++x) { @@ -191,10 +188,10 @@ int main(int argc, char** argv) } attroff(COLOR_PAIR(white)); refresh(); - s.draw.unlock(); + s::draw.unlock(); // generates the maze and renders it - generators[s.generator](field, width, height); + generators[s::generator](field, width, height); // gets the length of the longest path in the maze start = vec2<int>((std::rand() % ((width - 1) / 2)) * 2 + 1, @@ -240,68 +237,68 @@ int main(int argc, char** argv) (std::rand() % ((height - 1) / 2)) * 2 + 1); // draws random start - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(green)); mvprintw(start.y, start.x * 2, " "); attroff(COLOR_PAIR(green)); refresh(); - s.draw.unlock(); + s::draw.unlock(); // sets random exit(s) exits.clear(); viableExits.clear(); GetGridMap(field, grid, width, height, start); - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(yellow)); for (int y = 1; y < height; y += 2) { for (int x = 1; x < width; x += 2) { if (grid[(y * width) + x].g > (longestPathLength / 3)) { viableExits.push_back(grid[y * width + x].pos); - /* mvprintw(grid[y * width + x].pos.y, grid[y * width + x].pos.x * 2, " "); */ + /* mvprintw(grid[y * width + x].pos::y, grid[y * width + x].pos::x * 2, " "); */ } } } attroff(COLOR_PAIR(yellow)); refresh(); - s.draw.unlock(); + s::draw.unlock(); for (int i = 0; i < 2; ++i) { exits.push_back(viableExits[std::rand() % viableExits.size()]); } // draws random exit(s) - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(red)); for (vec2<int> e : exits) { mvprintw(e.y, e.x * 2, " "); } attroff(COLOR_PAIR(red)); refresh(); - s.draw.unlock(); + s::draw.unlock(); // gets the final path and renders the pathfinding - path = pathfinders[s.pathfinder](field, width, height, start, exits); + path = pathfinders[s::pathfinder](field, width, height, start, exits); - s.draw.lock(); + s::draw.lock(); refresh(); - s.draw.unlock(); + s::draw.unlock(); // draws the final path timer cycle; vec2<int>* prev = &path.front(); for (int i = 1; i < path.size(); ++i) { - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(yellow)); if (i != path.size() - 1) mvprintw(path[i].y, path[i].x * 2, " "); mvprintw((prev->y + path[i].y) / 2, (prev->x + path[i].x), " "); attroff(COLOR_PAIR(yellow)); refresh(); - s.draw.unlock(); + s::draw.unlock(); prev = &path[i]; - cycle.WaitInterval(s.time_path); + cycle.WaitInterval(s::time_path); } - cycle.WaitInterval(s.time_main); + cycle.WaitInterval(s::time_main); } endwin(); return 0; diff --git a/maze_gen.cpp b/maze_gen.cpp @@ -44,9 +44,9 @@ void maze_gen::Backtracker(bool* field, const int& width, const int& height) return ((cells.top()->y + y) * width) + cells.top()->x + x; }; auto drawoffset = [&](int x, int y) { - s.draw.lock(); + s::draw.lock(); mvprintw(cells.top()->y + y, (cells.top()->x + x) * 2, " "); - s.draw.unlock(); + s::draw.unlock(); }; // setting a random root position @@ -107,11 +107,11 @@ void maze_gen::Backtracker(bool* field, const int& width, const int& height) // if there are no viable directions it backtracks cells.pop(); } - if (s.render_maze_gen) { - s.draw.lock(); + if (s::render_maze_gen) { + s::draw.lock(); refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_hard_maze_gen); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_maze_gen); } } } @@ -205,7 +205,7 @@ void maze_gen::Kruskal(bool* field, const int& width, const int& height) edgePos = (e.primary + (e.secondary - e.primary) / 2)->pos; field[(edgePos.y * width) + edgePos.x] = true; - s.draw.lock(); + s::draw.lock(); mvprintw(e.primary->pos.y, e.primary->pos.x * 2, " "); mvprintw(e.secondary->pos.y, e.secondary->pos.x * 2, " "); mvprintw(edgePos.y, edgePos.x * 2, " "); @@ -216,19 +216,19 @@ void maze_gen::Kruskal(bool* field, const int& width, const int& height) attron(COLOR_PAIR(red)); mvprintw(pRoot->pos.y, pRoot->pos.x * 2, " "); attroff(COLOR_PAIR(red)); - s.draw.unlock(); + s::draw.unlock(); - if (s.render_maze_gen) { - s.draw.lock(); + if (s::render_maze_gen) { + s::draw.lock(); refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_hard_maze_gen); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_maze_gen); } } } - s.draw.lock(); + s::draw.lock(); mvprintw(sRoot->pos.y, sRoot->pos.x * 2, " "); - s.draw.unlock(); + s::draw.unlock(); attroff(COLOR_PAIR(black)); } @@ -296,7 +296,7 @@ void maze_gen::PrimRandom(bool* field, const int& width, const int& height) // if the current position is not part of the maze, make it one if (!field[Index(current->pos)]) { current->AddNeighbors(field, grid, width, height); - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(red)); for (cell* n : current->neighbors) { n->parent = current; @@ -304,20 +304,20 @@ void maze_gen::PrimRandom(bool* field, const int& width, const int& height) mvprintw(n->pos.y, n->pos.x * 2, " "); } attroff(COLOR_PAIR(red)); - s.draw.unlock(); + s::draw.unlock(); midpoint = (current + (current->parent - current) / 2)->pos; field[Index(current->pos)] = true; field[Index(midpoint)] = true; - s.draw.lock(); + s::draw.lock(); mvprintw(current->pos.y, current->pos.x * 2, " "); mvprintw(midpoint.y, midpoint.x * 2, " "); - if (s.render_maze_gen) { + if (s::render_maze_gen) { refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_hard_maze_gen); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_maze_gen); } else { - s.draw.unlock(); + s::draw.unlock(); } } } @@ -394,7 +394,7 @@ void maze_gen::PrimWeighted(bool* field, const int& width, const int& height) // if the current position is not part of the maze, make it one if (!field[Index(current->pos)]) { current->AddNeighbors(field, grid, width, height); - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(red)); for (cell* n : current->neighbors) { n->parent = current; @@ -403,20 +403,20 @@ void maze_gen::PrimWeighted(bool* field, const int& width, const int& height) mvprintw(n->pos.y, n->pos.x * 2, " "); } attroff(COLOR_PAIR(red)); - s.draw.unlock(); + s::draw.unlock(); midpoint = (current + (current->parent - current) / 2)->pos; field[Index(current->pos)] = true; field[Index(midpoint)] = true; - s.draw.lock(); + s::draw.lock(); mvprintw(current->pos.y, current->pos.x * 2, " "); mvprintw(midpoint.y, midpoint.x * 2, " "); - if (s.render_maze_gen) { + if (s::render_maze_gen) { refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_hard_maze_gen); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_maze_gen); } else { - s.draw.unlock(); + s::draw.unlock(); } } } @@ -454,22 +454,22 @@ void maze_gen::Wilson(bool* field, const int& width, const int& height) }; // draws a cell in the grid auto Draw = [&](vec2<int>* v) { - s.draw.lock(); + s::draw.lock(); mvprintw(v->y, v->x * 2, " "); - s.draw.unlock(); + s::draw.unlock(); }; // draws a cell with a coordinate offset auto DrawOffset = [&](int x, int y) { - s.draw.lock(); + s::draw.lock(); mvprintw(cells.back()->y + y, (cells.back()->x + x) * 2, " "); - s.draw.unlock(); + s::draw.unlock(); }; // looping through all path cells in the grid that are not part of the maze field[width + 1] = true; - s.draw.lock(); + s::draw.lock(); mvprintw(1, 2, " "); - s.draw.unlock(); + s::draw.unlock(); for (int y = 1; y < height; y += 2) { for (int x = 1; x < width; x += 2) { if (!field[y * width + x]) { @@ -527,11 +527,11 @@ void maze_gen::Wilson(bool* field, const int& width, const int& height) Draw(wall); cells.emplace_back(nextCell); self_collision: - if (s.render_maze_gen) { - s.draw.lock(); + if (s::render_maze_gen) { + s::draw.lock(); refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_soft_maze_gen); + s::draw.unlock(); + cycle.WaitInterval(s::time_soft_maze_gen); } } @@ -545,11 +545,11 @@ void maze_gen::Wilson(bool* field, const int& width, const int& height) prevCell = cells[i]; } - if (s.render_maze_gen) { - s.draw.lock(); + if (s::render_maze_gen) { + s::draw.lock(); refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_hard_maze_gen); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_maze_gen); } } } @@ -558,7 +558,7 @@ void maze_gen::Wilson(bool* field, const int& width, const int& height) void maze_gen::RecursiveDivider(bool* field, const int& width, const int& height) { - s.draw.lock(); + s::draw.lock(); for (int y = 1; y < height - 1; ++y) { for (int x = 1; x < width - 1; ++x) { field[y * width + x] = true; @@ -566,7 +566,7 @@ void maze_gen::RecursiveDivider(bool* field, const int& width, const int& height } } refresh(); - s.draw.unlock(); + s::draw.unlock(); timer cycle; @@ -592,7 +592,7 @@ void maze_gen::RecursiveDivider(bool* field, const int& width, const int& height dy -= 2; // hole column int hy = top_left.y + (2 * (std::rand() % (dy / 2))) + 1; - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(white)); for (int y = top_left.y + 1; y < bottom_right.y; y++) { field[y * width + wx] = false; @@ -604,8 +604,8 @@ void maze_gen::RecursiveDivider(bool* field, const int& width, const int& height mvprintw(hy, wx * 2, " "); attron(COLOR_PAIR(black)); refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_hard_maze_gen); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_maze_gen); vec2<int> new_bottom_right(wx, bottom_right.y); vec2<int> new_top_left(wx, top_left.y); Divide(top_left, new_bottom_right); @@ -623,7 +623,7 @@ void maze_gen::RecursiveDivider(bool* field, const int& width, const int& height dx -= 2; // hole row int hx = top_left.x + (2 * (std::rand() % (dx / 2))) + 1; - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(white)); for (int x = top_left.x + 1; x < bottom_right.x; x++) { field[wy * width + x] = false; @@ -635,8 +635,8 @@ void maze_gen::RecursiveDivider(bool* field, const int& width, const int& height mvprintw(wy, hx * 2, " "); attron(COLOR_PAIR(black)); refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_hard_maze_gen); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_maze_gen); vec2<int> new_bottom_right(bottom_right.x, wy); vec2<int> new_top_left(top_left.x, wy); Divide(top_left, new_bottom_right); @@ -695,7 +695,7 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei }; // gets rid of the walls inside the maze - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(black)); for (int y = 1; y < height - 1; ++y) { for (int x = 1; x < width - 1; ++x) { @@ -709,10 +709,10 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei field[y * width + x] = false; } } - if (s.render_maze_gen) + if (s::render_maze_gen) refresh(); attroff(COLOR_PAIR(black)); - s.draw.unlock(); + s::draw.unlock(); // initializes the grid cell grid[width * height]; for (int y = 0; y < height; ++y) { @@ -738,7 +738,7 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei return; // cleans the set from previous data - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(purple)); for (cell* c : l) { c->setName = 'l'; @@ -747,7 +747,7 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei mvprintw(c->pos.y, c->pos.x * 2, " "); } attroff(COLOR_PAIR(purple)); - s.draw.unlock(); + s::draw.unlock(); // gets two random seeds for set a and b respectively cell* seedA = l[std::rand() % l.size()]; @@ -762,8 +762,8 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei o.push_back(seedB); seedA->isVisited = true; seedB->isVisited = true; - if (s.render_maze_gen) { - s.draw.lock(); + if (s::render_maze_gen) { + s::draw.lock(); attron(COLOR_PAIR(red)); mvprintw(seedA->pos.y, seedA->pos.x * 2, " "); attroff(COLOR_PAIR(red)); @@ -771,7 +771,7 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei mvprintw(seedB->pos.y, seedB->pos.x * 2, " "); attroff(COLOR_PAIR(blue)); refresh(); - s.draw.unlock(); + s::draw.unlock(); } // expands a and b until they cover the whole of the local set @@ -782,8 +782,8 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei current = o[index]; o.erase(o.begin() + index); current->AddNeighbors(grid, width, height); - if (s.render_maze_gen) { - s.draw.lock(); + if (s::render_maze_gen) { + s::draw.lock(); attron(COLOR_PAIR(red)); if (current->setName == 'b') attron(COLOR_PAIR(blue)); @@ -791,14 +791,14 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei attroff(COLOR_PAIR(blue)); attroff(COLOR_PAIR(red)); refresh(); - s.draw.unlock(); + s::draw.unlock(); } for (cell* c : current->neighbors) { c->setName = current->setName; o.push_back(c); } - if (!current->isVisited && s.render_maze_gen) { - cycle.WaitInterval(s.time_soft_maze_gen); + if (!current->isVisited && s::render_maze_gen) { + cycle.WaitInterval(s::time_soft_maze_gen); } current->isVisited = true; } @@ -827,7 +827,7 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei } } // draws the corners of the wall - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(white)); for (vec2<int>* mid : w) { std::vector<cell*> wallCorners; @@ -862,28 +862,28 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei mvprintw(mid->y, mid->x * 2, " "); } attroff(COLOR_PAIR(white)); - if (s.render_maze_gen) + if (s::render_maze_gen) refresh(); - s.draw.unlock(); - if (s.render_maze_gen) - cycle.WaitInterval(s.time_soft_maze_gen); + s::draw.unlock(); + if (s::render_maze_gen) + cycle.WaitInterval(s::time_soft_maze_gen); // punches a hole in the wall midpoint = w[std::rand() % w.size()]; field[midpoint->y * width + midpoint->x] = true; - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(black)); mvprintw(midpoint->y, midpoint->x * 2, " "); attroff(COLOR_PAIR(black)); - if (s.render_maze_gen) + if (s::render_maze_gen) refresh(); - s.draw.unlock(); - if (s.render_maze_gen) - cycle.WaitInterval(s.time_hard_maze_gen); + s::draw.unlock(); + if (s::render_maze_gen) + cycle.WaitInterval(s::time_hard_maze_gen); // cleans up after a division is made - if (s.render_maze_gen) { - s.draw.lock(); + if (s::render_maze_gen) { + s::draw.lock(); attron(COLOR_PAIR(black)); for (cell* c : l) { c->setName = 's'; @@ -891,7 +891,7 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei } attroff(COLOR_PAIR(black)); refresh(); - s.draw.unlock(); + s::draw.unlock(); } else { for (cell* c : l) { c->setName = 's'; @@ -904,10 +904,39 @@ void maze_gen::RecursiveDividerSet(bool* field, const int& width, const int& hei Divide(l); - if (!s.render_maze_gen) { - s.draw.lock(); + if (!s::render_maze_gen) { + s::draw.lock(); refresh(); - s.draw.unlock(); + s::draw.unlock(); + } +} + +void maze_gen::BinaryTree(bool* field, const int& width, const int& height) +{ + std::vector<vec2<int>> neighbors; + vec2<int>* selected; + timer cycle; + for (int y = 1; y < height - 1; y += 2) { + for (int x = 1; x < width - 1; x += 2) { + if (x < width - 3) + neighbors.push_back(vec2<int>(x + 2, y)); + if (y < height - 3) + neighbors.push_back(vec2<int>(x, y + 2)); + if (neighbors.empty()) + continue; + selected = &neighbors[std::rand() % neighbors.size()]; + field[(y * width) + x] = true; + field[(selected->y * width) + selected->x] = true; + field[((selected->y + y) * width / 2) + (selected->x + x) / 2] = true; + s::draw.lock(); + mvprintw(y, x * 2, " "); + mvprintw(selected->y, selected->x * 2, " "); + mvprintw((selected->y + y) / 2, (selected->x + x), " "); + refresh(); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_maze_gen); + neighbors.clear(); + } } } @@ -923,6 +952,7 @@ std::map<std::string, { "PrimWeighted", maze_gen::PrimWeighted }, { "Wilson", maze_gen::Wilson }, { "RecursiveDivider", maze_gen::RecursiveDivider }, - { "RecursiveDividerSet", maze_gen::RecursiveDividerSet } + { "RecursiveDividerSet", maze_gen::RecursiveDividerSet }, + { "BinaryTree", maze_gen::BinaryTree }, }; diff --git a/maze_gen.hpp b/maze_gen.hpp @@ -26,6 +26,7 @@ void PrimWeighted(bool* field, const int& width, const int& height); void Wilson(bool* field, const int& width, const int& height); void RecursiveDividerSet(bool* field, const int& width, const int& height); void RecursiveDivider(bool* field, const int& width, const int& height); +void BinaryTree(bool* field, const int& width, const int& height); }; // namespace maze_gen #endif // MAZE_GEN_HPP diff --git a/pathfinding.cpp b/pathfinding.cpp @@ -68,9 +68,9 @@ std::vector<vec2<int>> pathfinding::Breadth( while (!q.empty()) { attron(COLOR_PAIR(green)); - s.draw.lock(); + s::draw.lock(); mvprintw(start.y, start.x * 2, " "); - s.draw.unlock(); + s::draw.unlock(); attron(COLOR_PAIR(green)); current = q.front(); @@ -88,18 +88,18 @@ std::vector<vec2<int>> pathfinding::Breadth( return path; } } - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(blue)); mvprintw(current->pos.y, current->pos.x * 2, " "); mvprintw(((current->pos + parent->pos) / 2).y, ((current->pos + parent->pos) / 2).x * 2, " "); attroff(COLOR_PAIR(blue)); - s.draw.unlock(); + s::draw.unlock(); q.pop(); current->AddNeighbors(field, grid, width, height); - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(cyan)); for (node* n : current->neighbors) { if (!n->isVisited) { @@ -110,12 +110,12 @@ std::vector<vec2<int>> pathfinding::Breadth( } } attroff(COLOR_PAIR(cyan)); - s.draw.unlock(); - if (s.render_pathfinding) { - s.draw.lock(); + s::draw.unlock(); + if (s::render_pathfinding) { + s::draw.lock(); refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_hard_pathfinding); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_pathfinding); } } return std::vector<vec2<int>>(); @@ -177,9 +177,9 @@ std::vector<vec2<int>> pathfinding::Depth( while (!q.empty()) { attron(COLOR_PAIR(green)); - s.draw.lock(); + s::draw.lock(); mvprintw(start.y, start.x * 2, " "); - s.draw.unlock(); + s::draw.unlock(); attron(COLOR_PAIR(green)); current = q.top(); current->isVisited = true; @@ -204,16 +204,16 @@ std::vector<vec2<int>> pathfinding::Depth( } } attron(COLOR_PAIR(blue)); - s.draw.lock(); + s::draw.lock(); mvprintw(current->pos.y, current->pos.x * 2, " "); mvprintw(wall->pos.y, wall->pos.x * 2, " "); - s.draw.unlock(); + s::draw.unlock(); attroff(COLOR_PAIR(blue)); q.pop(); current->AddNeighbors(field, grid, width, height); attron(COLOR_PAIR(cyan)); - s.draw.lock(); + s::draw.lock(); for (node* n : current->neighbors) { if (!n->isVisited) { n->parent = current; @@ -222,13 +222,13 @@ std::vector<vec2<int>> pathfinding::Depth( mvprintw(middle->pos.y, middle->pos.x * 2, " "); } } - s.draw.unlock(); + s::draw.unlock(); attroff(COLOR_PAIR(cyan)); - if (s.render_pathfinding) { - s.draw.lock(); + if (s::render_pathfinding) { + s::draw.lock(); refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_hard_pathfinding); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_pathfinding); } } return std::vector<vec2<int>>(); @@ -339,18 +339,18 @@ std::vector<vec2<int>> pathfinding::AStar( } else { middle = current; } - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(blue)); mvprintw(current->pos.y, current->pos.x * 2, " "); mvprintw(middle->pos.y, middle->pos.x * 2, " "); attroff(COLOR_PAIR(blue)); - s.draw.unlock(); + s::draw.unlock(); if (current->pos == start) { - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(green)); mvprintw(start.y, start.x * 2, " "); attroff(COLOR_PAIR(green)); - s.draw.unlock(); + s::draw.unlock(); } for (int i = 0; i < neighbors.size(); ++i) { @@ -366,12 +366,12 @@ std::vector<vec2<int>> pathfinding::AStar( if ((std::find(openSet.begin(), openSet.end(), neighbor) == openSet.end())) { openSet.push_back(neighbor); - s.draw.lock(); + s::draw.lock(); middle = (neighbor + (current - neighbor) / 2); attron(COLOR_PAIR(cyan)); mvprintw(middle->pos.y, middle->pos.x * 2, " "); attroff(COLOR_PAIR(cyan)); - s.draw.unlock(); + s::draw.unlock(); } else if (g_temp >= neighbor->g) { continue; } @@ -389,11 +389,11 @@ std::vector<vec2<int>> pathfinding::AStar( neighbor->f = neighbor->h + neighbor->g; neighbor->parent = current; } - if (s.render_pathfinding) { - s.draw.lock(); + if (s::render_pathfinding) { + s::draw.lock(); refresh(); - s.draw.unlock(); - cycle.WaitInterval(s.time_hard_pathfinding); + s::draw.unlock(); + cycle.WaitInterval(s::time_hard_pathfinding); } } } diff --git a/state.cpp b/state.cpp @@ -16,5 +16,5 @@ bool render_pathfinding = true; // should you render pathfinding proccess? bool ui_is_open = false; // is ui open or waiting to be rendered? bool ui_render_is_safe = false; // is it safe to render ui? std::string pathfinder = "A*"; -std::string generator = "RecursiveDivider"; +std::string generator = "BinaryTree"; }; diff --git a/state.hpp b/state.hpp @@ -1,37 +1,23 @@ -#pragma once - #ifndef STATE_HPP #define STATE_HPP #include <mutex> #include <string> -class state { -public: - static state& GetInstance() - { - static state instance; - return instance; - } - state(state const&) = delete; - void operator=(state const&) = delete; - std::mutex draw; - // add meta data variable - state() {}; - int time_hard_maze_gen = 10; // time between algorithm cycles - int time_soft_maze_gen = 1; // time between cycles within algorithms cycles - int time_hard_pathfinding = 15; // time between algorithm cycles - int time_soft_pathfinding = 2; // time between cycles within algorithms cycles - int time_main = 1500; // time between main loops - int time_path = 15; // time between drawing steps in final path - bool render_maze_gen = true; // should you render maze generating proccess? - bool render_pathfinding = true; // should you render pathfinding proccess? - bool ui_is_open = false; // is ui open or waiting to be rendered? - bool ui_render_is_safe = false; // is it safe to render ui? - std::string pathfinder = "A*"; - std::string generator = "RecursiveDivider"; +namespace s { +extern std::mutex draw; +extern int time_hard_maze_gen; // time between algorithm cycles +extern int time_soft_maze_gen; // time between cycles within algorithms cycles +extern int time_hard_pathfinding; // time between algorithm cycles +extern int time_soft_pathfinding; // time between cycles within algorithms cycles +extern int time_main; // time between main loops +extern int time_path; // time between drawing steps in final path +extern bool render_maze_gen; // should you render maze generating proccess? +extern bool render_pathfinding; // should you render pathfinding proccess? +extern bool ui_is_open; // is ui open or waiting to be rendered? +extern bool ui_render_is_safe; // is it safe to render ui? +extern std::string pathfinder; +extern std::string generator; }; #endif // STATE_HPP - -extern state& s; diff --git a/timer.cpp b/timer.cpp @@ -15,12 +15,12 @@ timer::~timer() void timer::WaitInterval(const float& time_ms) { using namespace std::chrono; - if (s.ui_is_open) { - s.ui_render_is_safe = true; - while (s.ui_is_open) { + if (s::ui_is_open) { + s::ui_render_is_safe = true; + while (s::ui_is_open) { std::this_thread::sleep_for(milliseconds(3)); } - s.ui_render_is_safe = false; + s::ui_render_is_safe = false; initTime = std::chrono::steady_clock::now(); elapsedTime = milliseconds(0); } else { diff --git a/ui.cpp b/ui.cpp @@ -26,11 +26,11 @@ static std::string Option( win_width += 2 + 10; int y_max, x_mas; // creating and rendering the sub window - s.ui_is_open = true; - while (!s.ui_render_is_safe) { + s::ui_is_open = true; + while (!s::ui_render_is_safe) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(black)); getmaxyx(stdscr, y_max, x_mas); WINDOW* win = newwin( @@ -84,8 +84,8 @@ static std::string Option( del_panel(pan); update_panels(); attroff(COLOR_PAIR(black)); - s.draw.unlock(); - s.ui_is_open = false; + s::draw.unlock(); + s::ui_is_open = false; return options[highlight]; break; case 27: // escape @@ -95,8 +95,8 @@ static std::string Option( del_panel(pan); update_panels(); attroff(COLOR_PAIR(black)); - s.draw.unlock(); - s.ui_is_open = false; + s::draw.unlock(); + s::ui_is_open = false; return current; break; default: @@ -117,11 +117,11 @@ static std::string Option(const std::vector<std::string>& options) win_width += 2 + 10; int y_max, x_mas; // creating and rendering the sub window - s.ui_is_open = true; - while (!s.ui_render_is_safe) { + s::ui_is_open = true; + while (!s::ui_render_is_safe) { std::this_thread::sleep_for(std::chrono::milliseconds(1)); } - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(black)); getmaxyx(stdscr, y_max, x_mas); WINDOW* win = newwin( @@ -167,8 +167,8 @@ static std::string Option(const std::vector<std::string>& options) del_panel(pan); update_panels(); attroff(COLOR_PAIR(black)); - s.draw.unlock(); - s.ui_is_open = false; + s::draw.unlock(); + s::ui_is_open = false; return options[highlight]; break; case 27: // escape @@ -178,8 +178,8 @@ static std::string Option(const std::vector<std::string>& options) del_panel(pan); update_panels(); attroff(COLOR_PAIR(black)); - s.draw.unlock(); - s.ui_is_open = false; + s::draw.unlock(); + s::ui_is_open = false; return ""; break; default: @@ -227,7 +227,7 @@ void ui::RenderUI() ++it) { names.push_back(it->first); } - s.generator = Option(names, s.generator); + s::generator = Option(names, s::generator); } if (mmenu == "Pathfinder =>") { @@ -244,7 +244,7 @@ void ui::RenderUI() it != pathfinders.end(); ++it) { names.push_back(it->first); } - s.pathfinder = Option(names, s.pathfinder); + s::pathfinder = Option(names, s::pathfinder); } } } @@ -256,7 +256,7 @@ void ui::ExecuteKeys() while (true) { getmaxyx(stdscr, height, width); c = getch(); - s.draw.lock(); + s::draw.lock(); attron(COLOR_PAIR(white)); // clears the top portion of the screen of previous text for (int i = 0; i <= width; ++i) { @@ -265,76 +265,76 @@ void ui::ExecuteKeys() // handles key presses switch (c) { case 'k': - s.time_hard_maze_gen += 1; - mvprintw(0, 0, "Maze generation hard time: %d", s.time_hard_maze_gen); + s::time_hard_maze_gen += 1; + mvprintw(0, 0, "Maze generation hard time: %d", s::time_hard_maze_gen); attroff(COLOR_PAIR(white)); refresh(); - s.draw.unlock(); + s::draw.unlock(); break; case 'K': - s.time_soft_maze_gen += 1; - mvprintw(0, 0, "Maze generation soft time: %d", s.time_soft_maze_gen); + s::time_soft_maze_gen += 1; + mvprintw(0, 0, "Maze generation soft time: %d", s::time_soft_maze_gen); attroff(COLOR_PAIR(white)); refresh(); - s.draw.unlock(); + s::draw.unlock(); break; case 'j': - s.time_hard_maze_gen -= 1; - mvprintw(0, 0, "Maze generation hard time: %d", s.time_hard_maze_gen); + s::time_hard_maze_gen -= 1; + mvprintw(0, 0, "Maze generation hard time: %d", s::time_hard_maze_gen); attroff(COLOR_PAIR(white)); refresh(); - s.draw.unlock(); + s::draw.unlock(); break; case 'J': - s.time_soft_maze_gen -= 1; - mvprintw(0, 0, "Maze generation soft time: %d", s.time_soft_maze_gen); + s::time_soft_maze_gen -= 1; + mvprintw(0, 0, "Maze generation soft time: %d", s::time_soft_maze_gen); attroff(COLOR_PAIR(white)); refresh(); - s.draw.unlock(); + s::draw.unlock(); break; case 'i': - s.time_hard_pathfinding += 1; - mvprintw(0, 0, "Pathfinding hard time: %d", s.time_hard_pathfinding); + s::time_hard_pathfinding += 1; + mvprintw(0, 0, "Pathfinding hard time: %d", s::time_hard_pathfinding); attroff(COLOR_PAIR(white)); refresh(); - s.draw.unlock(); + s::draw.unlock(); break; case 'I': - s.time_soft_pathfinding += 1; - mvprintw(0, 0, "Pathfinding soft time: %d", s.time_soft_pathfinding); + s::time_soft_pathfinding += 1; + mvprintw(0, 0, "Pathfinding soft time: %d", s::time_soft_pathfinding); attroff(COLOR_PAIR(white)); refresh(); - s.draw.unlock(); + s::draw.unlock(); break; case 'u': - s.time_hard_pathfinding -= 1; - mvprintw(0, 0, "Pathfinding hard time: %d", s.time_hard_pathfinding); + s::time_hard_pathfinding -= 1; + mvprintw(0, 0, "Pathfinding hard time: %d", s::time_hard_pathfinding); attroff(COLOR_PAIR(white)); refresh(); - s.draw.unlock(); + s::draw.unlock(); break; case 'U': - s.time_soft_pathfinding -= 1; - mvprintw(0, 0, "Pathfinding soft time: %d", s.time_soft_pathfinding); + s::time_soft_pathfinding -= 1; + mvprintw(0, 0, "Pathfinding soft time: %d", s::time_soft_pathfinding); attroff(COLOR_PAIR(white)); refresh(); - s.draw.unlock(); + s::draw.unlock(); break; case 27: attroff(COLOR_PAIR(white)); - s.draw.unlock(); + s::draw.unlock(); RenderUI(); break; case 'q': attroff(COLOR_PAIR(white)); - s.draw.unlock(); + s::draw.unlock(); endwin(); exit(0); default: mvprintw(0, 0, "Unknown mapping: <%d>", c); attroff(COLOR_PAIR(white)); refresh(); - s.draw.unlock(); + s::draw.unlock(); break; } std::this_thread::sleep_for(std::chrono::milliseconds(3));