ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/wall.C
Revision: 1.15
Committed: Sat Jan 6 14:42:30 2007 UTC (17 years, 5 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.14: +1 -0 lines
Log Message:
added some copyrights

File Contents

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