ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/wall.C
Revision: 1.4
Committed: Sun Sep 10 16:06:37 2006 UTC (17 years, 9 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.3: +290 -244 lines
Log Message:
indent

File Contents

# User Rev Content
1 root 1.4
2 elmex 1.1 /*
3     * static char *rcsid_wall_c =
4 root 1.4 * "$Id: wall.C,v 1.3 2006-09-03 00:18:42 root Exp $";
5 elmex 1.1 */
6    
7     /*
8     CrossFire, A Multiplayer game for X-windows
9    
10     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
11     Copyright (C) 1992 Frank Tore Johansen
12    
13     This program is free software; you can redistribute it and/or modify
14     it under the terms of the GNU General Public License as published by
15     the Free Software Foundation; either version 2 of the License, or
16     (at your option) any later version.
17    
18     This program is distributed in the hope that it will be useful,
19     but WITHOUT ANY WARRANTY; without even the implied warranty of
20     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21     GNU General Public License for more details.
22    
23     You should have received a copy of the GNU General Public License
24     along with this program; if not, write to the Free Software
25     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26    
27     The authors can be reached via e-mail at crossfire-devel@real-time.com
28     */
29    
30     #include <global.h>
31     #include <random_map.h>
32     #include <rproto.h>
33    
34     /* Put in the walls and autojoin them. */
35    
36    
37     /* given a layout and a coordinate, tell me which squares up/down/right/left
38 root 1.2 are occupied. */
39 elmex 1.1
40 root 1.4 int
41     surround_flag (char **layout, int i, int j, RMParms * RP)
42     {
43 elmex 1.1 /* 1 = wall to left,
44 root 1.4 2 = wall to right,
45     4 = wall above
46     8 = wall below */
47 elmex 1.1 int surround_index = 0;
48 root 1.4
49     if ((i > 0) && layout[i - 1][j] != 0)
50     surround_index |= 1;
51     if ((i < RP->Xsize - 1) && layout[i + 1][j] != 0)
52     surround_index |= 2;
53     if ((j > 0) && layout[i][j - 1] != 0)
54     surround_index |= 4;
55     if ((j < RP->Ysize - 1) && layout[i][j + 1] != 0)
56     surround_index |= 8;
57 elmex 1.1 return surround_index;
58     }
59    
60    
61     /* like surround_flag, but only walls count.
62 root 1.2 */
63 elmex 1.1
64 root 1.4 int
65     surround_flag2 (char **layout, int i, int j, RMParms * RP)
66     {
67 elmex 1.1 /* 1 = wall to left,
68 root 1.4 2 = wall to right,
69     4 = wall above
70     8 = wall below */
71 elmex 1.1 int surround_index = 0;
72 root 1.4
73     if ((i > 0) && layout[i - 1][j] == '#')
74     surround_index |= 1;
75     if ((i < RP->Xsize - 1) && layout[i + 1][j] == '#')
76     surround_index |= 2;
77     if ((j > 0) && layout[i][j - 1] == '#')
78     surround_index |= 4;
79     if ((j < RP->Ysize - 1) && layout[i][j + 1] == '#')
80     surround_index |= 8;
81 elmex 1.1 return surround_index;
82     }
83    
84    
85     /* like surround_flag, except it checks a map, not a layout.
86     * Since this is part of the random map code, presumption
87     * is that this is not a tiled map.
88     * What is considered blocking and not is somewhat hard coded.
89     */
90 root 1.4 int
91     surround_flag3 (mapstruct *map, sint16 i, sint16 j, RMParms * RP)
92     {
93     /*
94     * 1 = blocked to left,
95     * 2 = blocked to right,
96     * 4 = blocked above
97     * 8 = blocked below
98     */
99    
100     int surround_index = 0;
101 elmex 1.1
102 root 1.4 if ((i > 0) && (GET_MAP_MOVE_BLOCK (map, i - 1, j) & ~MOVE_BLOCK_DEFAULT))
103     surround_index |= 1;
104     if ((i < RP->Xsize - 1) && (GET_MAP_MOVE_BLOCK (map, i + 1, j) & ~MOVE_BLOCK_DEFAULT))
105     surround_index |= 2;
106     if ((j > 0) && (GET_MAP_MOVE_BLOCK (map, i, j - 1) & ~MOVE_BLOCK_DEFAULT))
107     surround_index |= 4;
108     if ((j < RP->Ysize - 1) && (GET_MAP_MOVE_BLOCK (map, i, j + 1) & ~MOVE_BLOCK_DEFAULT))
109     surround_index |= 8;
110    
111     return surround_index;
112 elmex 1.1 }
113    
114     /* like surround_flag2, except it checks a map, not a layout. */
115    
116 root 1.4 int
117     surround_flag4 (mapstruct *map, int i, int j, RMParms * RP)
118     {
119 elmex 1.1 /* 1 = blocked to left,
120 root 1.4 2 = blocked to right,
121     4 = blocked above
122     8 = blocked below */
123 elmex 1.1 int surround_index = 0;
124    
125 root 1.4 if ((i > 0) && wall_blocked (map, i - 1, j))
126     surround_index |= 1;
127     if ((i < RP->Xsize - 1) && wall_blocked (map, i + 1, j))
128     surround_index |= 2;
129     if ((j > 0) && wall_blocked (map, i, j - 1))
130     surround_index |= 4;
131     if ((j < RP->Ysize - 1) && wall_blocked (map, i, j + 1))
132     surround_index |= 8;
133 elmex 1.1
134     return surround_index;
135     }
136    
137     /* takes a map and a layout, and puts walls in the map (picked from
138 root 1.2 w_style) at '#' marks. */
139 elmex 1.1
140 root 1.4 void
141     make_map_walls (mapstruct *map, char **layout, char *w_style, RMParms * RP)
142     {
143     char styledirname[256];
144     char stylefilepath[256];
145     mapstruct *style_map = 0;
146     object *the_wall;
147    
148     /* get the style map */
149     if (!strcmp (w_style, "none"))
150     return;
151     sprintf (styledirname, "%s", "/styles/wallstyles");
152     sprintf (stylefilepath, "%s/%s", styledirname, w_style);
153     style_map = find_style (styledirname, w_style, -1);
154     if (style_map == 0)
155     return;
156    
157     /* fill up the map with the given floor style */
158     if ((the_wall = pick_random_object (style_map)) != NULL)
159     {
160     int i, j;
161     char *cp;
162     int joinedwalls = 0;
163     object *thiswall;
164    
165     sprintf (RP->wall_name, "%s", &the_wall->arch->name);
166     if ((cp = strchr (RP->wall_name, '_')) != NULL)
167     {
168     *cp = 0;
169     joinedwalls = 1;
170 root 1.2 }
171    
172 root 1.4 for (i = 0; i < RP->Xsize; i++)
173     for (j = 0; j < RP->Ysize; j++)
174     {
175     if (layout[i][j] == '#')
176     {
177     if (joinedwalls)
178     thiswall = pick_joined_wall (the_wall, layout, i, j, RP);
179     else
180     thiswall = arch_to_object (the_wall->arch);
181     thiswall->x = i;
182     thiswall->y = j;
183     thiswall->move_block = MOVE_ALL;
184     insert_ob_in_map (thiswall, map, thiswall, INS_NO_MERGE | INS_NO_WALK_ON);
185     }
186     }
187 elmex 1.1 }
188     }
189    
190    
191     /* picks the right wall type for this square, to make it look nice,
192 root 1.2 and have everything nicely joined. It uses the layout. */
193 elmex 1.1
194 root 1.4 object *
195     pick_joined_wall (object *the_wall, char **layout, int i, int j, RMParms * RP)
196     {
197 elmex 1.1 /* 1 = wall to left,
198 root 1.4 2 = wall to right,
199     4 = wall above
200     8 = wall below */
201     int surround_index = 0;
202 elmex 1.1 int l;
203     char wall_name[64];
204 root 1.4 archetype *wall_arch = 0;
205 elmex 1.1
206 root 1.4 strcpy (wall_name, the_wall->arch->name);
207 elmex 1.1
208     /* conventionally, walls are named like this:
209 root 1.4 wallname_wallcode, where wallcode indicates
210     a joinedness, and wallname is the wall.
211     this code depends on the convention for
212     finding the right wall. */
213 elmex 1.1
214     /* extract the wall name, which is the text up to the leading _ */
215 root 1.4 for (l = 0; l < 64; l++)
216     {
217     if (wall_name[l] == '_')
218     {
219     wall_name[l] = 0;
220     break;
221     }
222     }
223    
224     surround_index = surround_flag2 (layout, i, j, RP);
225    
226     switch (surround_index)
227     {
228     case 0:
229     strcat (wall_name, "_0");
230     break;
231     case 1:
232     strcat (wall_name, "_1_3");
233     break;
234     case 2:
235     strcat (wall_name, "_1_4");
236     break;
237     case 3:
238     strcat (wall_name, "_2_1_2");
239     break;
240     case 4:
241     strcat (wall_name, "_1_2");
242     break;
243     case 5:
244     strcat (wall_name, "_2_2_4");
245     break;
246     case 6:
247     strcat (wall_name, "_2_2_1");
248     break;
249     case 7:
250     strcat (wall_name, "_3_1");
251     break;
252     case 8:
253     strcat (wall_name, "_1_1");
254     break;
255     case 9:
256     strcat (wall_name, "_2_2_3");
257     break;
258     case 10:
259     strcat (wall_name, "_2_2_2");
260     break;
261     case 11:
262     strcat (wall_name, "_3_3");
263     break;
264     case 12:
265     strcat (wall_name, "_2_1_1");
266     break;
267     case 13:
268     strcat (wall_name, "_3_4");
269     break;
270     case 14:
271     strcat (wall_name, "_3_2");
272     break;
273     case 15:
274     strcat (wall_name, "_4");
275     break;
276     }
277     wall_arch = find_archetype (wall_name);
278     if (wall_arch)
279     return arch_to_object (wall_arch);
280     else
281     {
282     nroferrors--;
283     return arch_to_object (the_wall->arch);
284     }
285    
286 elmex 1.1
287     }
288 root 1.4
289 elmex 1.1
290     /* this takes a map, and changes an existing wall to match what's blocked
291     * around it, counting only doors and walls as blocked. If insert_flag is
292     * 1, it will go ahead and insert the wall into the map. If not, it
293     * will only return the wall which would belong there, and doesn't
294     * remove anything. It depends on the
295     * global, previously-set variable, "wall_name"
296     */
297    
298 root 1.4 object *
299     retrofit_joined_wall (mapstruct *the_map, int i, int j, int insert_flag, RMParms * RP)
300     {
301     /* 1 = wall to left,
302     * 2 = wall to right,
303     * 4 = wall above
304     * 8 = wall below
305     */
306     int surround_index = 0;
307     int l;
308     object *the_wall = 0;
309     object *new_wall = 0;
310     archetype *wall_arch = 0;
311    
312     /* first find the wall */
313     for (the_wall = get_map_ob (the_map, i, j); the_wall != NULL; the_wall = the_wall->above)
314     if ((the_wall->move_type & MOVE_WALK) && the_wall->type != EXIT && the_wall->type != TELEPORTER)
315     break;
316    
317    
318     /* if what we found is a door, don't remove it, set the_wall to NULL to
319     * signal that later.
320     */
321     if (the_wall && (the_wall->type == DOOR || the_wall->type == LOCKED_DOOR))
322     {
323     the_wall = NULL;
324     /* if we're not supposed to insert a new wall where there wasn't one,
325     * we've gotta leave.
326     */
327     if (insert_flag == 0)
328     return 0;
329 elmex 1.1 }
330 root 1.4 else if (the_wall == NULL)
331     return NULL;
332 elmex 1.1
333 root 1.4 /* canonicalize the wall name */
334     for (l = 0; l < 64; l++)
335     {
336     if (RP->wall_name[l] == '_')
337     {
338     RP->wall_name[l] = 0;
339     break;
340 root 1.2 }
341 elmex 1.1 }
342    
343 root 1.4 surround_index = surround_flag4 (the_map, i, j, RP);
344     /* This would be a lot cleaner to just us a lookup table,
345     * eg, wall_suffix[surround_index]
346     */
347     switch (surround_index)
348     {
349 root 1.2 case 0:
350 root 1.4 strcat (RP->wall_name, "_0");
351     break;
352 root 1.2 case 1:
353 root 1.4 strcat (RP->wall_name, "_1_3");
354     break;
355 root 1.2 case 2:
356 root 1.4 strcat (RP->wall_name, "_1_4");
357     break;
358 root 1.2 case 3:
359 root 1.4 strcat (RP->wall_name, "_2_1_2");
360     break;
361 root 1.2 case 4:
362 root 1.4 strcat (RP->wall_name, "_1_2");
363     break;
364 root 1.2 case 5:
365 root 1.4 strcat (RP->wall_name, "_2_2_4");
366     break;
367 root 1.2 case 6:
368 root 1.4 strcat (RP->wall_name, "_2_2_1");
369     break;
370 root 1.2 case 7:
371 root 1.4 strcat (RP->wall_name, "_3_1");
372     break;
373 root 1.2 case 8:
374 root 1.4 strcat (RP->wall_name, "_1_1");
375     break;
376 root 1.2 case 9:
377 root 1.4 strcat (RP->wall_name, "_2_2_3");
378     break;
379 root 1.2 case 10:
380 root 1.4 strcat (RP->wall_name, "_2_2_2");
381     break;
382 root 1.2 case 11:
383 root 1.4 strcat (RP->wall_name, "_3_3");
384     break;
385 root 1.2 case 12:
386 root 1.4 strcat (RP->wall_name, "_2_1_1");
387     break;
388 root 1.2 case 13:
389 root 1.4 strcat (RP->wall_name, "_3_4");
390     break;
391 root 1.2 case 14:
392 root 1.4 strcat (RP->wall_name, "_3_2");
393     break;
394 root 1.2 case 15:
395 root 1.4 strcat (RP->wall_name, "_4");
396     break;
397 elmex 1.1 }
398 root 1.4 wall_arch = find_archetype (RP->wall_name);
399     if (wall_arch != NULL)
400     {
401     new_wall = arch_to_object (wall_arch);
402     new_wall->x = i;
403     new_wall->y = j;
404     if (the_wall && the_wall->map)
405     {
406     remove_ob (the_wall);
407     free_object (the_wall);
408 root 1.2 }
409 root 1.4 the_wall->move_block = MOVE_ALL;
410     insert_ob_in_map (new_wall, the_map, new_wall, INS_NO_MERGE | INS_NO_WALK_ON);
411 elmex 1.1 }
412 root 1.4 else
413     nroferrors--; /* it's OK not to find an arch. */
414     return new_wall;
415 elmex 1.1 }