Game-TextMapper
view release on metacpan or search on metacpan
lib/Game/TextMapper/Gridmapper.pm view on Meta::CPAN
# Copyright (C) 2009-2021 Alex Schroeder <alex@gnu.org>
#
# This program is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, either version 3 of the License, or (at your option) any
# later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.
=encoding utf8
=head1 NAME
Game::TextMapper::Gridmapper - generate dungeon maps
=head1 DESCRIPTION
This generates dungeon maps. At its core, this uses a 3Ã3 layout, 9 sections
total. 5 or 7 of these 9 sections get a room. The connections for the rooms (the
"shape") is picked at random from a fixed list of configurations (plus flipped
and rotated variants). The first room contains the stairs.
To generate bigger dungeons, more of these 3Ã3 layouts are added to the first.
As the number of rooms is dynamic, the algorithm figures out how to best use a
number of layouts containing 5 or 7 rooms to get to that number, and then simply
drops the extra rooms.
=head1 METHODS
=cut
package Game::TextMapper::Gridmapper;
use Game::TextMapper::Log;
use Game::TextMapper::Constants qw($dx $dy);
use Modern::Perl '2018';
use List::Util qw'shuffle none any min max all';
use List::MoreUtils qw'pairwise';
use Mojo::Util qw(url_escape);
use Mojo::Base -base;
my $log = Game::TextMapper::Log->get;
# This is the meta grid for the geomorphs. Normally this is (3,3) for simple
# dungeons. We need to recompute these when smashing geomorphs together.
has 'dungeon_dimensions';
has 'dungeon_geomorph_size';
# This is the grid for a particular geomorph. This is space for actual tiles.
has 'room_dimensions';
# Rows and columns, for the tiles. Add two tiles for the edges, so the first
# two rows and the last two rows, and the first two columns and the last two
# columns should be empty. This is the empty space where stairs can be added.
# (0,0) starts at the top left and goes rows before columns, like text. Max
# tiles is the maximum number of tiles. We need to recompute these values when
# smashing two geomorphs together.
has 'row';
has 'col';
has 'max_tiles';
sub init {
my $self = shift;
$self->dungeon_geomorph_size(3); # this stays the same
$self->dungeon_dimensions([3, 3]); # this will change
$self->room_dimensions([5, 5]);
$self->recompute();
}
sub recompute {
my $self = shift;
$self->row($self->dungeon_dimensions->[0]
* $self->room_dimensions->[0]
+ 4);
$self->col($self->dungeon_dimensions->[1]
* $self->room_dimensions->[1]
+ 4);
$self->max_tiles($self->row * $self->col - 1);
}
=head2 generate_map($pillars, $n, $caves)
If C<$pillars> is true, then rooms with pillars are generated. This is usually a
good idea. It's harder to pull off from I<Hex Describe> because the description
of the dungeon should mention the pillars but there's now way to do that.
Perhaps, if C<$pillars> were to be a reference of room numbers with pillars, it
might work; right now, however, it's simply a boolean value.
C<$n> is number of rooms.
If C<$caves> is true, then the entire map uses cave walls instead of regular
walls.
=cut
sub generate_map {
( run in 0.655 second using v1.01-cache-2.11-cpan-75ffa21a3d4 )