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 )