Dynamically Sized Cave

From RogueBasin
Jump to navigation Jump to search

Example

./cave.pl 500 1618413480
########################################################################################################
####      ##    ########################################################################################
##                ######################################################################################
##                ######################################################################################
####                ####################################################################################
####                ####################################################################################
####                ####################################################################################
####                  ##################################################################################
######                ##################################################################################
############          ##################################################################################
##############        ##    ############################################################################
##############                ##########################################################################
##############                  ########################################################################
##############                  ########################################################################
################                ########################################################################
########                        ########################################################################
######                        ##########################################################################
######                      ############################################################################
########                ################################################################################
######                  ################################################################################
######        ####      ####################################      ######################################
######          ##        ################################          ####################################
######          ####              ########################              ################################
########      ########              ##############                        ##############################
########################              ##    ##                              ############################
########################                                                      ##########################
######################                                                          ########################
####################                                                            ########################
##################                                                ######        ########################
##################                                                ######          ######################
####################                                              ######          ############    ######
########################    ##                            ##    ######                ######        ####
################################                      ##############                                  ##
################################                        ##                                            ##
################################        ##                                                          ####
################################        ########                                                      ##
##################################    ############                                                    ##
######################################################                                              ####
######################################################                                              ####
######################################################                                            ######
######################################################                              ####################
########################################################                            ####################
##########################################################        ######            ####################
##########################################################      ######            ######################
########################################################        ####        ############################
########################################################      ######      ##############################
######################################################        ######      ##############################
####################################################                      ##############################
####################################################                        ############################
######################################################                      ############################
##################################################################        ##############################
########################################################################################################

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