File Coverage

blib/lib/Games/RolePlay/MapGen/Exporter/XML.pm
Criterion Covered Total %
statement 10 12 83.3
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 14 16 87.5


line stmt bran cond sub pod time code
1             # vi:tw=0 syntax=perl:
2              
3             package Games::RolePlay::MapGen::Exporter::XML;
4              
5 2     2   13 use common::sense;
  2         3  
  2         19  
6 2     2   108 use Carp;
  2         4  
  2         181  
7 2     2   1909 use Tie::IxHash;
  2         32440  
  2         97  
8 2     2   988 use XML::Simple;
  0            
  0            
9              
10             1;
11              
12             # new {{{
13             sub new {
14             my $class = shift;
15             my $this = bless {o => {@_}}, $class;
16              
17             return $this;
18             }
19             # }}}
20             # go {{{
21             sub go {
22             my $this = shift;
23             my $opts = {@_};
24              
25             for my $k (keys %{ $this->{o} }) {
26             $opts->{$k} = $this->{o}{$k} if not exists $opts->{$k};
27             }
28              
29             croak "ERROR: fname is a required option for " . ref($this) . "::go()" unless $opts->{fname};
30             croak "ERROR: _the_map is a required option for " . ref($this) . "::go()" unless ref($opts->{_the_map});
31              
32             my $map = $this->genmap($opts);
33             unless( $opts->{fname} eq "-retonly" ) {
34             open my $out, ">$opts->{fname}" or die "ERROR: couldn't open $opts->{fname} for write: $!";
35             print $out "\n\n";
36             print $out "\n\n";
37             print $out "\n", $map;
38             close $out;
39             }
40              
41             return $map;
42             }
43             # }}}
44             # genmap {{{
45             sub genmap {
46             my $this = shift;
47             my $opts = shift;
48             my $m = $opts->{_the_map};
49             my $g = $opts->{_the_groups};
50              
51             my $options = [];
52             my $groups = [];
53             my $map = [];
54              
55             my $ah = sub { my %h; tie %h, "Tie::IxHash", (@_); \%h };
56              
57             # options {{{
58             my $sort_opts = sub {
59             my ($c, $d) = map {ref $opts->{$_} ? 1:0} $a, $b;
60              
61             # warn "sorting ($a, $b, $c, $d)";
62              
63             return $c <=> $d if ($c + $d) == 1;
64             return $a cmp $b;
65             };
66              
67             for my $k (sort $sort_opts keys %$opts) {
68             unless( $k =~ m/^(?:_.+?|objs|plugins)$/ ) {
69             my $v = $opts->{$k};
70              
71             if( my $t = ref $v ) {
72             next if $t ne "HASH"; # probably a r_cb => sub {} code ref from XMLImporter
73              
74             push @$options, $ah->( name=>$k, value=>join(" ", map { "$_: $v->{$_};" } sort keys %$v ));
75              
76             } else {
77             push @$options, $ah->( name=>$k, value=>$v );
78             }
79             }
80             }
81             # }}}
82             # groups {{{
83             for my $g (@{ $opts->{_the_groups} }) {
84             push @$groups, $ah->(
85             name => $g->{name},
86             type => $g->{type},
87             rectangle => [map {
88             $ah->(
89             loc => join(",", @{ $g->{loc}[$_] }),
90             size => join("x", @{ $g->{size}[$_] }),
91             )
92             } 0 .. $#{ $g->{loc} }],
93             );
94             }
95             # }}}
96              
97             my $iend = $#{ $opts->{_the_map} };
98             for my $i (0 .. $iend) {
99             my $jend = $#{ $opts->{_the_map}[$i] };
100             my $row = $ah->( ypos=>$i, tile=>[] );
101              
102             for my $j (0 .. $jend) {
103             my $tile = $opts->{_the_map}[$i][$j];
104              
105             my $h;
106             if( my $t = $tile->{type} ) {
107             my $closures = [];
108              
109             $h = $ah->(
110             xpos => $j,
111             type => $tile->{type},
112             );
113              
114             for my $dir (qw(north south east west)) {
115             my $d = substr $dir, 0, 1;
116             my $o = $tile->{od}{$d};
117              
118             if( $o == 1 ) {
119             # open -- so don't make it show a closure
120              
121             } elsif( $o > 1 ) {
122             my $door = $tile->{od}{$d};
123              
124             push @$closures, $ah->( dir => $dir, type => "door",
125             (map { $_ => $door->{$_} ? "yes" : "no" } qw(locked stuck secret open)),
126              
127             (map { $_."_open_dir" => {n=>"north", e=>"east", s=>"south", w=>"west"}->{$door->{open_dir}{$_}} } qw(major minor)),
128             );
129              
130             } else {
131             push @$closures, $ah->( dir => $dir, type => "wall" );
132             }
133             }
134              
135             $h->{closure} = $closures if int @$closures;
136              
137             push @{ $row->{tile} }, $h;
138              
139             } else {
140             push @{ $row->{tile} }, $h = {xpos=>$j, type=>"wall"}; # this didn't used to be here... it made parsing craptastic
141             }
142              
143             $opts->{t_cb}->( ($j+1,$i+1), $h ) if exists $opts->{t_cb};
144             }
145              
146             push @$map, $row if int @{$row->{tile}}
147             }
148              
149             my %main; tie %main, "Tie::IxHash", (
150             option => $options,
151             tile_group => $groups,
152             'map' => { row => $map },
153             );
154              
155             return XMLout(\%main,
156             RootName => "MapGen",
157             NoSort => 1, # IxHash does this, please don't help me, kthx
158             );
159             }
160             # }}}
161              
162             __END__