ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/lib/adm/map_check
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 # (C) Copyright Markus Weber, 1994. All rights reserved.
4 # Permission is granted to use, copy, and modify for non-commercial use.
5 #
6
7 # usage: check-consistency.pl [options]...
8 # Options:
9 # archdb=pathname-of-archetype-database *** not used ***
10 # default ./ARCHDB .{dir,pag}
11 # archetypes=pathname-of-archetypes-file
12 # default $cfdir/share/crossfire/archetypes
13 # cfdir=pathname-to-crossfire-installation
14 # default /opt/cf0901 (hardcoded)
15 # mapdir=pathname-of-map-directory
16 # default $cfdir/share/crossfire/maps
17 # start-map=map-path-of-starting map
18 # default (init in archetypes)
19
20 # %% make it a command line option
21 $debug = 1;
22
23 #
24 # ARGUMENT PROCESSING
25 #
26 # preset options
27 $cfdir = "/export/home/crossfire/cf-installroot";
28
29 # loop thru arg vector
30 while (@ARGV) {
31 $_ = @ARGV[0];
32 if (/^archdb=/) {
33 ($junk,$archdb) = split(/=/,$ARGV[0]);
34 shift;
35 }
36 elsif (/^archetypes=/) {
37 ($junk,$archetypes) = split(/=/,$ARGV[0]);
38 shift;
39 }
40 elsif (/^cfdir=/) {
41 ($junk,$cfdir) = split(/=/,$ARGV[0]);
42 shift;
43 }
44 elsif (/^mapdir=/) {
45 ($junk,$mapdir) = split(/=/,$ARGV[0]);
46 shift;
47 }
48 elsif (/^start-map=/) {
49 ($junk,$start_map) = split(/=/,$ARGV[0]);
50 shift;
51 }
52 else {
53 print "Unknown option $ARGV[0]\n";
54 exit;
55 }
56 }
57
58 # post-process
59 $mapdir = "$cfdir/share/crossfire/maps" unless defined($mapdir);
60 $archetypes = "$cfdir/share/crossfire/archetypes" unless defined($archetypes);
61 print STDERR "DBG: archetypes=$archetypes\n" if $debug > 5;
62 print STDERR "DBG: archdb=$archdb\n" if $debug > 5;
63 print STDERR "DBG: mapdir=$mapdir\n" if $debug > 5;
64
65
66 #
67 # INIT ARCHETYPES DATABASE
68 #
69 print STDERR "DBG: initializing archetype database...\n" if $debug;
70 &init_archetypes_database; # unless $skip_db_init;
71 print STDERR "DBG: ...done\n" if $debug;
72
73 defined($start_map) || die "FATAL: no starting map";
74 print STDERR "DBG: start_map=$start_map\n" if $debug;
75
76
77 print STDERR "DBG: scanning for archetypes of special interest...\n" if $debug;
78
79 while ( ($arch,$type) = each(%ARCHDB) ) {
80
81 next if !defined($type); # skip if not special
82
83 $_ = $type; # see below
84
85 if ($type == 41 || $type == 66 || $type == 94) {
86 # EXITS: archetypes with exits to other maps
87 $EXITS{$arch} = 1;
88 }
89 # Bad Programming Style Alert. Don't try this at home!
90 elsif (/^1[78]$/ || /^2[679]$/ || /^3[012]$/ || /^9[123]$/) {
91 # CONNECT: "connected" archetypes,
92 # e.g. buttons, handles, gates, ...
93 $CONNECT{$arch} = 1;
94 }
95 if ($type == 85) {
96 $SB{$arch} = 1;
97 }
98
99 }
100
101 print STDERR "DBG: ...done.\n" if $debug;
102
103 #
104 # MAIN LOOP
105 #
106
107 # pathname of start_map is assumed to be absolute (e.g. /village/village
108 push(@MAPS,$start_map);
109
110 while ($map = pop(@MAPS)) {
111
112 # print STDERR "array stack size is $#MAPS\n";
113 next if $visited{$map}; # skip if been here before
114 $visited{$map} = 1; # flag it if not
115
116 # skip random maps
117 next if ($map =~ m#/!#);
118
119 print STDERR "DBG: visiting $map\n" if $debug;
120 #print "visiting $map\n" if $debug;
121
122 #
123 # side effect: check_map pushes any (legal) exits found on stack
124 #
125 &check_map($map);
126 }
127
128 print "Unused archetypes:\n";
129 foreach $key (sort(keys %ARCHDB)) {
130 print "$key\n" if (!defined($USED{$key}))
131 }
132
133
134
135 exit;
136
137 #
138 # ++++++++++++++++++++ END OF MAIN ++++++++++++++++++
139 #
140
141 #
142 # INIT ARCHETYPES DATABASE
143 #
144 # store (archname,type) pairs
145 #
146 sub init_archetypes_database {
147 local($arch_lines,$arches); # counters
148 local($arch,$type,$slaying); # values
149 local($junk);
150
151 print STDERR "DBG: opening archetypes: $archetypes\n" if $debug > 5;
152 open(ARCHETYPES,$archetypes) || die "can't open $archetypes";
153
154 $arch_lines = 0;
155 $arches = 0;
156 $type = 0;
157
158 while ( <ARCHETYPES> ) {
159 $arch_lines++;
160 if (/^Object\s/) {
161 ($junk,$arch) = split;
162 if (!defined($arch)) {
163 print STDERR "$archetypes: bad Object, line $arch_lines\n";
164 }
165 }
166 elsif (/^type\s/) {
167 ($junk,$type) = split;
168 if (!defined($type)) {
169 print STDERR "$archetypes: bad type, line $arch_lines\n";
170 }
171 }
172 elsif (/^slaying\s/ && $arch eq "map") {
173 ($junk,$slaying) = split;
174 # don't care if defined or not (yet)
175 }
176 elsif (/^end$/) {
177 print STDERR "DBG: entered arch=$arch, optional type=$type\n" if $debug > 10;
178 next if (!defined($arch));
179 # don't care whether $type defined or not
180 $ARCHDB{$arch} = $type;
181 $arches++;
182 $type = 0;
183 }
184 elsif (/^end\s*$/) {
185 print STDERR "DBG: arch $arch is using end with space before newline\n";
186 next if (!defined($arch));
187 # don't care whether $type defined or not
188 $ARCHDB{$arch} = $type;
189 $arches++;
190 $type = 0;
191 }
192 }
193
194 #
195 # find start map
196 # print error message iff "map" arch not found or missing path
197 # assign start map (unless pre-defined on cmd line)
198 #
199 if (!defined($slaying)) {
200 print STDERR "***ERROR*** no map object or map path missing\n";
201 }
202 elsif (!defined($start_map)) {
203 $start_map = $slaying;
204 }
205 #print STDERR "DBG: start_map=$start_map\n";
206
207 close(ARCHETYPES);
208 print STDERR "DBG: closed $archetypes, $arch_lines lines, $arches arches\n"
209 if $debug > 5;
210 }
211
212 #
213 # CHECK MAP FOR ELEMENTARY CONSISTENCY
214 #
215
216 sub check_map {
217 local($map) = @_;
218 local($arch,$connected,$slaying,$exit,$x,$y, $rx, $ry);
219 local($lines,$fullmap);
220 local($junk);
221 $depth=0;
222
223 # build full pathname (nb: map path starts with /) and open map file
224 $fullmap = "$mapdir$map";
225 open(MAP,$fullmap) || die "can't open $fullmap";
226 print STDERR "DBG: opened $map\n" if $debug > 5;
227
228 $lines = 0;
229
230 while ( <MAP> ) {
231 if (/^tile_path_/) {
232 ($junk,$slaying) = split;
233 $_ = "$map $slaying"; # easy matching :-)
234 s@^(/.*/)([^/]*)\s([^\./].*)$@\1\2 \1\3@;
235 s@^(/.*/)([^/]*)\s(\.\./.*)$@\1\2 \1\3@;
236 s@/[^/]*/\.\./@/@g;
237 ($junk,$exit) = split;
238 next if $visited{$exit};
239
240 if ( (! -r "$mapdir$exit") && ( $exit ne "/!") ) {
241 print "ERROR: map $map, arch $arch, line $lines, no such exit $exit ($rx, $ry, to $x, $y)\n";
242 next;
243 }
244 push(@MAPS,$exit);
245 }
246
247
248 $lines++;
249 if (/^arch\s/) {
250 # Note we have to do some checks here - that is because
251 # if an object is inside an object, the value of $arch
252 # is clobbered.
253 ($junk,$arch) = split;
254 # if ($SB{$arch}) {
255 # print "WARNING: spellbook found at map $map, line $lines, arch $arch\n";
256 # }
257 if (!defined($ARCHDB{$arch})) {
258 print "FATAL: map $map, line $lines, bad archetype: $arch ($rx, $ry)\n";
259 }
260 $USED{$arch}=1;
261 undef($slaying);
262 undef($x);
263 undef($y);
264 undef($rx);
265 undef($ry);
266 undef($connected);
267 $depth++;
268 }
269 elsif (/^connected\s/) {
270 ($junk,$connected) = split;
271 }
272 elsif (/^slaying\s/) {
273 ($junk,$slaying) = split;
274 }
275 elsif (/^hp\s/) {
276 ($junk,$x) = split;
277 }
278 elsif (/^sp\s/) {
279 ($junk,$y) = split;
280 }
281 elsif (/^x\s/) {
282 ($junk, $rx) = split;
283 }
284 elsif (/^y\s/) {
285 ($junk, $ry) = split;
286 }
287 elsif (/^anim$/) {
288 print "Map $fullmap has an anim command in it\n";
289 }
290
291 next if !/^end$/; # continue iff not end of arch
292 $depth--;
293
294 #
295 # CHECK 2: connect-arch actually connected?
296 # NB: if not, that's perfectly legal, but suspicious
297 #
298 # if ($CONNECT{$arch}) {
299 # if (!$connected) {
300 #print STDERR "WARNING: map $map, line $lines, arch $arch, not connected\n";
301 #print "WARNING: map $map, line $lines, arch $arch, not connected\n";
302 # }
303 # next;
304 # }
305
306 next if !$EXITS{$arch}; # continue if not an exit
307
308
309 #
310 # CHECK 3: exit-type arch, but no path given
311 # Presumably the path defaults to the local map,
312 # but in all probability this is an error
313 #
314 if (!defined($slaying)) {
315 if ($x || $y) {
316 #print STDERR "ERROR: map $map, line $lines, arch $arch, exit defaults\n";
317 #print "ERROR: map $map, line $lines, arch $arch, exit defaults\n";
318 }
319 else {
320 #print STDERR "INFO: map $map, line $lines, arch $arch, no exit defined\n";
321 #print "INFO: map $map, line $lines, arch $arch, no exit defined\n";
322 }
323 next;
324 }
325
326 #
327 # CHECK 4: verify that exit map exists
328 # if not, the game (hopefully!) won't crash, but
329 # chances are this _is_ an error
330 #
331
332 #
333 # normalize exit path (FullyQualifiedPathName :-)))
334 # (i.e. construct absolute pathname, rooted in CLibDir/maps)
335 # E.g.:
336 # current map: /village/somewhere
337 # EXIT PATH YIELDS
338 # /village/building /village/building
339 # townhouse /village/townhouse
340 # ../island /island
341 #
342 $_ = "$map $slaying"; # easy matching :-)
343 # /path/map exit --> /path/map /path/exit
344 s@^(/.*/)([^/]*)\s([^\./].*)$@\1\2 \1\3@;
345 # /path/map ../exit --> /path/map /path/../exit
346 s@^(/.*/)([^/]*)\s(\.\./.*)$@\1\2 \1\3@;
347 # /dir/../ --> / (all occurances)
348 s@/[^/]*/\.\./@/@g;
349
350 ($junk,$exit) = split;
351 #print STDERR "DBG: exit $map $exit\n" if $debug > 5;
352 #print "exit $map $exit\n";
353
354 #
355 # shortcut: if the exit map was already checked, don't bother
356 # stacking it again.
357 # %% if a map is never pushed twice in the first place,
358 # the corresponding test in the main loop is probably
359 # in vain.
360 #
361 next if $visited{$exit};
362
363 #
364 # this is check 4, finally.
365 # if exit map can't be opened, complain and continue
366 #
367 if ( (! -r "$mapdir$exit") && ( $exit ne "/!") ) {
368 #print STDERR "ERROR: map $map, arch $arch, line $lines, no such exit $exit\n";
369 print "ERROR: map $map, arch $arch, line $lines, no such exit $exit ($rx, $ry, to $x, $y)\n";
370 next;
371 }
372
373 #
374 # the exit map looks good; push it and continue
375 push(@MAPS,$exit);
376 }
377
378 close(MAP);
379 if ($depth != 0) {
380 print "ERROR: map $map, mismatched arch/end, $depth\n";
381 }
382 }