5 use experimental 'switch';
6 use lib 'lib'; # make runnable for simple cases
9 use Getopt::Long 2.33 qw(HelpMessage :config bundling);
10 use Games::Wormy::TICalcLevels;
11 use Games::Wormy::WormEdit;
13 our $VERSION = '1.07';
16 'format|f=s', # output type
17 'raw|r!', # compatibility for yaml format
18 'version=i', # force version
19 'levels|render:i', # image of level(s)
20 'output|o=s', # output file
21 ) or HelpMessage(-exitval => 2);
22 $opt{format} //= 'yaml' if $opt{raw};
23 $opt{format} //= 'pnm' if defined $opt{levels};
25 my @OBJTYPE = ('none', 'line', 'fat line', 'bar', 'circle');
26 my @ENDTYPE = ('none', 'message', 'small message');
30 my @objtypes = map { $_->{type} } @$objects;
32 $count{$_}++ for @objtypes;
33 return (@objtypes > 1 && keys %count == 1 && 'all ') . join(', ',
34 map { $OBJTYPE[$_] ? $OBJTYPE[$_] . ($count{$_} > 1 && 's') : $_ }
39 # read and parse all input data
42 my $rawdata = readline;
43 if (substr($rawdata, 0, 11) eq "**TI86**\032\012\000") {
44 # compiled calculator file
45 $data = Games::Wormy::TICalcLevels->read($rawdata, $opt{version});
47 elsif (substr($rawdata, 0, 8) eq 'WormEdit') {
48 # original wormedit source
49 $data = Games::Wormy::WormEdit->read($rawdata, $opt{version});
52 die "Unrecognised file type\n";
55 my $format = $opt{format}; # override distinct from image fallback
57 # derive format from file extension
58 $format //= $1 if $opt{output} =~ /\.([^.]+)$/;
60 if ($format ~~ [qw{ yaml json txt }]) {
61 # redirect standard output to given file
62 open my $output, '>', $opt{output}
63 or die "Cannot output to '$opt{output}': $!";
67 # images are written directly to file
74 # output with user-preferred formatting
78 say JSON->new->encode($data);
81 # full data in yaml (human-readable) formatting
83 local $YAML::CompressSeries;
84 $YAML::CompressSeries = 0;
85 my $yml = "# Wormy levelset\n" . YAML::Dump($data);
87 # inline format of short hashes
89 ^(\ *) - \n # array indicator
90 ((?:\1\ \ [a-z0-9]{1,5}:\ *\d+\n)+) # simple hash declaration
91 (?!\1\ ) # no further children
93 my ($indent, $value) = ($1, $2);
97 "$indent- {$value}\n";
104 print " ($data->{description})" if defined $data->{description};
106 printf "File version: %s\n", "$data->{format} v$data->{version}";
107 printf "Defaults: %s\n", join('; ',
108 $data->{sprite} ? 'sprite ' . scalar @{ $data->{sprite} } : (),
109 defined $data->{hiname} ? 'hiscore by ' . $data->{hiname} : (),
113 for my $variant (qw/single peaworm multi race ctf/) {
114 my $count = $data->{levelcount}->{$variant};
115 defined $count or next;
117 printf '%s (%s)', ucfirst $variant, $count;
120 for (0 .. $count - 1) {
121 my $level = $data->{levels}->[$_ + $startnr];
122 printf("\n- %-22s%4s:%3s+%2s%3s %3sx%-3s%s",
123 $level->{id} || $level->{name} || '#'.($_+1),
124 @$level{qw/size bsize growth/},
125 $variant eq 'single' && "x$level->{peas}",
126 @$level{qw/width height/},
127 join(';', map {" $_"} grep {$_}
128 @{$level->{objects}} && sprintf('%2d object%s (%s)',
129 scalar @{$level->{objects}}, @{$level->{objects}} != 1 && 's',
130 objsummary($level->{objects}),
132 $level->{sprite} && @{$level->{sprite}} && sprintf('sprite %d',
133 scalar @{$level->{sprite}},
135 $level->{balls} && @{$level->{balls}} && sprintf('%d bounc%s',
136 scalar @{$level->{balls}}, @{$level->{balls}} == 1 ? 'y' : 'ies',
144 printf("-- %-21s%4s: %s (%s)\n",
146 defined $data->{finish}->{code}
147 ? length $data->{finish}->{code} : '?',
148 defined $data->{finish}->{type}
149 ? $ENDTYPE[$data->{finish}->{type}] || 'unknown' : 'code',
150 $data->{finish}->{message} // '?',
151 ) if $variant eq 'single';
156 require Games::Wormy::Render;
160 # find all numeric values in argument
161 @request = $opt{levels} =~ /(\d+)/g;
164 # default to all levels
165 @request = 0 .. $data->{levelcount}->{total} - 1;
167 @request or die "no levels found or specified\n";
169 my $img = Games::Wormy::Render->composite(
170 map { $data->{levels}->[$_] } @request
171 ) or die "empty result for levels\n";
172 if ($format ~~ 'pbm') {
173 $img = $img->to_paletted({make_colors => 'mono'});
174 $opt{format} = 'pnm';
177 $opt{output} ? (file => $opt{output}) : (fh => \*STDOUT),
178 type => $opt{format},
179 ) or die $img->errstr;
187 parse-wormedit - Wormy level data parser
191 parse-wormedit [--format=<type>] [--level=<number>] [--output=<file.ext>] <input.lvl>
195 Reads Wormy levels (either original WormEdit source or compiled TI-86 string)
196 from STDIN or given file, and prints parsed data to STDOUT.
198 If an I<output> file name is given, its extension determines the format,
199 otherwise explicitly given by the I<format> option:
205 Plain text summary of levelpack contents.
209 All parsed data in YAML syntax.
213 Parsed data in JSON syntax.
215 =item pnm, png, bmp, ...
217 Image drawing of rendered levels.
218 Unrecognised values are interpreted as file type and converted by Imager.
224 Mischa POSLAWSKY <wormy@shiar.org>