Thread: Adventures in labyrinth generation.

Hybrid View

Previous Post Previous Post   Next Post Next Post
  1. #1
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    FWIW, I thought this was simply genius.
    #
    # Unicursal: One way to create a random unicursal Maze is to take a perfect Maze, seal off the exit so there's only the one entrance, then add walls bisecting each passage. This will turn each dead end into a U-turn passageway, and there will be a unicursal passage starting and ending at the original Maze's beginning, that will follow the same path as someone wall following the original Maze. The new unicursal Maze will have twice the dimensions of the original perfect Maze it was based on. Small tricks may be done to have the start and end not always be next to each other: When creating the perfect Maze, never add segments attached to the right or bottom walls, so the resulting Maze will have an easy solution that follows that wall. Have the entrance at the upper right, and after bisecting to create the unicursal routing, remove the right and bottom wall. This will result in a unicursal Maze that starts at the upper right and ends at the lower left.
    Image: http://www.astrolog.org/labyrnth/maze/unicursl.gif
    Webpage: http://www.astrolog.org/labyrnth/algrithm.htm

    But now I see that you've already seen that page.
    http://www.gamedev.net/community/for...page=1�
    [edit=2] Weird, that link was either copied or transmitted incorrectly. Here it is again.
    http://www.gamedev.net/community/for...page=1� [/edit]
    [edit=3] Urf, it happened again! I guess it's the sequence <ampersand><hash> in the link that makes vBulletin mess up.
    Just go here and scroll down. http://www.gamedev.net/community/for...opic_id=501637 [/edit]

    [edit] Anyway, here's my very ugly half-hour-to-code C++ labyrinth generator that gives you all of the possible labyrinths for a given size.

    Yes, it takes forever to execute. And yes, I know positions are reversed. No, I can't be bothered to fix it.

    Code:
    #include <iostream>
    #include <cstdlib>
    #include <ctime>
    
    class Position {
    private:
        int xp, yp;
    public:
        Position(int xp, int yp) : xp(xp), yp(yp) {}
        
        void add_xp(int add) { xp += add; }
        void add_yp(int add) { yp += add; }
        
        int add_direction(int add, int dir);
        int get_dirs() { return 4; }
        
        void set_xp(int xp) { this->xp = xp; }
        void set_yp(int yp) { this->yp = yp; }
        
        int get_xp() { return xp; }
        int get_yp() { return yp; }
    };
    
    int Position::add_direction(int add, int dir) {
        switch(dir) {
        case 0:
            xp += add;
            break;
        case 1:
            xp -= add;
            break;
        case 2:
            yp += add;
            break;
        case 3:
            yp -= add;
            break;
        }
    }
    
    class Map {
    private:
        static const int WIDTH = 6, HEIGHT = 6;
        char cell[WIDTH][HEIGHT];
    public:
        Map() { clear(); }
        
        void set_cell(int x, int y, char c) { cell[x][y] = c; }
        char get_cell(int x, int y);
        
        bool is_empty(int x, int y) { return get_cell(x, y) == get_empty_char(); }
        
        char get_empty_char() { return '-'; }
        int get_width() { return WIDTH; }
        int get_height() { return HEIGHT; }
        
        void clear();
        void display();
        bool map_is_full();
    };
    
    char Map::get_cell(int x, int y) {
        if(x < 0 || y < 0 || x >= get_width() || y >= get_height()) {
            return -1;
        }
        
        return cell[x][y];
    }
    
    void Map::clear() {
        for(int x = 0; x < get_width(); x ++) {
            for(int y = 0; y < get_height(); y ++) {
                set_cell(x, y, get_empty_char());
            }
        }
    }
    
    void Map::display() {
        for(int x = 0; x < get_width(); x ++) {
            for(int y = 0; y < get_height(); y ++) {
                std::cout << get_cell(x, y);
            }
            
            std::cout << '\n';
        }
    }
    
    bool Map::map_is_full() {
        for(int x = 0; x < get_width(); x ++) {
            for(int y = 0; y < get_height(); y ++) {
                if(get_cell(x, y) == get_empty_char()) return false;
            }
        }
        
        return true;
    }
    
    void trace_labyrinth(Map &map, Position &pos);
    
    int main() {
        std::srand((unsigned)std::time(0));
        
        Map map;
        Position start(
            std::rand() &#37; map.get_width(),
            std::rand() % map.get_height());
        
        map.set_cell(start.get_xp(), start.get_yp(), '@');
        
        trace_labyrinth(map, start);
        
        return 0;
    }
    
    void trace_labyrinth(Map &map, Position &pos) {
        Position next = pos;
        
        int startdir = rand() % next.get_dirs();
        int dir = startdir;
        bool found_move = false;
        do {
            next = pos;
            next.add_direction(1, dir);
            
            if(map.is_empty(next.get_xp(), next.get_yp())) {
                map.set_cell(next.get_xp(), next.get_yp(), "v^><"[dir]);
                
                trace_labyrinth(map, next);
                found_move = true;
            }
            
            dir ++;
            dir %= next.get_dirs();
        } while(dir != startdir);
        
        if(!found_move) {
            map.set_cell(pos.get_xp(), pos.get_yp(), '$');
            
            if(map.map_is_full()) {
                map.display();
                std::cout << std::endl;
            }
        }
        
        map.set_cell(pos.get_xp(), pos.get_yp(), map.get_empty_char());
    }
    [/edit]
    Last edited by dwks; 10-11-2008 at 04:09 PM.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Labyrinth generation
    By guesst in forum Game Programming
    Replies: 16
    Last Post: 10-09-2008, 06:02 PM
  2. Diablo's random level generation
    By glo in forum Game Programming
    Replies: 7
    Last Post: 07-19-2008, 03:04 AM
  3. C Program with Tone Generation. HELP
    By LaVieEnRose in forum C Programming
    Replies: 1
    Last Post: 11-22-2007, 08:37 PM
  4. Grid generation from scattered points?
    By canada-paul in forum C Programming
    Replies: 6
    Last Post: 12-12-2003, 05:46 PM
  5. Random number generation
    By Lisa Mowbray in forum C++ Programming
    Replies: 4
    Last Post: 04-30-2002, 12:22 PM