ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/wall.C
Revision: 1.12
Committed: Sat Dec 30 18:45:28 2006 UTC (17 years, 4 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.11: +7 -7 lines
Log Message:
random maps are nphard

File Contents

# User Rev Content
1 elmex 1.1 /*
2     CrossFire, A Multiplayer game for X-windows
3    
4     Copyright (C) 2002 Mark Wedel & Crossfire Development Team
5     Copyright (C) 1992 Frank Tore Johansen
6    
7     This program is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11    
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     GNU General Public License for more details.
16    
17     You should have received a copy of the GNU General Public License
18     along with this program; if not, write to the Free Software
19     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20    
21 root 1.6 The authors can be reached via e-mail at <crossfire@schmorp.de>
22 elmex 1.1 */
23    
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.12 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.12 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.12 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 root 1.4 if ((i > 0) && (GET_MAP_MOVE_BLOCK (map, i - 1, j) & ~MOVE_BLOCK_DEFAULT))
97     surround_index |= 1;
98     if ((i < RP->Xsize - 1) && (GET_MAP_MOVE_BLOCK (map, i + 1, j) & ~MOVE_BLOCK_DEFAULT))
99     surround_index |= 2;
100     if ((j > 0) && (GET_MAP_MOVE_BLOCK (map, i, j - 1) & ~MOVE_BLOCK_DEFAULT))
101     surround_index |= 4;
102     if ((j < RP->Ysize - 1) && (GET_MAP_MOVE_BLOCK (map, i, j + 1) & ~MOVE_BLOCK_DEFAULT))
103     surround_index |= 8;
104    
105     return surround_index;
106 elmex 1.1 }
107    
108     /* like surround_flag2, except it checks a map, not a layout. */
109    
110 root 1.4 int
111 root 1.12 surround_flag4 (maptile *map, int i, int j, random_map_params * RP)
112 root 1.4 {
113 elmex 1.1 /* 1 = blocked to left,
114 root 1.4 2 = blocked to right,
115     4 = blocked above
116     8 = blocked below */
117 elmex 1.1 int surround_index = 0;
118    
119 root 1.4 if ((i > 0) && wall_blocked (map, i - 1, j))
120     surround_index |= 1;
121     if ((i < RP->Xsize - 1) && wall_blocked (map, i + 1, j))
122     surround_index |= 2;
123     if ((j > 0) && wall_blocked (map, i, j - 1))
124     surround_index |= 4;
125     if ((j < RP->Ysize - 1) && wall_blocked (map, i, j + 1))
126     surround_index |= 8;
127 elmex 1.1
128     return surround_index;
129     }
130    
131     /* takes a map and a layout, and puts walls in the map (picked from
132 root 1.2 w_style) at '#' marks. */
133 elmex 1.1
134 root 1.4 void
135 root 1.12 make_map_walls (maptile *map, char **layout, char *w_style, random_map_params * RP)
136 root 1.4 {
137     char styledirname[256];
138     char stylefilepath[256];
139 root 1.7 maptile *style_map = 0;
140 root 1.4 object *the_wall;
141    
142     /* get the style map */
143     if (!strcmp (w_style, "none"))
144     return;
145     sprintf (styledirname, "%s", "/styles/wallstyles");
146     sprintf (stylefilepath, "%s/%s", styledirname, w_style);
147     style_map = find_style (styledirname, w_style, -1);
148     if (style_map == 0)
149     return;
150    
151     /* fill up the map with the given floor style */
152     if ((the_wall = pick_random_object (style_map)) != NULL)
153     {
154     int i, j;
155     char *cp;
156     int joinedwalls = 0;
157     object *thiswall;
158    
159     sprintf (RP->wall_name, "%s", &the_wall->arch->name);
160     if ((cp = strchr (RP->wall_name, '_')) != NULL)
161     {
162     *cp = 0;
163     joinedwalls = 1;
164 root 1.2 }
165    
166 root 1.4 for (i = 0; i < RP->Xsize; i++)
167     for (j = 0; j < RP->Ysize; j++)
168     {
169     if (layout[i][j] == '#')
170     {
171     if (joinedwalls)
172     thiswall = pick_joined_wall (the_wall, layout, i, j, RP);
173     else
174     thiswall = arch_to_object (the_wall->arch);
175     thiswall->x = i;
176     thiswall->y = j;
177     thiswall->move_block = MOVE_ALL;
178     insert_ob_in_map (thiswall, map, thiswall, INS_NO_MERGE | INS_NO_WALK_ON);
179     }
180     }
181 elmex 1.1 }
182     }
183    
184    
185     /* picks the right wall type for this square, to make it look nice,
186 root 1.2 and have everything nicely joined. It uses the layout. */
187 elmex 1.1
188 root 1.4 object *
189 root 1.12 pick_joined_wall (object *the_wall, char **layout, int i, int j, random_map_params * RP)
190 root 1.4 {
191 elmex 1.1 /* 1 = wall to left,
192 root 1.4 2 = wall to right,
193     4 = wall above
194     8 = wall below */
195     int surround_index = 0;
196 elmex 1.1 int l;
197     char wall_name[64];
198 root 1.4 archetype *wall_arch = 0;
199 elmex 1.1
200 root 1.4 strcpy (wall_name, the_wall->arch->name);
201 elmex 1.1
202     /* conventionally, walls are named like this:
203 root 1.4 wallname_wallcode, where wallcode indicates
204     a joinedness, and wallname is the wall.
205     this code depends on the convention for
206     finding the right wall. */
207 elmex 1.1
208     /* extract the wall name, which is the text up to the leading _ */
209 root 1.4 for (l = 0; l < 64; l++)
210     {
211     if (wall_name[l] == '_')
212     {
213     wall_name[l] = 0;
214     break;
215     }
216     }
217    
218     surround_index = surround_flag2 (layout, i, j, RP);
219    
220     switch (surround_index)
221     {
222     case 0:
223     strcat (wall_name, "_0");
224     break;
225     case 1:
226     strcat (wall_name, "_1_3");
227     break;
228     case 2:
229     strcat (wall_name, "_1_4");
230     break;
231     case 3:
232     strcat (wall_name, "_2_1_2");
233     break;
234     case 4:
235     strcat (wall_name, "_1_2");
236     break;
237     case 5:
238     strcat (wall_name, "_2_2_4");
239     break;
240     case 6:
241     strcat (wall_name, "_2_2_1");
242     break;
243     case 7:
244     strcat (wall_name, "_3_1");
245     break;
246     case 8:
247     strcat (wall_name, "_1_1");
248     break;
249     case 9:
250     strcat (wall_name, "_2_2_3");
251     break;
252     case 10:
253     strcat (wall_name, "_2_2_2");
254     break;
255     case 11:
256     strcat (wall_name, "_3_3");
257     break;
258     case 12:
259     strcat (wall_name, "_2_1_1");
260     break;
261     case 13:
262     strcat (wall_name, "_3_4");
263     break;
264     case 14:
265     strcat (wall_name, "_3_2");
266     break;
267     case 15:
268     strcat (wall_name, "_4");
269     break;
270     }
271 root 1.5 wall_arch = archetype::find (wall_name);
272 elmex 1.1
273 root 1.11 return wall_arch
274     ? arch_to_object (wall_arch)
275     : 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.12 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.2 case 0:
339 root 1.4 strcat (RP->wall_name, "_0");
340     break;
341 root 1.2 case 1:
342 root 1.4 strcat (RP->wall_name, "_1_3");
343     break;
344 root 1.2 case 2:
345 root 1.4 strcat (RP->wall_name, "_1_4");
346     break;
347 root 1.2 case 3:
348 root 1.4 strcat (RP->wall_name, "_2_1_2");
349     break;
350 root 1.2 case 4:
351 root 1.4 strcat (RP->wall_name, "_1_2");
352     break;
353 root 1.2 case 5:
354 root 1.4 strcat (RP->wall_name, "_2_2_4");
355     break;
356 root 1.2 case 6:
357 root 1.4 strcat (RP->wall_name, "_2_2_1");
358     break;
359 root 1.2 case 7:
360 root 1.4 strcat (RP->wall_name, "_3_1");
361     break;
362 root 1.2 case 8:
363 root 1.4 strcat (RP->wall_name, "_1_1");
364     break;
365 root 1.2 case 9:
366 root 1.4 strcat (RP->wall_name, "_2_2_3");
367     break;
368 root 1.2 case 10:
369 root 1.4 strcat (RP->wall_name, "_2_2_2");
370     break;
371 root 1.2 case 11:
372 root 1.4 strcat (RP->wall_name, "_3_3");
373     break;
374 root 1.2 case 12:
375 root 1.4 strcat (RP->wall_name, "_2_1_1");
376     break;
377 root 1.2 case 13:
378 root 1.4 strcat (RP->wall_name, "_3_4");
379     break;
380 root 1.2 case 14:
381 root 1.4 strcat (RP->wall_name, "_3_2");
382     break;
383 root 1.2 case 15:
384 root 1.4 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 }