Day 17: Maze Maker for Fun

Maze Maker

I remember when I was in school, I used to play the game where you help the mouse go through the maze and reach the target as quickly as possible. Even
when I finished my college, I would still wonder how one can create a maze. Those who create maze must be super ingenious.

It was only recently I decided to decode the mystery of maze creation. I asked my friend Google and guess what, I was presented with plenty of solutions in various languages. Some very difficult to follow and some not so difficult. Having got my head around the algorithm, I decided to do it in my first language i.e. Perl. It didn’t took me long to convert the algorithm into Perl script.

As you all know, I am still a new player in Raku. Thankfully I have plenty of support when it comes to Raku queries. For the first time, I decided to be part of Raku Advent Calendar. Thanks to JJ Merelo, I was given a slot. At that point, I didn’t have a clue what I am going to do. But I knew I have plenty of ideas that can be converted into Raku.

As you guessed it correctly, I picked my favourite maze maker script for the Raku Advent Calendar. With the help of many people on Twitter, I got my first draft ready in Raku. But it wasn’t creating the tunnel as expected. I went to my friend, Scimon Proctor, for guidance. He helped me with the Raku magic and all working smoothly now.

It was time to do some housekeeping before I hand it over to JJ Merelo. Having spent around 30 minutes, I got my final draft ready as below:

use v6;

my %opposite-of = ( 'north' => 'south', 'south' => 'north',  'west' => 'east', 'east'  => 'west' );
my @directions  = %opposite-of.keys;

sub MAIN(Int :$height = 10, Int :$width = 10) {
    my $maze;
    make-maze( 0, 0, $maze, $height, $width );
    say render-maze( $maze, $height, $width );
}

#
#
# METHODS

sub make-maze( $x, $y, $maze is rw, $height, $width ) {

    for ( @directions.pick(@directions) ) -> $direction {
        my ( $new_x, $new_y ) = ( $x, $y );

        if    ( 'east'  eq $direction ) { $new_x += 1; }
        elsif ( 'west'  eq $direction ) { $new_x -= 1; }
        elsif ( 'south' eq $direction ) { $new_y += 1; }
        else                            { $new_y -= 1; }

        if not-visited( $new_x, $new_y, $maze, $height, $width ) {
            $maze[$y][$x]{$direction} = 1;
            $maze[$new_y][$new_x]{ %opposite-of{$direction} } = 1;
            make-maze( $new_x, $new_y, $maze, $height, $width );
        }
    }
}

sub not-visited( $x, $y, $maze, $height, $width ) {

    # check the boundary
    return if $x < 0 or $y < 0;
    return if $x > $width - 1 or $y > $height - 1;

    # return false if already visited
    return if $maze[$y][$x];

    # return true
    return 1;
}

sub render-maze($maze, $height, $width) {

    my $as_string = " " ~ ( "_ " x $width );
    $as_string ~= "\n";

    for ( 0 .. $height - 1 ) -> $y {
        $as_string ~= "|";
        for ( 0 .. $width - 1 ) -> $x {
            my $cell = $maze[$y][$x];
            $as_string ~= $cell<south> ?? " " !! "_";
            $as_string ~= $cell<east>  ?? " " !! "|";
        }
        $as_string ~= "\n";
    }

    return $as_string;
}

What next?

I am thinking of converting this into a Raku Library, something like Games::Maze. I am working on it, hopefully I should have it ready before Christmas.

If you think it can be improved in any way then please do share with me. I would love to hear from you and learn from your experience. Till then have fun with it from a Perl Fan, who equally loves Raku.

2 thoughts on “Day 17: Maze Maker for Fun

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.