ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/adm/map_info
Revision: 1.1.1.1 (vendor branch)
Committed: Fri Feb 3 07:14:15 2006 UTC (18 years, 3 months ago) by root
Branch: UPSTREAM, MAIN
CVS Tags: LAST_C_VERSION, rel-2_82, rel-2_81, rel-2_80, UPSTREAM_2006_03_15, rel-3_1, rel-3_0, rel-2_6, rel-2_7, rel-2_4, rel-2_5, rel-2_2, rel-2_3, rel-2_0, rel-2_1, rel-2_72, rel-2_73, rel-2_71, rel-2_76, rel-2_77, rel-2_74, rel-2_75, rel-2_54, rel-2_55, rel-2_56, rel-2_79, rel-2_52, rel-2_53, rel-2_32, UPSTREAM_2006_02_22, rel-2_90, rel-2_92, rel-2_93, rel-2_78, rel-2_61, UPSTREAM_2006_02_03, difficulty_fix_merge_060810_2300, rel-2_43, rel-2_42, rel-2_41, HEAD
Branch point for: difficulty_fix
Changes since 1.1: +0 -0 lines
Log Message:
initial import

File Contents

# Content
1 #!/usr/bin/perl
2 #
3 # This program is meant to use check crossfire (version 0.90.?) maps.
4 # Program wanderers through mapfiles and reports all objects that
5 # can't be found in the archetypes, all exit that doesn't lead to
6 # anywhere and all corrupted mapfiles.
7 #
8 # By: Tero Haatanen <Tero.Haatanen@lut.fi>
9 #
10 # Usage: wanderer.pl directory
11
12 # Set if you want to get warnings about spikes, gates, buttons, et al that
13 # are not connected. This can be annoying at times, since many maps use
14 # these objects for decorations.
15 $CONNECTED = 0;
16 $LIB = "/export/home/crossfire/cf-installroot/share/crossfire";
17 $ARCH = "$LIB/archetypes";
18 $BMAPS = "$LIB/bmaps";
19 $ANIM = "$LIB/animations";
20 $MAPS = "$LIB/maps";
21 # Set VERBOSE=1 if you want more output
22 $VERBOSE=0;
23 $SHOW_UNUSED = 0;
24
25 if (! $ARGV[0]) {
26 print "Using $MAPS are starting map directory.\n";
27 $STARTING = $MAPS;
28 } else {
29 $STARTING = $ARGV[0];
30 }
31
32
33 # read filenames to @maps
34 chdir ($STARTING);
35 while ($area = shift) {
36 &maplist ($area);
37 }
38
39 $* = 1; # use multiline matches
40
41 &faces;
42 &animations;
43 # read archetypes
44 &archetypes;
45
46
47 %ex = &collect ('^type 66$'); # type 66 == exit
48 %tele = &collect ('^type 41$'); # type 41 == teleport
49 %conn = &collect ('^type (17|18|26|27|29|30|31|32|91|92|93|94)$');
50 delete $conn{"spikes_moving"};
51 delete $conn{"magic_ear"};
52 %players = &collect ('^type 1$'); # type 1 == player
53 #
54 # In theory, I don't think any of these should show up in maps.
55 # For now, I mostly ignore them so I can more easily check out the
56 # editor directory and verify everything is in place.
57 %abilities = &collect('^type (2|10|11|12|19|25|43|44|49|50|52|88|97|110|114|121|141|151)$');
58
59 # check exits from archetypes
60 foreach $a (keys (%ex), keys (%tele)) {
61 if ($arches {$a} =~ /^food -?\d+$/) {
62 print "Warning: Archetype $a has food field.\n";
63 }
64 }
65
66 # some general info
67 print "=" x 70, "\n";
68 print "Number of mapfiles = " , @maps + 0, "\n";
69 print "Number of archetypes = " , values(%arches)+0, ":\n";
70 print " - Exits (" , values(%ex)+0, ")\n";
71 print " - Teleports (" , values(%tele)+0, ")\n";
72 print " - Connected objects (", values(%conn)+0, ")\n";
73 print " - Players (" , values(%players)+0, ")\n";
74 print "=" x 70, "\n";
75
76 # check maps
77 while ($file = shift (@maps)) {
78 &readmap;
79 }
80
81 # summary of missing archetypes
82 if (%missing) {
83 print "=" x 70, "\n";
84 print "Missing archetypes: ", join (", ", sort keys (%missing)), "\n";
85 }
86 # if you don't want list of used objects, uncomment next line
87 # and you can comment also last line check_obj
88 # (This isn't very useful, but maybe tells something)
89
90 #exit;
91
92 #&print_usage();
93
94 if ($SHOW_UNUSED) {
95 print " Unused object\n";
96 foreach $a (sort(keys %arches)) {
97 print "$a\n" if (!$objects{$a} && !$players{$a} && !$abilities{$a})
98 }
99 }
100
101 exit;
102
103 sub print_usage() {
104 print "=" x 70, "\nArchetype count\n";
105 $total = 0;
106 foreach $a (sort by (keys (%objects))) {
107 printf ("%-24s%d\n", $a, $objects{$a});
108 $total += $objects{$a};
109 }
110 print '-' x 30, "\nTotal objects $total\n";
111 }
112 # return table containing all objects in the map
113 sub readmap {
114 my ($m);
115 my($last);
116 my($parent);
117 $last = "";
118 $parent = "";
119
120 $/ = "\nend\n";
121 if (! open (IN, $file)) {
122 print "Can't open map file $file\n";
123 return;
124 }
125 $_ = <IN>;
126 if (! /^arch map$/) {
127 # print "Error: file $file isn't mapfile.\n";
128 return;
129 }
130 if ($VERBOSE) {
131 print "Testing $file, ";
132 print /^name (.+)$/ ? $1 : "No mapname";
133 print ", size [", /^x (\d+)$/ ? $1 : 16;
134 print ",", /^y (\d+)/ ? $1 : 16, "]";
135
136 if (! /^msg$/) {
137 print ", No message\n";
138 } elsif (/(\w+@\S+)/) {
139 print ", $1\n";
140 } else {
141 print ", Unknown\n";
142 }
143 $printmap=0;
144 }
145 else {
146 $name= /^name (.+)$/ ? $1 : "No mapname";
147 $x= /^x (\d+)$/ ? $1 : 16;
148 $y= /^y (\d+)/ ? $1 : 16;
149 $mapname="Map $file, $name, size [$x, $y]\n" ;
150 $printmap=1;
151 }
152
153
154 while (<IN>) {
155 if (($m = (@_ = /^arch \S+\s*$/g)) > 1) {
156 $parent = /^arch (\S+)\s*$/;
157 # object has inventory
158 my ($inv) = $_;
159 while (<IN>) {
160 if (/((.|\n)*end\n)(arch (.|\n)*\nend\n)/) {
161 &check_obj ("$inv$1");
162 &check_obj ($3);
163 last;
164 } elsif (/^arch (.|\n)*\nend$/) {
165 &check_obj ($_);
166 } elsif (/^end$/) {
167 &check_obj ("$inv$_");
168 } else {
169 # if ($printmap) { print "$mapname"; $printmap=0;}
170 # This doesn't work right - it gets confused when objects are within
171 # another object
172 # print " Error: Corrupted map file $file.\nSegment:\n$_\nLine: $.\n";
173 }
174 }
175 $parent="";
176 } elsif (/^More$/ || $m == 1) {
177 &check_obj ($_);
178 } else {
179 # if ($printmap) { print "$mapname"; $printmap=0;}
180 # print " Error: Corrupted map file $file.\nSegment:\n$_\nLine: $.\n";
181 }
182 }
183 close (IN);
184 }
185
186 sub check_obj {
187 $_ = shift @_;
188
189 local ($x) = (/^x (\d+)$/)?$1:0;
190 local ($y) = (/^y (\d+)$/)?$1:0;
191 local($arch) = /^arch (\S+)\s*$/;
192
193 if (! $arches{$1} && $last ne $1) {
194 $last = $1;
195 if ($printmap) { print "$mapname"; $printmap=0;}
196 print " Error: Object $last is not defined in archetypes file ($x,$y), arch=$arch\n";
197 $missing{$last}++;
198 } elsif ($ex{$1}) {
199 &examine_exit ($_);
200 } elsif ($tele{$1}) {
201 if (/^food -?\d+$/) {
202 if ($printmap) { print "$mapname"; $printmap=0;}
203 print " Error: Teleport $1 has food field.\n";
204 }
205 else {
206 &examine_exit ($_);
207 }
208 } elsif ($conn{$1} && ! /^connected -?\d+$/) {
209 $last = $1;
210 if ($CONNECTED) {
211 if ($printmap) { print "$mapname"; $printmap=0;}
212 print " Warning: Object $last has not been connected, $x,$y\n"
213 }
214 } elsif ($players{$1} && $last ne $1 && ! /^type / ) {
215 $last = $1;
216 if ($printmap) { print "$mapname"; $printmap=0;}
217 print " Error: Player $last found in the map.\n";
218 } elsif ($1 eq "scroll" && ! /^msg$/) {
219 $last = $1;
220 # print " Warning: scroll without message ($x, $y:$parent), should be random_scroll?\n";
221 } elsif ($1 eq "potion" && $last ne $1) {
222 $last = $1;
223 # print " Warning: potion found, should be random_potion or random_food?\n";
224 } elsif ($1 eq "ring" || $1 eq "amulet") {
225 $last = $1;
226 # print " Warning: ring/amulet found ($x,$y:$parent), should be random_talisman?\n";
227 }
228 $objects{$1}++;
229 if (/^color_fg (\S+)$/ || /^color_bg (\S+)$/) {
230 $last = $arch;
231 if ($printmap) { print "$mapname"; $printmap=0;}
232 print " Warning: Object ".$arch." is setting color ($1), $x,$y\n";
233 }
234 if (/^animation (\S+)$/) {
235 if (! $anim{$1}) {
236 if ($printmap) { print "$mapname"; $printmap=0;}
237 print "Error: Object $arch is using an unknown animation $1\n"
238 }
239 }
240 if (/^face (\S+)$/) {
241 if (! $faces{$1}) {
242 if ($printmap) { print "$mapname"; $printmap=0;}
243 print "Error: Object $arch is using an unknown face $1\n"
244 }
245 }
246 }
247
248 sub by {
249 $_ = $objects{$b} <=> $objects{$a};
250 $_ ? $_ : $a cmp $b;
251 }
252
253 sub obj_name {
254 $_ = shift(@_);
255 local ($name) = /^name (.+)$/; # object's name
256 local ($arch) = /^arch (\S+)$/;
257 if (!defined ($name) && $arches{$arch} =~ /^name (.+)$/) {
258 $name = $1; # archetype's name
259 }
260 return defined ($name) ? $name : $arch; # archetype or name
261 }
262
263 sub examine_exit {
264 $_ = shift(@_);
265
266 local ($x) = (/^hp (\d+)$/)?$1:0;
267 local ($y) = (/^sp (\d+)$/)?$1:0;
268 local ($x1) = (/^x (\d+)$/)?$1:0;
269 local ($y1) = (/^y (\d+)$/)?$1:0;
270 local ($to) = /^slaying (\S+)$/;
271
272 if (/^food (-?\d+)$/) {
273 # old style exits, doesn't work with crossfire 0.90-1
274 if ($printmap) { print "$mapname"; $printmap=0;}
275 print " Error: ", &obj_name($_), " ($x1,$y1) -> ",
276 "Old style level [$1] ($x,$y)\n";
277 } elsif (! defined ($to)) {
278 # print " Closed: ", &obj_name($_), " ($x1,$y1)\n";
279 } else {
280 # These are currently used be crossfire
281 if ($to eq "/!") { # this is a random exit - if we
282 # have a final map, make sure it
283 # exists
284 local ($finalmap) = /^final_map (\S+)$/;
285 if ($finalmap ne "") {
286 if ($finalmap =~ m!^/!) { $cdir = "$MAPS"; }
287 else { ($cdir) = $file =~ m!(.*/)!; }
288 if (! -f "$cdir$finalmap") {
289 if ($printmap) { print "$mapname"; $printmap=0;}
290 print " Missing: ", &obj_name($_), " ($x1,$y1) -> $finalmap ($x,$y)\n";
291 }
292 }
293 return;
294 }
295 if ($to =~ m!^/!) {
296 $cdir = "$MAPS";
297 } else {
298 ($cdir) = $file =~ m!(.*/)!;
299 }
300 if (! -f "$cdir$to") {
301 if ($printmap) { print "$mapname"; $printmap=0;}
302 print " Missing: ", &obj_name($_), " ($x1,$y1) -> $to ($x,$y)\n";
303 } else {
304 # print " OK: ", &obj_name($_), " ($x1,$y1) -> $to ($x,$y)\n";
305 }
306 }
307 }
308
309 # @maps contains all filenames
310 sub maplist {
311 local ($dir, $file, @dirs) = shift;
312
313 opendir (DIR , $dir) || die "Can't open directory : $dir\n";
314 while ($file = readdir (DIR)) {
315 next if ($file eq "." || $file eq ".." || $file eq "CVS" || $file eq "unlinked" || $file eq "editor");
316 $file = "$dir/$file";
317 next if (-l $file);
318 push (@dirs, $file) if (-d $file);
319 push (@maps, $file) if (-f $file);
320 }
321 closedir (DIR);
322
323 # recurcive handle sub-dirs too
324 while ($_ = shift @dirs) {
325 &maplist ($_);
326 }
327 }
328
329 # collect all objects matching with reg.expr.
330 sub collect {
331 local ($expr,$a, %col) = shift;
332
333 foreach $a (keys %arches) {
334 $_ = $arches{$a};
335 if (/$expr/) {
336 $col{$a}++;
337 }
338 }
339 return %col;
340 }
341
342 # collect all archetypes into associative array %arches
343 sub archetypes {
344 open (IN, $ARCH) || die "Can't open archetype file $ARCH.\n";
345 $/ = "\nend\n";
346 while (<IN>) {
347 while (/^Object (\S+)\s*$/g) {
348 $arches{$1} = $_;
349 }
350 }
351 close (IN);
352 }
353
354 sub faces {
355 open(IN, $BMAPS) || die ("Can't open faces file $BMAPS\n");
356 while (<IN>) {
357 chomp;
358 ($num, $name) = split;
359 $faces{$name} = $name;
360 }
361 close(IN);
362 }
363
364
365 sub animations {
366 open(IN, $ANIM) || die ("Can't open animations file $ANIM\n");
367 while (<IN>) {
368 if (/^anim (\S+)\s*$/) {
369 $anim{$1} = $1;
370 }
371 }
372 close(IN);
373 }
374
375