File Coverage

blib/lib/Games/Roguelike/Item.pm
Criterion Covered Total %
statement 44 68 64.7
branch 13 34 38.2
condition 3 9 33.3
subroutine 7 13 53.8
pod 6 6 100.0
total 73 130 56.1


line stmt bran cond sub pod time code
1 1     1   706 use strict;
  1         4  
  1         50  
2              
3             package Games::Roguelike::Item;
4              
5 1     1   6 use Games::Roguelike::Utils qw(:all);
  1         3  
  1         242  
6 1     1   7 use Games::Roguelike::Console;
  1         2  
  1         32  
7 1     1   5 use Games::Roguelike::Area;
  1         3  
  1         31  
8 1     1   4 use Carp qw(croak confess carp);
  1         1  
  1         811  
9              
10             our $AUTOLOAD;
11              
12             =head1 NAME
13              
14             Games::Roguelike::Item - Roguelike item object
15              
16             =head1 SYNOPSIS
17              
18             package myItem;
19             use base 'Games::Roguelike::Item';
20              
21             $i = myItem->new($area, sym=>'!', x=>5,y=>6); # creates an item at location 5, 6
22             # with symbol '!', inside area $area
23              
24             =head1 DESCRIPTION
25              
26             Item object used by drawing routines in Roguelke::Area
27              
28             =head2 METHODS
29              
30             =over 4
31              
32             =cut
33              
34             =item new($container, %opts)
35              
36             $container is usually an "area" or "mob" or another "item" object.
37              
38             At a minimum, it must support the additem and delitem methods.
39              
40             The "new" method automatically calls additem on the container.
41              
42             Options include:
43              
44             sym : symbol this item is drawn with
45             color : color this item is drawn with
46             x : map location of item
47             y : map location of item
48              
49             Other options are saved in the hash as "user defined" options.
50              
51             =cut
52              
53             sub new {
54 3     3 1 6 my $pkg = shift;
55              
56 3         5 my $cont = shift;
57              
58 3 50       17 croak("can't create item without container argument")
59             unless UNIVERSAL::can($cont, 'additem');
60            
61 3         6 my $self = {};
62              
63 3         6 $self->{sym}='$'; # default, just so there is one
64 3         6 $self->{color}='bold yellow'; # default
65              
66 3         13 while( my ($k, $v) = splice(@_, 0, 2)) {
67 24         76 $self->{$k} = $v;
68             }
69            
70 3         7 bless $self, $pkg;
71              
72 3         12 $cont->additem($self);
73              
74 3         11 return $self;
75             }
76              
77             =item x()
78              
79             =item y()
80              
81             Return the item's x/y members only if the item is in an ::Area object,
82              
83             Otherwise, return the container's x and y members.
84              
85             Direct access to the $item->{x}/{y} members is encouraged if you don't care how it's contained.
86              
87             =cut
88              
89             sub x {
90 0     0 1 0 my $self = shift;
91 0 0       0 if (!$self->{inarea}) {
92 0         0 return $self->{cont}->x;
93             }
94 0         0 return $self->{x};
95             }
96              
97             sub y {
98 0     0 1 0 my $self = shift;
99 0 0       0 if (!$self->{inarea}) {
100 0         0 return $self->{cont}->y;
101             }
102 0         0 return $self->{y};
103             }
104              
105             =item setcont(newcont)
106              
107             Sets the container for an item, returns 0 if it's already contained within that continer.
108              
109             Dies if the container has no {items} list (ie: can't contain things)
110              
111             ** Should only ever be called**
112             - by the container's "additem" method, and
113             - only if the container is derived from ::Area, ::Mob or ::Item.
114              
115             (This can & will be made generic at some point)
116              
117             =cut
118              
119             sub setcont {
120 3     3 1 10 my $self = shift;
121 3         5 my $cont = shift;
122              
123 3 50       13 confess("not an item") unless $self->isa('Games::Roguelike::Item');
124 3 50 33     22 confess("not an container") unless ref($cont->{items}) && UNIVERSAL::can($cont, 'additem');
125              
126 3 50       8 if ($cont) {
127 3 100 66     22 if (!defined($self->{cont}) || $cont != $self->{cont}) {
128 2 0       19 $self->{in} = $cont->isa('Games::Roguelike::Area') ? 'area'
    50          
    100          
129             : $cont->isa('Games::Roguelike::Mob') ? 'mob'
130             : $cont->isa('Games::Roguelike::Item') ? 'item' : 'void';
131              
132 2         6 $self->{"in" . $self->{in}} = 1;
133              
134             # for now, do this, until interface is better documented
135 2 50       7 die("item must be in an area, mob or another item as a container")
136             if $self->{invoid};
137              
138 2 50       7 $self->{cont}->delitem($self) if $self->{cont};
139 2         3 push @{$cont->{items}}, $self;
  2         6  
140 2         5 $self->{cont} = $cont;
141              
142 2 100       12 if ($self->{inarea}) {
143 1         2 $self->{r} = $cont;
144             } else {
145 1         3 $self->{r} = $cont->{r};
146             }
147              
148 2         7 return 1;
149             }
150 1         2 return 0;
151             } else {
152 0           return $self->{cont};
153             }
154             }
155              
156             # perl accessors are slow compared to just accessing the hash directly
157             # autoload is even slower
158             sub AUTOLOAD {
159 0     0     my $self = shift;
160 0 0         my $pkg = ref($self) or croak("$self is not an object");
161              
162 0           my $name = $AUTOLOAD;
163 0           $name =~ s/.*://; # strip fully-qualified portion
164 0 0 0       $name =~ s/^set// if @_ && !exists $self->{$name};
165              
166 0 0         unless (exists $self->{$name}) {
167 0           croak "Can't access `$name' field in class $pkg";
168             }
169              
170 0 0         if (@_) {
171 0           return $self->{$name} = $_[0];
172             } else {
173 0           return $self->{$name};
174             }
175             }
176              
177 0     0     sub DESTROY {
178             }
179              
180             =item additem (item)
181              
182             Add item to reside within me. Override this to make backpacks, etc.
183              
184             Return value 0 = can't add, too full/or not a backpack
185             Return value 1 = add ok
186             Return value -1 = move occured, but not added
187              
188             Default implementation is to return "0", cannot add.
189              
190             =cut
191              
192             sub additem {
193 0     0 1   my $self = shift;
194 0           return 0; # i'm not a backpack
195             }
196              
197             =item delitem (item)
198              
199             Deletes item from within me. Override this to make backpacks, etc.
200              
201             =cut
202              
203             sub delitem {
204 0     0 1   my $self = shift;
205 0           croak("this should never be called, since additem always returns 0");
206             }
207              
208             =back
209              
210             =head1 SEE ALSO
211              
212             L
213              
214             =cut
215              
216             1;