ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/wall.C
Revision: 1.17
Committed: Sat Jan 27 00:56:48 2007 UTC (17 years, 3 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.16: +1 -1 lines
Log Message:
proactive

File Contents

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