ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/wall.C
Revision: 1.24
Committed: Thu Nov 8 19:43:25 2007 UTC (16 years, 7 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_4, rel-2_32, rel-2_43, rel-2_42, rel-2_41
Changes since 1.23: +4 -4 lines
Log Message:
update copyrights and other minor stuff to deliantra

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.24 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 pippijn 1.16 *
4 root 1.24 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 root 1.23 * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.16 *
8 root 1.24 * Deliantra is free software: you can redistribute it and/or modify
9 pippijn 1.16 * it under the terms of the GNU General Public License as published by
10 root 1.23 * the Free Software Foundation, either version 3 of the License, or
11 pippijn 1.16 * (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 root 1.23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 pippijn 1.16 * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19 root 1.23 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20     *
21 root 1.24 * The authors can be reached via e-mail to <support@deliantra.net>
22 pippijn 1.16 */
23 elmex 1.1
24     #include <global.h>
25     #include <random_map.h>
26     #include <rproto.h>
27    
28     /* Put in the walls and autojoin them. */
29    
30    
31     /* given a layout and a coordinate, tell me which squares up/down/right/left
32 root 1.2 are occupied. */
33 elmex 1.1
34 root 1.4 int
35 root 1.13 surround_flag (char **layout, int i, int j, random_map_params *RP)
36 root 1.4 {
37 elmex 1.1 /* 1 = wall to left,
38 root 1.4 2 = wall to right,
39     4 = wall above
40     8 = wall below */
41 elmex 1.1 int surround_index = 0;
42 root 1.4
43     if ((i > 0) && layout[i - 1][j] != 0)
44     surround_index |= 1;
45     if ((i < RP->Xsize - 1) && layout[i + 1][j] != 0)
46     surround_index |= 2;
47     if ((j > 0) && layout[i][j - 1] != 0)
48     surround_index |= 4;
49     if ((j < RP->Ysize - 1) && layout[i][j + 1] != 0)
50     surround_index |= 8;
51 elmex 1.1 return surround_index;
52     }
53    
54    
55     /* like surround_flag, but only walls count.
56 root 1.2 */
57 elmex 1.1
58 root 1.4 int
59 root 1.13 surround_flag2 (char **layout, int i, int j, random_map_params *RP)
60 root 1.4 {
61 elmex 1.1 /* 1 = wall to left,
62 root 1.4 2 = wall to right,
63     4 = wall above
64     8 = wall below */
65 elmex 1.1 int surround_index = 0;
66 root 1.4
67     if ((i > 0) && layout[i - 1][j] == '#')
68     surround_index |= 1;
69     if ((i < RP->Xsize - 1) && layout[i + 1][j] == '#')
70     surround_index |= 2;
71     if ((j > 0) && layout[i][j - 1] == '#')
72     surround_index |= 4;
73     if ((j < RP->Ysize - 1) && layout[i][j + 1] == '#')
74     surround_index |= 8;
75 elmex 1.1 return surround_index;
76     }
77    
78    
79     /* like surround_flag, except it checks a map, not a layout.
80     * Since this is part of the random map code, presumption
81     * is that this is not a tiled map.
82     * What is considered blocking and not is somewhat hard coded.
83     */
84 root 1.4 int
85 root 1.13 surround_flag3 (maptile *map, sint16 i, sint16 j, random_map_params *RP)
86 root 1.4 {
87     /*
88     * 1 = blocked to left,
89     * 2 = blocked to right,
90     * 4 = blocked above
91     * 8 = blocked below
92     */
93    
94     int surround_index = 0;
95 elmex 1.1
96 elmex 1.20 // don't forget to update the mapspace!
97 root 1.21 if (i > 0) map->at (i - 1, j ).update ();
98     if (i < RP->Xsize - 1) map->at (i + 1, j ).update ();
99     if (j > 0) map->at (i , j - 1).update ();
100     if (j < RP->Ysize - 1) map->at (i , j + 1).update ();
101 elmex 1.20
102     if ((i > 0) && (GET_MAP_MOVE_BLOCK (map, i - 1, j) & MOVE_WALK))
103 root 1.4 surround_index |= 1;
104 elmex 1.20 if ((i < RP->Xsize - 1) && (GET_MAP_MOVE_BLOCK (map, i + 1, j) & MOVE_WALK))
105 root 1.4 surround_index |= 2;
106 elmex 1.20 if ((j > 0) && (GET_MAP_MOVE_BLOCK (map, i, j - 1) & MOVE_WALK))
107 root 1.4 surround_index |= 4;
108 elmex 1.20 if ((j < RP->Ysize - 1) && (GET_MAP_MOVE_BLOCK (map, i, j + 1) & MOVE_WALK))
109 root 1.4 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 root 1.13 surround_flag4 (maptile *map, int i, int j, random_map_params *RP)
118 root 1.4 {
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 root 1.13 make_map_walls (maptile *map, char **layout, char *w_style, random_map_params *RP)
142 root 1.4 {
143 root 1.14 char styledirname[1024];
144     char stylefilepath[1024];
145 root 1.7 maptile *style_map = 0;
146 root 1.4 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 root 1.17 if (!style_map)
155 root 1.4 return;
156    
157     /* fill up the map with the given floor style */
158 root 1.19 if ((the_wall = style_map->pick_random_object ()))
159 root 1.4 {
160     int i, j;
161     char *cp;
162     int joinedwalls = 0;
163     object *thiswall;
164    
165 root 1.22 sprintf (RP->wall_name, "%s", &the_wall->arch->archname);
166 root 1.4 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 root 1.13 pick_joined_wall (object *the_wall, char **layout, int i, int j, random_map_params *RP)
196 root 1.4 {
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 root 1.14 char wall_name[1024];
204 root 1.4 archetype *wall_arch = 0;
205 elmex 1.1
206 root 1.22 assign (wall_name, the_wall->arch->archname);
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 root 1.13 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 root 1.4 }
277 root 1.5 wall_arch = archetype::find (wall_name);
278 elmex 1.1
279 root 1.13 return wall_arch ? arch_to_object (wall_arch) : arch_to_object (the_wall->arch);
280 elmex 1.1 }
281 root 1.4
282 elmex 1.1
283     /* this takes a map, and changes an existing wall to match what's blocked
284     * around it, counting only doors and walls as blocked. If insert_flag is
285     * 1, it will go ahead and insert the wall into the map. If not, it
286     * will only return the wall which would belong there, and doesn't
287     * remove anything. It depends on the
288     * global, previously-set variable, "wall_name"
289     */
290    
291 root 1.4 object *
292 root 1.13 retrofit_joined_wall (maptile *the_map, int i, int j, int insert_flag, random_map_params *RP)
293 root 1.4 {
294     /* 1 = wall to left,
295     * 2 = wall to right,
296     * 4 = wall above
297     * 8 = wall below
298     */
299     int surround_index = 0;
300     int l;
301     object *the_wall = 0;
302     object *new_wall = 0;
303     archetype *wall_arch = 0;
304    
305     /* first find the wall */
306 root 1.10 for (the_wall = GET_MAP_OB (the_map, i, j); the_wall != NULL; the_wall = the_wall->above)
307 root 1.4 if ((the_wall->move_type & MOVE_WALK) && the_wall->type != EXIT && the_wall->type != TELEPORTER)
308     break;
309    
310    
311     /* if what we found is a door, don't remove it, set the_wall to NULL to
312     * signal that later.
313     */
314     if (the_wall && (the_wall->type == DOOR || the_wall->type == LOCKED_DOOR))
315     {
316     the_wall = NULL;
317     /* if we're not supposed to insert a new wall where there wasn't one,
318     * we've gotta leave.
319     */
320     if (insert_flag == 0)
321     return 0;
322 elmex 1.1 }
323 root 1.4 else if (the_wall == NULL)
324     return NULL;
325 elmex 1.1
326 root 1.4 /* canonicalize the wall name */
327     for (l = 0; l < 64; l++)
328     {
329     if (RP->wall_name[l] == '_')
330     {
331     RP->wall_name[l] = 0;
332     break;
333 root 1.2 }
334 elmex 1.1 }
335    
336 root 1.4 surround_index = surround_flag4 (the_map, i, j, RP);
337     /* This would be a lot cleaner to just us a lookup table,
338     * eg, wall_suffix[surround_index]
339     */
340     switch (surround_index)
341     {
342 root 1.13 case 0:
343     strcat (RP->wall_name, "_0");
344     break;
345     case 1:
346     strcat (RP->wall_name, "_1_3");
347     break;
348     case 2:
349     strcat (RP->wall_name, "_1_4");
350     break;
351     case 3:
352     strcat (RP->wall_name, "_2_1_2");
353     break;
354     case 4:
355     strcat (RP->wall_name, "_1_2");
356     break;
357     case 5:
358     strcat (RP->wall_name, "_2_2_4");
359     break;
360     case 6:
361     strcat (RP->wall_name, "_2_2_1");
362     break;
363     case 7:
364     strcat (RP->wall_name, "_3_1");
365     break;
366     case 8:
367     strcat (RP->wall_name, "_1_1");
368     break;
369     case 9:
370     strcat (RP->wall_name, "_2_2_3");
371     break;
372     case 10:
373     strcat (RP->wall_name, "_2_2_2");
374     break;
375     case 11:
376     strcat (RP->wall_name, "_3_3");
377     break;
378     case 12:
379     strcat (RP->wall_name, "_2_1_1");
380     break;
381     case 13:
382     strcat (RP->wall_name, "_3_4");
383     break;
384     case 14:
385     strcat (RP->wall_name, "_3_2");
386     break;
387     case 15:
388     strcat (RP->wall_name, "_4");
389     break;
390 elmex 1.1 }
391 root 1.11
392 root 1.5 wall_arch = archetype::find (RP->wall_name);
393 root 1.11
394     if (!wall_arch)
395 root 1.4 {
396     new_wall = arch_to_object (wall_arch);
397     new_wall->x = i;
398     new_wall->y = j;
399 root 1.11
400 root 1.4 if (the_wall && the_wall->map)
401     {
402 root 1.8 the_wall->remove ();
403 root 1.9 the_wall->destroy ();
404 root 1.2 }
405 root 1.11
406 root 1.4 the_wall->move_block = MOVE_ALL;
407     insert_ob_in_map (new_wall, the_map, new_wall, INS_NO_MERGE | INS_NO_WALK_ON);
408 elmex 1.1 }
409 root 1.11
410 root 1.4 return new_wall;
411 elmex 1.1 }