The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

Game::TextPatterns - generate patterns of text

SYNOPSIS

  use Game::TextPatterns;

  my $pat = Game::TextPatterns->new( pattern => ".#\n#." );

  $pat->multiply(7,3)->border->border(1, '.')->border;

  print $pat->string;

Ta-da! You should now have an Angband checker type vault. (Doors not included. Items and monsters may cost extra.)

  ####################
  #..................#
  #.################.#
  #.#.#.#.#.#.#.#.##.#
  #.##.#.#.#.#.#.#.#.#
  #.#.#.#.#.#.#.#.##.#
  #.##.#.#.#.#.#.#.#.#
  #.#.#.#.#.#.#.#.##.#
  #.##.#.#.#.#.#.#.#.#                       @
  #.################.#
  #..................#
  ####################

Items might be added by applying an appropriate mask:

  my $i = Game::TextPatterns->new( pattern => "." );
  $i->multiply( 19, 11 );
  $i->white_noise( '?', .1 );
  $pat->mask( '.', $i );
  print $pat->string;

Which could result in

  ####################
  #.?..............?.#
  #.################.#
  #.#.#.#.#.#.#.#.##.#
  #?##.#.#.#.#.#.#.#.#
  #.#.#.#.#.#.#?#.##?#
  #.##.#?#.#.#.#.#.#.#
  #.#.#?#.#.#.#.#.##.#                  #######
  #.##.#.#.#.#.#.#.#.#                  .@...<#
  #.################.#                  #######
  #.?....?.?.........#
  ####################

And this pattern adjusted with four_up, twice

  $pat = Game::TextPatterns->new( pattern => <<"EOF" );
  ..##.
  ...##
  #....
  ##..#
  .#.##
  EOF
  print $pat->four_up->four_up->string;

creates

  .#.##..##..#.##..##.
  ##..#...####..#...##
  #....#....#....#....
  ...####..#...####..#
  ..##..#.##..##..#.##
  ##.#..##..##.#..##..
  #..####...#..####...
  ....#....#....#....#
  ##...#..####...#..##
  .##..##.#..##..##.#.
  .#.##..##..#.##..##.
  ##..#...####..#...##
  #....#....#....#....
  ...####..#...####..#
  ..##..#.##..##..#.##
  ##.#..##..##.#..##..
  #..####...#..####...
  ....#....#....#....#
  ##...#..####...#..##
  .##..##.#..##..##.#.

Consult the eg/ and t/ directories under this module's distribution for more example code.

DESCRIPTION

Game::TextPatterns contains methods that generate and alter text patterns. Potential uses include the creation of ASCII art or the construction of vaults for roguelike games.

Terminology

Columns (x, width) and Rows (y, height) are used in various places.

    columns ...
  r 
  o  ###%#######+######
  w  #...the.pattern..#
  s  #######+##########
  .  #........#.......#
  .  #.......@'...<...#
  .  ##################

The pattern text should be ASCII; Unicode or other such multibyte encodings may cause problems.

Geometrical terms (quadrant I or Q1 in the following diagram) are used, though for angles of rotation 0 1 2 3 are used instead of 0, 90, 180, 270 degress or other forms.

     90 (1)
  Q2 | Q1
  ---+--- 0 (0)
  Q3 | Q4
     270 (3)

CONSTRUCTORS

These return new objects. Some require an existing object that probably should not be the same as the object being operated on. If something goes wrong they will throw an exception.

clone

Returns a new object from an existing one with the current state of the pattern attribute.

new pattern => ...

Constructor. A pattern attribute must be specified.

rebuild

MooX::Rebuild feature that returns a new object with the original pattern attribute.

ATTRIBUTES

Only one at the moment.

pattern

Required. Must be a string (which will be split on $/ into an array reference) or an array reference of strings or an object that has a pattern method that does the same thing as pattern of this module.

File::Slurper may help read pattern data directly from a file.

pattern can be called as a method to return the current pattern as an array reference. It may be a bad idea to modify the contents of that reference directly.

METHODS

Call these on something returned by a constructor. Those that modify the pattern in-place (some though do not) can be chained with other methods. If something goes wrong these will throw an exception.

append_cols fill pattern

Appends the given pattern to the right of the existing object (or a sort of a horizontal cat(1)). If the patterns are of unequal size the fill character (or array reference) will be used to fill in the gaps. If fill is an array reference the first character of that reference will be used to fill gaps should the object be smaller, or otherwise the second character of the array will be used as fill if the object is larger than the given pattern.

append_rows fill pattern

Appends the given pattern below the existing object (much like cat(1) does for text). Same rules for fill as for append_cols.

as_array

Returns the pattern of the object as a reference to a 2D array. Presumably useful for some other interface that expects a 2D grid. See also from_array.

border width character

Creates a border of the given width (1 by default) and character (# by default) around the pattern.

cols

Returns the width (x, or number of columns) in the pattern. This is based on the length of the first line of the pattern.

crop point1 point2

Crops the pattern to the given column and row pairs, which are counted from zero for the first row or column, or backwards from the end for negative numbers. Will throw an error if the crop values lie outside the size of the pattern.

See also trim.

dimensions

Returns the cols and rows of the current pattern.

draw_in point1 [ point2 ] pattern

Draws the pattern within the given bounds, though will not extend the dimensions of the object if the pattern exceeds that (hence the lower right bound being optional). Should the pattern be smaller than the given bounds nothing will be changed at those subsequent points (this differs from other methods that accept a fill argument).

See also the more complicated overlay.

fill_4way point char

Replaces the character found at point with char and repeats this fill for all similar characters found by 4-way motion from the starting point.

fill_8way point char

Replaces the character found at point with char and repeats this fill for all similar characters found by 8-way motion from the starting point.

flip_both

Flips the pattern by columns and by rows. Similar to a rotate by 180 degrees.

  ###.  ->  ...#
  #...  ->  .###
flip_cols

Flips the columns (vertical mirror) in the pattern.

  ###.  ->  .###
  #...  ->  ...#
flip_four [ reduce-col? [ reduce-row? ] ]

Treats the object as a pattern in quadrant I of the unit circle and returns a new object with that pattern flipped as appropriate into the other three quadrants. See also four_up.

      ###.
      #... becomes:
  
  .######.
  ...##...
  ...##...
  .######.

Note that this does not modify the object in-place, to do that:

  $pat = $pat->flip_four;

The optional reduce-col and reduce-row will cause a row, a column, or if only reduce-col is supplied and is true, both a row and a column to be lost. That is flip_four(1) causes

     ###.
     #... to become
  
  .#####.
  ...#...
  .#####.
flip_rows

Flips the rows (horizontal mirror).

  ###.  ->  #...
  #...  ->  ###.
four_up [ fill ] [ crop? ]

Treats the object as a pattern in quadrant I of the unit circle and returns a new object with that pattern rotated into the other three quadrants by an appropriate number of degrees. See also flip_four.

      ###.
      #... becomes:
  
  ??..????
  ??#.????
  ??#.###.
  ??###...
  ...###??
  .###.#??
  ????.#??
  ????..??

fill will be used if the input is not a square during various calls to append_cols and append_rows, unless crop is a true value, in which case the object used will be cropped to be a square before the rotations. The default fill as shown above is ?.

Note that this does not modify the object in-place.

from_array array

Replaces the pattern of the object with the contents of the given 2D array. See also as_array.

mask char pattern

mask replaces instances of the char in the object with the corresponding character(s) of the given pattern.

multiply cols [ rows ]

Multiplies the existing data in the columns or rows, unless cols or rows is 1. With no rows set multiplies both the columns and rows by the given value.

overlay point pattern mask

Draws the pattern into the object at the given point though preserving anything from the original object that match the mask character in the pattern.

See also the simpler draw_in.

rows

Returns the height (y, or number of rows) in the pattern.

rotate amount

Rotates the pattern by 0, 90, 180, or 270 degrees specified by the integers 0, 1, 2, and 3 (or modulus of those).

randomly match percent callback

Similar to white_noise but calls a callback function for each matching cell randomly found. For example to act on 10% of cells that match # use

    use constant { ROW => 1, COL => 0, };
    $m->randomly(
        qr/#/, 0.1,
        sub {
            my ($pat, $point, $max_cols, $max_rows) = @_;
            substr $pat->[$point->[ROW]], $point->[COL], 1, 'x';
        }
    );

as internally the pattern is stored as an array of strings.

string sep

Returns the pattern as a string with rows joined by the sep value ($/ by default which typically is but may not be a newline).

trim amount

Convenience method for crop( [amount,amount], [-amount,-amount] ).

white_noise char percent

Fills the object with the given percentage of the char randomly.

    # 50% fill with 'x'
    $v->white_noise( 'x', .5 );

See randomly for a similar routine to this one, if more complicated.

BUGS

Reporting Bugs

Please report any bugs or feature requests to bug-game-textpatterns at rt.cpan.org, or through the web interface at http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Game-TextPatterns.

Patches might best be applied towards:

https://github.com/thrig/Game-TextPatterns

Known Issues

Probably should have used a 2D array instead of an array of strings, internally. But that is very unlikely to change at this point.

Probably needs more tests for various edge conditions.

flip_four and four_up probably need better names.

Some of the calling arguments to various methods likely need improvements which will probably break backwards compatibility.

Humans are really good at mixing up the col,row (x,y) points with other forms especially given the different orientation of the internal pattern. Favor non-square patterns for tests to better expose such mixups.

Unicode is not really supported; would instead need to operate on characters or potentially even allow for lengths of text in each cell of the pattern grid (but that gets back to the array of strings thing, above).

SEE ALSO

Game::DijkstraMap can path-find across text patterns, handy if one desires maps that do not completely thwart a player.

  use 5.24.0;
  ...
  $pat = $pat->four_up->four_up;
  my $dm = Game::DijkstraMap->new;
  $dm->map( $pat->as_array );
  # assuming the pattern did not have any goals already on it
  my $uc = $dm->unconnected;
  $dm->update( [ $uc->[0]->@*, $dm->min_cost ] );
  $dm->recalc;
  # then check if anything still unconnected...

Another option might be to use a standard image library and then devise a conversion such that particular colors become particular ASCII symbols (or combinations of symbols, with Unicode or control sequences to set colors or such).

Game::PlatformsOfPeril has some levels built with this module.

And then there is also the https://github.com/thrig/ministry-of-silly-vaults/

AUTHOR

thrig - Jeremy Mates (cpan:JMATES) <jmates at cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2018 by Jeremy Mates

This program is distributed under the (Revised) BSD License: http://www.opensource.org/licenses/BSD-3-Clause