Dynamically Sized Cave

From RogueBasin
Revision as of 15:16, 14 April 2021 by Foobar (talk | contribs) (Created page with "=== Example === <pre> ./cave.pl 500 1618413156 #################################################################################################### #### ################...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Example

./cave.pl 500 1618413156
####################################################################################################
####      ##########################################################################################
##          ####      ##            ################################################################
##                                    ##############################################################
##                                    ##############################################################
##                                      ############################################################
##                                        ##########################################################
##                                          ########################################################
##            ####                          ########################################################
####    ##########                                    ##############################################
####################                                    ############################################
########################                                    ########################################
########################                                      ######################################
########################                                          ##################################
######################                                                ##############################
######################                                                  ############################
########################                                                ############################
##########################                                            ##############################
############################                                        ################################
################################                                        ############################
####################################                                            ####################
####################################                                              ##################
####################################                    ####                      ##################
######################################                ########                    ##################
######################################              ############                  ##################
######################################            ################                ##    ############
######################################        ####################                        ##########
######################################        ######################                      ##########
########################################    ######################                            ######
##############################################################                                  ####
############################################################              ####                    ##
############################################################              ######      ##          ##
############################################################                ####                ####
####################################################                        ######              ####
##################################################                        ##########          ######
##################################################                ##################        ########
####################################################            ####################          ######
##################################################        ########################            ######
##################################################      ########################                ####
##################################################        ######################                ####
################################################            ####################                  ##
########################################                      ####################                ##
######################################                          ##################              ####
######################################                          ####################          ######
####################################                          ######################################
######################################    ####        ##############################################
####################################################################################################

Code

#!/usr/bin/env perl

use strict;
use warnings;

no warnings 'uninitialized';
no warnings 'recursion';

use List::Util qw/min max shuffle/;

# Command-line options

my $CELLS = $ARGV[0] || 250;
my $SEED  = $ARGV[1] || time();

srand($SEED);

# Constants

my %DIRECTIONS = (
    N => { dy => -1, opposite => 'S' },
    S => { dy => 1,  opposite => 'N' },
    E => { dx => 1,  opposite => 'W' },
    W => { dx => -1, opposite => 'E' },
);

# Variables

my $map = {};
my ( $min_x, $min_y, $max_x, $max_y ) = ( 0, 0, 0, 0 );
my $count = 0;

# Code

carve( 0, 0, 'E' );
print output();

print "$0 $CELLS $SEED # => ( $min_x, $min_y, $max_x, $max_y )\n";

sub carve {
    my ( $x0, $y0, $direction ) = @_;

    my $x1 = $x0 + $DIRECTIONS{$direction}{dx};
    my $y1 = $y0 + $DIRECTIONS{$direction}{dy};

    return if defined $map->{$y1}{$x1};    # already visited

    $min_x = min( $min_x, $x1 );
    $max_x = max( $max_x, $x1 );

    $min_y = min( $min_y, $y1 );
    $max_y = max( $max_y, $y1 );

    $map->{$y0}{$x0}{$direction} = 1;
    $map->{$y1}{$x1}{ $DIRECTIONS{$direction}{opposite} } = 1;

    return if $count++ > $CELLS;

    for my $new_direction ( shuffle keys %DIRECTIONS ) {
        carve( $x1, $y1, $new_direction );
    }
}

sub output {
    my $output = '';
    for my $y ( $min_y - 1 .. $max_y + 1 ) {
        for my $x ( $min_x - 1 .. $max_x + 1 ) {
            $output .= ref $map->{$y}{$x} ? '  ' : '##';
        }
        $output .= "\n";
    }
    return $output;
}

Description

This code is similar to the Dynamically Sized Maze. The main difference is that we replace the internal maze with an open space, resulting in a very organic-like cave.

Usage

$ ./cave.pl [length] [random seed]


See also