ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/exit.C
Revision: 1.27
Committed: Sun Jul 1 05:00:19 2007 UTC (16 years, 10 months ago) by root
Content type: text/plain
Branch: MAIN
CVS Tags: rel-2_2, rel-2_3
Changes since 1.26: +10 -11 lines
Log Message:
- upgrade crossfire trt to the GPL version 3 (hopefully correctly).
- add a single file covered by the GNU Affero General Public License
  (which is not yet released, so I used the current draft, which is
  legally a bit wavy, but its likely better than nothing as it expresses
  direct intent by the authors, and we can upgrade as soon as it has been
  released).
  * this should ensure availability of source code for the server at least
    and hopefully also archetypes and maps even when modified versions
    are not being distributed, in accordance of section 13 of the agplv3.

File Contents

# User Rev Content
1 elmex 1.1 /*
2 root 1.27 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.23 *
4 root 1.27 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.23 *
8 root 1.27 * Crossfire TRT is free software: you can redistribute it and/or modify
9 pippijn 1.23 * it under the terms of the GNU General Public License as published by
10 root 1.27 * the Free Software Foundation, either version 3 of the License, or
11 pippijn 1.23 * (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.27 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 pippijn 1.23 * GNU General Public License for more details.
17     *
18     * You should have received a copy of the GNU General Public License
19 root 1.27 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20     *
21     * The authors can be reached via e-mail to <crossfire@schmorp.de>
22 pippijn 1.23 */
23 elmex 1.1
24     #include <global.h>
25     #include <random_map.h>
26     #include <sproto.h>
27     #include <rproto.h>
28    
29     /* find a character in the layout. fx and fy are pointers to
30     where to find the char. fx,fy = -1 if not found. */
31 root 1.4 void
32 root 1.16 find_in_layout (int mode, char target, int *fx, int *fy, char **layout, random_map_params *RP)
33 root 1.4 {
34 elmex 1.1 int M;
35 root 1.4 int i, j;
36    
37     *fx = -1;
38     *fy = -1;
39 elmex 1.1
40     /* if a starting point isn't given, pick one */
41 root 1.4 if (mode < 1 || mode > 4)
42 root 1.24 M = rndm (4) + 1;
43 root 1.4 else
44     M = mode;
45 elmex 1.1
46     /* four different search starting points and methods so that
47     we can do something different for symmetrical maps instead of
48     the same damned thing every time. */
49 root 1.4 switch (M)
50     {
51 root 1.16 case 1:
52     { /* search from top left down/right */
53     for (i = 1; i < RP->Xsize; i++)
54     for (j = 1; j < RP->Ysize; j++)
55     {
56     if (layout[i][j] == target)
57     {
58     *fx = i;
59     *fy = j;
60     return;
61     }
62     }
63     break;
64     }
65     case 2:
66     { /* Search from top right down/left */
67     for (i = RP->Xsize - 2; i > 0; i--)
68     for (j = 1; j < RP->Ysize - 1; j++)
69     {
70     if (layout[i][j] == target)
71     {
72     *fx = i;
73     *fy = j;
74     return;
75     }
76     }
77     break;
78     }
79     case 3:
80     { /* search from bottom-left up-right */
81     for (i = 1; i < RP->Xsize - 1; i++)
82     for (j = RP->Ysize - 2; j > 0; j--)
83     {
84     if (layout[i][j] == target)
85     {
86     *fx = i;
87     *fy = j;
88     return;
89     }
90     }
91     break;
92     }
93     case 4:
94     { /* search from bottom-right up-left */
95     for (i = RP->Xsize - 2; i > 0; i--)
96     for (j = RP->Ysize - 2; j > 0; j--)
97     {
98     if (layout[i][j] == target)
99     {
100     *fx = i;
101     *fy = j;
102     return;
103     }
104     }
105     break;
106     }
107 root 1.4 }
108 elmex 1.1 }
109    
110     /* orientation: 0 means random,
111     1 means descending dungeon
112     2 means ascending dungeon
113     3 means rightward
114     4 means leftward
115     5 means northward
116     6 means southward
117     */
118 root 1.4 void
119 root 1.13 place_exits (maptile *map, char **maze, char *exitstyle, int orientation, random_map_params *RP)
120 root 1.4 {
121 root 1.18 char styledirname[1024];
122 root 1.16 maptile *style_map_down = 0; /* harder maze */
123     maptile *style_map_up = 0; /* easier maze */
124 elmex 1.1 object *the_exit_down; /* harder maze */
125     object *the_exit_up; /* easier maze */
126     object *random_sign; /* magic mouth saying this is a random map. */
127 root 1.4 int cx = -1, cy = -1; /* location of a map center */
128     int upx = -1, upy = -1; /* location of up exit */
129     int downx = -1, downy = -1;
130     int final_map_exit = 1;
131    
132     if (RP->exit_on_final_map)
133 root 1.16 if (strstr (RP->exit_on_final_map, "no"))
134     final_map_exit = 0;
135 elmex 1.1
136 root 1.16 if (!orientation)
137 root 1.24 orientation = rndm (6) + 1;
138 elmex 1.1
139 root 1.4 switch (orientation)
140 elmex 1.1 {
141 root 1.15 case 1:
142     {
143     sprintf (styledirname, "/styles/exitstyles/up");
144     style_map_up = find_style (styledirname, exitstyle, -1);
145     sprintf (styledirname, "/styles/exitstyles/down");
146     style_map_down = find_style (styledirname, exitstyle, -1);
147     break;
148     }
149    
150     case 2:
151     {
152     sprintf (styledirname, "/styles/exitstyles/down");
153     style_map_up = find_style (styledirname, exitstyle, -1);
154     sprintf (styledirname, "/styles/exitstyles/up");
155     style_map_down = find_style (styledirname, exitstyle, -1);
156     break;
157     }
158    
159     default:
160     {
161     sprintf (styledirname, "/styles/exitstyles/generic");
162     style_map_up = find_style (styledirname, exitstyle, -1);
163     style_map_down = style_map_up;
164     break;
165     }
166 elmex 1.1 }
167 root 1.15
168 root 1.4 if (style_map_up == 0)
169 root 1.5 the_exit_up = arch_to_object (archetype::find ("exit"));
170 root 1.16
171 root 1.4 else
172 elmex 1.1 {
173 root 1.4 object *tmp;
174    
175 root 1.25 tmp = style_map_up->pick_random_object ();
176 root 1.4 the_exit_up = arch_to_object (tmp->arch);
177 elmex 1.1 }
178    
179     /* we need a down exit only if we're recursing. */
180 root 1.4 if (RP->dungeon_level < RP->dungeon_depth || RP->final_map[0] != 0)
181     if (style_map_down == 0)
182 root 1.5 the_exit_down = arch_to_object (archetype::find ("exit"));
183 root 1.16
184 root 1.4 else
185     {
186     object *tmp;
187    
188 root 1.25 tmp = style_map_down->pick_random_object ();
189 root 1.4 the_exit_down = arch_to_object (tmp->arch);
190     }
191     else
192     the_exit_down = 0;
193 elmex 1.1
194     /* set up the up exit */
195     the_exit_up->stats.hp = RP->origin_x;
196     the_exit_up->stats.sp = RP->origin_y;
197 root 1.17 the_exit_up->slaying = RP->origin_map;
198 elmex 1.1
199     /* figure out where to put the entrance */
200     /* begin a logical block */
201     {
202     /* First, look for a '<' char */
203 root 1.4 find_in_layout (0, '<', &upx, &upy, maze, RP);
204 elmex 1.1
205     /* next, look for a C, the map center. */
206 root 1.4 find_in_layout (0, 'C', &cx, &cy, maze, RP);
207    
208 elmex 1.1 /* if we didn't find an up, find an empty place far from the center */
209 root 1.4 if (upx == -1 && cx != -1)
210     {
211     if (cx > RP->Xsize / 2)
212     upx = 1;
213 elmex 1.1 else
214 root 1.4 upx = RP->Xsize - 2;
215 root 1.17
216 root 1.4 if (cy > RP->Ysize / 2)
217     upy = 1;
218     else
219     upy = RP->Ysize - 2;
220 root 1.17
221 root 1.4 /* find an empty place far from the center */
222     if (upx == 1 && upy == 1)
223     find_in_layout (1, 0, &upx, &upy, maze, RP);
224     else if (upx == 1 && upy > 1)
225     find_in_layout (3, 0, &upx, &upy, maze, RP);
226     else if (upx > 1 && upy == 1)
227     find_in_layout (2, 0, &upx, &upy, maze, RP);
228     else if (upx > 1 && upy > 1)
229     find_in_layout (4, 0, &upx, &upy, maze, RP);
230     }
231    
232 elmex 1.1 /* no indication of where to place the exit, so just place it. */
233 root 1.4 if (upx == -1)
234     find_in_layout (0, 0, &upx, &upy, maze, RP);
235 elmex 1.1
236     the_exit_up->x = upx;
237     the_exit_up->y = upy;
238    
239     /* surround the exits with notices that this is a random map. */
240 root 1.17 for (int j = 1; j < 9; j++)
241 root 1.4 {
242     if (!wall_blocked (map, the_exit_up->x + freearr_x[j], the_exit_up->y + freearr_y[j]))
243     {
244     random_sign = get_archetype ("sign");
245     random_sign->x = the_exit_up->x + freearr_x[j];
246     random_sign->y = the_exit_up->y + freearr_y[j];
247    
248 root 1.17 char buf[8192];
249 root 1.4 sprintf (buf, "This is a random map.\nLevel: %d\n", (RP->dungeon_level) - 1);
250    
251     random_sign->msg = buf;
252     insert_ob_in_map (random_sign, map, NULL, 0);
253     }
254 elmex 1.1 }
255 root 1.17
256 elmex 1.1 /* Block the exit so things don't get dumped on top of it. */
257     the_exit_up->move_block = MOVE_ALL;
258    
259 root 1.4 insert_ob_in_map (the_exit_up, map, NULL, 0);
260     maze[the_exit_up->x][the_exit_up->y] = '<';
261 elmex 1.1
262     /* set the starting x,y for this map */
263 root 1.11 map->enter_x = the_exit_up->x;
264     map->enter_y = the_exit_up->y;
265 elmex 1.1
266     /* first, look for a '>' character */
267 root 1.4 find_in_layout (0, '>', &downx, &downy, maze, RP);
268 elmex 1.1 /* if no > is found use C */
269 root 1.4 if (downx == -1)
270     {
271     downx = cx;
272     downy = cy;
273     };
274    
275 elmex 1.1 /* make the other exit far away from this one if
276     there's no center. */
277 root 1.4 if (downx == -1)
278     {
279     if (upx > RP->Xsize / 2)
280     downx = 1;
281 elmex 1.1 else
282 root 1.4 downx = RP->Xsize - 2;
283 root 1.17
284 root 1.4 if (upy > RP->Ysize / 2)
285     downy = 1;
286     else
287     downy = RP->Ysize - 2;
288 root 1.17
289 root 1.4 /* find an empty place far from the entrance */
290     if (downx == 1 && downy == 1)
291     find_in_layout (1, 0, &downx, &downy, maze, RP);
292     else if (downx == 1 && downy > 1)
293     find_in_layout (3, 0, &downx, &downy, maze, RP);
294     else if (downx > 1 && downy == 1)
295     find_in_layout (2, 0, &downx, &downy, maze, RP);
296     else if (downx > 1 && downy > 1)
297     find_in_layout (4, 0, &downx, &downy, maze, RP);
298 root 1.17 }
299 root 1.4
300 elmex 1.1 /* no indication of where to place the down exit, so just place it */
301 root 1.4 if (downx == -1)
302     find_in_layout (0, 0, &downx, &downy, maze, RP);
303 root 1.16
304 root 1.4 if (the_exit_down)
305     {
306 root 1.21 char buf[16384];
307 root 1.4
308 root 1.22 int i = find_free_spot (the_exit_down, map, downx, downy, 1, SIZEOFFREE1 + 1);
309 root 1.4 the_exit_down->x = downx + freearr_x[i];
310     the_exit_down->y = downy + freearr_y[i];
311     RP->origin_x = the_exit_down->x;
312     RP->origin_y = the_exit_down->y;
313     write_map_parameters_to_string (buf, RP);
314     the_exit_down->msg = buf;
315 root 1.16
316 root 1.4 /* the identifier for making a random map. */
317 root 1.16 if (RP->dungeon_level >= RP->dungeon_depth && *RP->final_map)
318 root 1.4 {
319 root 1.7 maptile *new_map;
320 root 1.17 object *the_exit_back = arch_to_object (the_exit_up->arch);
321 root 1.4
322     /* load it */
323 root 1.19 if (!(new_map = maptile::find_sync (RP->final_map)))
324 root 1.4 return;
325    
326 root 1.19 new_map->load_sync ();
327    
328 root 1.4 the_exit_down->slaying = RP->final_map;
329    
330 root 1.17 for (object *tmp = new_map->at (new_map->enter_x, new_map->enter_y).bot; tmp; tmp = tmp->above)
331 root 1.4 /* Remove exit back to previous random map. There should only be one
332     * which is why we break out. To try to process more than one
333     * would require keeping a 'next' pointer, ad free_object kills tmp, which
334     * breaks the for loop.
335     */
336 root 1.17 if (tmp->type == EXIT && EXIT_PATH (tmp) && !strncmp (EXIT_PATH (tmp), "?random/", 8))
337 root 1.4 {
338 root 1.9 tmp->destroy ();
339 root 1.4 break;
340     }
341    
342     if (final_map_exit == 1)
343     {
344     /* setup the exit back */
345     the_exit_back->slaying = map->path;
346     the_exit_back->stats.hp = the_exit_down->x;
347     the_exit_back->stats.sp = the_exit_down->y;
348 root 1.11 the_exit_back->x = new_map->enter_x;
349     the_exit_back->y = new_map->enter_y;
350 root 1.4
351     insert_ob_in_map (the_exit_back, new_map, NULL, 0);
352     }
353     }
354     else
355     the_exit_down->slaying = "/!";
356 elmex 1.1
357 root 1.4 /* Block the exit so things don't get dumped on top of it. */
358     the_exit_down->move_block = MOVE_ALL;
359     insert_ob_in_map (the_exit_down, map, NULL, 0);
360     maze[the_exit_down->x][the_exit_down->y] = '>';
361 elmex 1.1 }
362 root 1.4 }
363 elmex 1.1 }
364    
365     /* this function unblocks the exits. We blocked them to
366     keep things from being dumped on them during the other
367     phases of random map generation. */
368 root 1.4 void
369 root 1.16 unblock_exits (maptile *map, char **maze, random_map_params *RP)
370 root 1.4 {
371     int i = 0, j = 0;
372 elmex 1.1 object *walk;
373    
374 root 1.4 for (i = 0; i < RP->Xsize; i++)
375     for (j = 0; j < RP->Ysize; j++)
376     if (maze[i][j] == '>' || maze[i][j] == '<')
377     {
378 root 1.10 for (walk = GET_MAP_OB (map, i, j); walk != NULL; walk = walk->above)
379 root 1.4 {
380     if (walk->move_block == MOVE_ALL && walk->type != LOCKED_DOOR)
381     {
382 elmex 1.26 walk->move_block = 0;
383 root 1.4 update_object (walk, UP_OBJ_CHANGE);
384     }
385     }
386 elmex 1.1 }
387     }
388 root 1.17