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

NAME

Games::Roguelike::Area - Roguelike area map

SYNOPSIS

 package myArea;
 use base 'Games::Roguelike::Area';

 $a = myArea->new(w=>80,h=>50);                                 # creates an area with specified width/height
 $a->generate('cavelike');                                              # make a cavelike maze
 $char = Games::Roguelike::Mob->new($a, sym=>'@');              # add a mobile object with symbol '@'

DESCRIPTION

Library for loading or generating mazes, managing items/mobs

        * assumes the user will be using overridden Games::Roguelike::Mob's as characters in the game
        * provides a flexible load() function
        * contains an array of 'features', which can be named, searched for and positioned

METHODS

new(OPT1=>VAL1, OPT2=>VAL2...)

Options can also all be set/get as class accessors:

        world => undef,                 # world this area belongs to (optional container which can "addarea")
        name => '',                     # name of this level/area (required if world is specified)
        map => []                       # double-indexed array of map symbols 
        color => []                     # double-indexed array of strings (used to color map symbols)
        mobs => [],                     # list of mobs
        items => [],                    # list of items

 # These will default to the world defaults, if world is set

        w=>80, h=>40,                   # width/height of this area
        debugmap => 0,                  # turn on map coordinate display
        memcolor => 'gray',             # color drawn when an area is not in sight

 # These vars, or the world defaults (if a world is defined)
 # are used by map-making, pathfinding and field-of view, rather than using hooks
 # specifically because function calling seems to slow things down

        wsym => '#',                    # default wall symbol
        fsym => '.',                    # default floor symbol
        dsym => '+',                    # default door symbol
        noview => '#+',                 # list of symbols that block view
        nomove => '#',                  # list of symbols that block movement   
        
getmapsym ($x,$y)
getmapcolor ($x,$y)
setmap ($x,$y, $sym [,$color])

Raw accessors may be subject to change in future versions, but are much faster.

 $area->{map}[$x][$y] = $sym, 
 $area->{color}[$x][$y] = $color

Function accessors will always work, but are slower:

 $sym=$area->getmapsym($x,$y) 
 $color=$area->getmapcolor($x,$y) 
 $area->setmap($x,$y, $sym [,$color]);

If you're looping over the whole map, you can use foreachmap().

etcetera.

rpoint ()

Returns a random point as an X/Y array, that's within the map, and not on the edge..

rpoint_empty ()

Returns a random point that's empty (eiher the symbol is ''' or is undefined)

findpath(x1, y1, x2, y2)

Returns 1 if there is a path from x1,y2 to x2,y2. Uses "nomove" member as the list of symbols that cannot be moved through.

findclose(x1, y1, x2, y2)

Returns the closest you can get to x2,y2 from x1,y2 without going through a "nomove" symbol.

Return value is (X,Y) array, or undefined if there's no path.

maxcardinal ()

Maximum point someone can walk from x/y in each of 4 cardinal directions, returned as an array of XY arrays.

Array is sorted n,s,e,w.

digone (x, y, $ws, $fs)

"Digs" one square of the map, at position x,y - turning it into a "floor", while also turning the surrounding areas into "walls", if they are currently not assigned.

Optionally can specify wall & floor symbols (or uses area defaults).

Does nothing if the map symbol at x,y is not a wall or void.

Returns the number of walls that the new point is surrounded by or -1 if the point was off the map.

nexttosym(x, y, sym)

Returns a direction if x,y are adjacent to sym, otherwise returns undef.

okdoor(x, y)

Looks at the clockwize adjacent symbols for an alternating pattern of walls and floors, to see if a door would be meaningful.

Uses {nomove} as the list of "wall" symbols.

makepath(x1, y1, x2, y2)

Drill a right-angled corridor between 2 nonempty points using digone().

** Notably the whole auto-door upon breaking into an open area doesn't always work right, and should.

makepath2 (x1, y1, x2, y2)

Like makepath, but diagonal and with no doors.

findfeature (symbol)

Searches "map feature list" for the given symbol, returns coordinates if found.

addfeature (symbol [, x, y])

Adds a symbol to the map (to a random open floor point if one is not specified), and also adds it to the searchable "feature list".

inbound(x, y)

Returns true if x >= 0 and x < $self->{w} and y >= 0 and y < $self->{h}.

generate ($type [, options ... ])

This calls "$type::generate" if it is defined, perhaps in the caller's package, etc.

Predefined types are "Rooms", "Cavelike" and "Maze" (see below).

If no "::" is present, 'Games::Roguelike::Area::' is prepended, and the first character is propercased.

If &{"$type::generate"} is not defined, it will require "$type" and then try again.

Assuming there is no function named "wilderness::generate", then the following are roughly equivalent:

 $self->generate('Games::Roguelike::Area::Rooms');
or
 $self->generate('rooms');  
or
 Games::Roguelike::Area::Rooms::generate($self);
or
 $self = new Games::Roguelike::Area::Rooms; $self->generate();

Additonal options are passed to the generate function. Generate functions should support named parameters..

Common option is a "with=>[feature1, feature2]" feature list, that get added to empty floor map locations, and appended to the map's feature list.

Height, width are taken from the area object.

generate('cavelike', [with=>[sym1[,sym2...]])

Makes a random map with a bunch of cave-like rooms connected by corridors.

Can specify a list of symbols to be added as "features" of the map.

generate ('rooms', [with=>[sym1[,sym2...]])

Makes a random nethack-style map with a bunch of rectangle rooms connected by corridors

If you specify a "with" list, it puts those symbols on the map in random rooms, and calls "addfeature" on them.

generate('maze', rand=>number, with=>feature-list)

Generate a tight, difficult maze. Rand defaults to 5 (higher numbers are less random).

foreachmap (code-reference [,noborder=>1] [,border=>1])

Loops over each map location, and calls the code with parameters x, y and map-symbol.

Option "border" calls the code only for border (edge) squares.

Option "noborder" calls the code for everything but border (edge) squares.

draw ({dispx=>, dispy=>, vp=>, con=>});

Draws the map using offset params dispx, dispy,disph,dispw,

Uses the perspective of $vp (viewpoint), if specified. $vp can contain an x, y coordinate and a "pov" integer which is the maximum sight distance.

Uses the console $con to draw the map.

Uses the algorithm provided by the "checkpov" function for field of view calculations.

Usually done after each move.

mobat (x, y)

Returns a single mob located at x/y, or undef if none is there.

items ([x, y])

Returns reference to array of items located at x/y, or reference to array of all items if no x/y is supplied.

mobs ([x, y])

Returns reference to array of all mobs located at x/y, or all mobs if no x/y is supplied.

checkpov (vp, x, y)

Returns 1 if the $vp object (something that has an x, a y and a pov) can see x/y.

Uses the "noview" area variable to determine what can be seen through.

checkmap (vp, x, y, sym)

Returns 1 if the $vp mob can see x/y, 2 if $vp has a memory of x/y, and also memorizes x/y if it can be seen by adding it to the vp's "memory" variable..

Uses the "noview" area variable to determine what can be seen through.

addmob (mob)

Adds a mob to the area, unless it's already in it.

delmob (mob)

Removes mob from the area.

findrandmap (symbol[, mobok=0])

Finds a random map location containing symbol (if mobok is not set, then it won't returns locations that have mobs).

dump

Prints map to stdout, without mobs and items. For a more flexible approach, create a ::Console::Dump object and call draw() using it.

additem (item)

Adds item to floor. Override this to add floor full messages, etc.

Return value 0 = can't add, too full Return value 1 = add ok Return value -1 = move occured, but not added

If the item doesn't have an {x} and {y} value then the item is added to a random location.

delitem (item)

Removes item from the area.

load (file | options)

Loads an area from a file, which is a perl program that sets these vars:

 $map           : 2d map as one big string
 or $yxarray    : 2d map as y then x indexed array
 %key           : for each symbol in the map *optionally* provide:
        color   - color of that symbol
        sym     - real symbol to use
        feature - name of feature for feature table, don't specify with class!
        class   - optional package to use for "new", passed the area itself as the first argument to new
        lib     - look up item or mob from library

 %lib           : hash of hashes, used to populate items or monsters - as needed

Alternatively, these can be passed as named options to the load function.

The map system knows very little about game semantics. It's merely a way of loading maps made of symbols - some of which may correlate to perl objects. The tictactoe example script uses the map load system.

'>', and '<' are assumed to be "stair features" unless otherwise specified.

Objects can be looked up by name from the item library instead of specified in full.

At a minimum, classes must add themselves, somehow, to the area object when new is called.

  The example below loads a standard map, with blue doors, 2 mobs and 1 item

  One mob is loaded via a package "mymonster", and is passed "hd" & "name" parameters,
  in addition to the "x", "y" and "sym" parameters which are derived from its location.

  The other mob is loaded from the library named "blue dragon", and has it's "name" and "hp" 
  parameters modified.

About lib entries:

If a key entry has a "lib", it's assumed to the be the name of an entry in the lib hash.

The lib hash is then looked up and has its values copied into the key entry before using the key entry.

"lib" entries can be recursive.

The "lib" can be loaded from an external shared file, so multiple maps can use the same "lib".

About items:

The "items" member of an object (mob or backpack), if it is an array reference, will be auto-expanded by creating an item object for each array member with the parent object set as the first, unnamed, argument to new.

If a member of the items array is a hash ref, it's treated like a key entry. If it's a scalar string, it's equivalent to {lib=>'string'}.

If there's no class set within an item, a warning is emitted.

EXAMPLE 1:

 $map = '
 ##########
 #k <+  ! #
 ######## #
 #>  D    #
 ##########
 ';

 %key = (
        'k'=>{class=>'mymonster', type='kobold', name=>'Harvey', hd=>12, 
              items=>['potion of healing',
                      {class=>'myweapon', name=>'Blue Sword', hd=>9, dd=>4, drain=>1, glow=>1}
                     ]
             },
        '!'=>{lib=>'potion of speed'},
        'D'=>{lib=>'blue dragon', name=>'Charlie', hp=>209},
        '+'=>{color=>'blue'}
       );

 %lib = (
        'potion of speed'=>{class=>'myitem', type=>'potion', effect=>'speed', power=>1},        
        'blue dragon'=>{class=>'mymob', type=>'dragon', breath=>'lightning', hp=>180, hd=>12, at=>[10,5], dm=>[5,10], speed=>5, loot=>4},
       );

  $area->load(map=>$map, key=>%key, lib=>\%lib);

EXAMPLE 2:

 use Games::Roguelike::Caves;
 my $yx = generate_cave($r->{w},$r->{h}, 12, .46, '#', '.');
 $area->load(yxarray=>$yx);

SEE ALSO

Games::Roguelike::World, Games::Roguelike::Mob, Games::Roguelike::Console

AUTHOR

Erik Aronesty earonesty@cpan.org

LICENSE

This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

See http://www.perl.com/perl/misc/Artistic.html or the included LICENSE file.