ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/special.C
Revision: 1.24
Committed: Sun Jul 1 05:00:19 2007 UTC (19 years, 2 months ago) by root
Content type: text/plain
Branch: MAIN
Changes since 1.23: +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.24 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 pippijn 1.16 *
4 root 1.24 * Copyright (©) 2005,2006,2007 Marc Alexander Lehmann / Robin Redeker / the Crossfire TRT team
5     * Copyright (©) 2002,2007 Mark Wedel & Crossfire Development Team
6     * Copyright (©) 1992,2007 Frank Tore Johansen
7 pippijn 1.16 *
8 root 1.24 * Crossfire TRT 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.24 * 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.24 * 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.24 * 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.16 */
23 elmex 1.1
24     /* Specials in this file:
25 root 1.2 included maps */
26 elmex 1.1
27     #include <global.h>
28     #include <random_map.h>
29     #include <rproto.h>
30    
31     #define NUM_OF_SPECIAL_TYPES 4
32     #define NO_SPECIAL 0
33     #define SPECIAL_SUBMAP 1
34     #define SPECIAL_FOUNTAIN 2
35     #define SPECIAL_EXIT 3
36    
37     #define GLORY_HOLE 1
38     #define ORC_ZONE 2
39     #define MINING_ZONE 3
40     #define NR_OF_HOLE_TYPES 3
41    
42     /* clear map completely of all objects: a rectangular area of xsize, ysize
43     is cleared with the top left corner at xstart, ystart */
44    
45 root 1.4 void
46 root 1.6 nuke_map_region (maptile *map, int xstart, int ystart, int xsize, int ysize)
47 root 1.4 {
48     int i, j;
49 elmex 1.1 object *tmp;
50 root 1.4
51     for (i = xstart; i < xstart + xsize; i++)
52     for (j = ystart; j < ystart + ysize; j++)
53     {
54 root 1.9 for (tmp = GET_MAP_OB (map, i, j); tmp != NULL; tmp = tmp->above)
55 root 1.4 {
56     if (!QUERY_FLAG (tmp, FLAG_IS_FLOOR))
57     {
58     if (tmp->head)
59     tmp = tmp->head;
60 root 1.7 tmp->remove ();
61 root 1.8 tmp->destroy ();
62 root 1.9 tmp = GET_MAP_OB (map, i, j);
63 root 1.4 }
64     if (tmp == NULL)
65     break;
66     }
67 elmex 1.1 }
68     }
69    
70    
71    
72 root 1.4 /* copy in_map into dest_map at point x,y */
73 elmex 1.1
74    
75 root 1.4 void
76 root 1.6 include_map_in_map (maptile *dest_map, maptile *in_map, int x, int y)
77 root 1.4 {
78     int i, j;
79 elmex 1.1 object *tmp;
80     object *new_ob;
81 root 1.4
82 elmex 1.1 /* First, splatter everything in the dest map at the location */
83 root 1.10 nuke_map_region (dest_map, x, y, in_map->width, in_map->height);
84 root 1.4
85 root 1.10 for (i = 0; i < in_map->width; i++)
86     for (j = 0; j < in_map->height; j++)
87 root 1.4 {
88 root 1.9 for (tmp = GET_MAP_OB (in_map, i, j); tmp != NULL; tmp = tmp->above)
89 root 1.4 {
90     /* don't copy things with multiple squares: must be dealt with
91     specially. */
92     if (tmp->head != NULL)
93     continue;
94     new_ob = arch_to_object (tmp->arch);
95     copy_object_with_inv (tmp, new_ob);
96     if (QUERY_FLAG (tmp, FLAG_IS_LINKED))
97     add_button_link (new_ob, dest_map, tmp->path_attuned);
98     new_ob->x = i + x;
99     new_ob->y = j + y;
100     insert_multisquare_ob_in_map (new_ob, dest_map);
101     }
102 elmex 1.1 }
103     }
104    
105 root 1.4 int
106 root 1.6 find_spot_for_submap (maptile *map, char **layout, int *ix, int *iy, int xsize, int ysize)
107 root 1.4 {
108 elmex 1.1 int tries;
109 root 1.4 int i = 0, j = 0; /* initialization may not be needed but prevents compiler warnings */
110     int is_occupied = 0;
111     int l, m;
112    
113 elmex 1.1 /* don't even try to place a submap into a map if the big map isn't
114     sufficiently large. */
115 root 1.10 if (2 * xsize > map->width || 2 * ysize > map->height)
116 root 1.4 return 0;
117    
118 elmex 1.1 /* search a bit for a completely free spot. */
119 root 1.4 for (tries = 0; tries < 20; tries++)
120     {
121     /* pick a random location in the layout */
122 root 1.19 i = rndm (map->width - xsize - 2) + 1;
123     j = rndm (map->height - ysize - 2) + 1;
124 root 1.4 is_occupied = 0;
125     for (l = i; l < i + xsize; l++)
126     for (m = j; m < j + ysize; m++)
127     is_occupied |= layout[l][m];
128     if (!is_occupied)
129     break;
130     }
131    
132 elmex 1.1
133     /* if we failed, relax the restrictions */
134 root 1.4
135     if (is_occupied)
136     { /* failure, try a relaxed placer. */
137     /* pick a random location in the layout */
138     for (tries = 0; tries < 10; tries++)
139     {
140 root 1.19 i = rndm (map->width - xsize - 2) + 1;
141     j = rndm (map->height - ysize - 2) + 1;
142 root 1.4 is_occupied = 0;
143     for (l = i; l < i + xsize; l++)
144     for (m = j; m < j + ysize; m++)
145     if (layout[l][m] == 'C' || layout[l][m] == '>' || layout[l][m] == '<')
146     is_occupied |= 1;
147     }
148 elmex 1.1 }
149 root 1.4 if (is_occupied)
150     return 0;
151     *ix = i;
152     *iy = j;
153 elmex 1.1 return 1;
154 root 1.4 }
155 elmex 1.1
156    
157 root 1.4 void
158 root 1.6 place_fountain_with_specials (maptile *map)
159 root 1.4 {
160     int ix, iy, i = -1, tries = 0;
161 root 1.6 maptile *fountain_style = find_style ("/styles/misc", "fountains", -1);
162 root 1.18
163     if (!fountain_style)
164 root 1.19 {
165 pippijn 1.20 LOG (llevError, "unable to load stylemap /styles/misc fountains\n");
166 root 1.19 return;
167     }
168 root 1.18
169 root 1.4 object *fountain = get_archetype ("fountain");
170 root 1.8 object *potion = object::create ();
171    
172 root 1.22 fountain_style->pick_random_object ()->copy_to (potion);
173 root 1.4
174     while (i < 0 && tries < 10)
175     {
176 root 1.19 ix = rndm (map->width - 2) + 1;
177     iy = rndm (map->height - 2) + 1;
178 root 1.15 i = find_free_spot (fountain, map, ix, iy, 1, SIZEOFFREE1 + 1);
179 root 1.4 tries++;
180 root 1.8 }
181    
182 root 1.4 if (i == -1)
183     { /* can't place fountain */
184 root 1.8 fountain->destroy ();
185     potion->destroy ();
186 root 1.4 return;
187     }
188 root 1.8
189 elmex 1.1 ix += freearr_x[i];
190     iy += freearr_y[i];
191 root 1.4 potion->face = fountain->face;
192     SET_FLAG (potion, FLAG_NO_PICK);
193     SET_FLAG (potion, FLAG_IDENTIFIED);
194 root 1.3 potion->name = potion->name_pl = "fountain";
195 elmex 1.1 potion->x = ix;
196     potion->y = iy;
197 root 1.21 potion->materialname = "adamantium";
198 elmex 1.1 fountain->x = ix;
199     fountain->y = iy;
200 root 1.4 insert_ob_in_map (fountain, map, NULL, 0);
201     insert_ob_in_map (potion, map, NULL, 0);
202 elmex 1.1 }
203    
204 root 1.4 void
205 root 1.12 place_special_exit (maptile *map, int hole_type, random_map_params *RP)
206 root 1.4 {
207     int ix, iy, i = -1;
208 root 1.23 char buf[16384];
209     const char *style, *decor, *mon;
210 root 1.6 maptile *exit_style = find_style ("/styles/misc", "obscure_exits", -1);
211 root 1.4 int g_xsize, g_ysize;
212    
213 root 1.18 if (!exit_style)
214 root 1.19 {
215     LOG (llevError, "unabel to load stylemap /styles/misc obscure_exits\n");
216     return;
217     }
218 root 1.18
219 root 1.8 object *the_exit = object::create ();
220 root 1.4
221     if (!exit_style)
222     return;
223    
224 root 1.22 exit_style->pick_random_object ()->copy_to (the_exit);
225 root 1.4
226     while (i < 0)
227     {
228 root 1.19 ix = rndm (map->width - 2) + 1;
229     iy = rndm (map->height - 2) + 1;
230 root 1.15 i = find_free_spot (the_exit, map, ix, iy, 1, SIZEOFFREE1 + 1);
231 elmex 1.1 }
232 root 1.4
233     ix += freearr_x[i];
234     iy += freearr_y[i];
235     the_exit->x = ix;
236     the_exit->y = iy;
237    
238     if (!hole_type)
239 root 1.19 hole_type = rndm (NR_OF_HOLE_TYPES) + 1;
240 root 1.4
241     switch (hole_type)
242     {
243 root 1.12 case GLORY_HOLE: /* treasures */
244     {
245 root 1.17 g_xsize = rndm (3) + 4 + RP->difficulty / 4;
246     g_ysize = rndm (3) + 4 + RP->difficulty / 4;
247 root 1.12 style = "onion";
248     decor = "wealth2";
249     mon = "none";
250     break;
251     }
252 root 1.4
253 root 1.12 case ORC_ZONE: /* hole with orcs in it. */
254     {
255 root 1.17 g_xsize = rndm (3) + 4 + RP->difficulty / 4;
256     g_ysize = rndm (3) + 4 + RP->difficulty / 4;
257 root 1.12 style = "onion";
258     decor = "wealth2";
259     mon = "orc";
260     break;
261     }
262 root 1.4
263 root 1.12 case MINING_ZONE: /* hole with orcs in it. */
264     {
265 root 1.17 g_xsize = rndm (9) + 4 + RP->difficulty / 4;
266     g_ysize = rndm (9) + 4 + RP->difficulty / 4;
267 root 1.12 style = "maze";
268     decor = "minerals2";
269     mon = "none";
270     break;
271     }
272 root 1.4
273 root 1.12 default: /* undefined */
274     LOG (llevError, "place_special_exit: undefined hole type %d\n", hole_type);
275     return;
276     break;
277 elmex 1.1 }
278    
279 root 1.4 /* Need to be at least this size, otherwise the load
280     * code will generate new size values which are too large.
281     */
282     if (g_xsize < MIN_RANDOM_MAP_SIZE)
283     g_xsize = MIN_RANDOM_MAP_SIZE;
284     if (g_ysize < MIN_RANDOM_MAP_SIZE)
285     g_ysize = MIN_RANDOM_MAP_SIZE;
286    
287     write_parameters_to_string (buf, g_xsize, g_ysize, RP->wallstyle, RP->floorstyle, mon,
288     "none", style, decor, "none", RP->exitstyle, 0, 0, 0,
289 root 1.11 RMOPT_WALLS_ONLY, 0, 0, 1, RP->dungeon_level, RP->dungeon_level,
290 root 1.4 RP->difficulty, RP->difficulty, -1, 1, 0, 0, 0, 0, RP->difficulty_increase);
291     the_exit->slaying = "/!";
292     the_exit->msg = buf;
293 elmex 1.1
294 root 1.4 insert_ob_in_map (the_exit, map, NULL, 0);
295 elmex 1.1 }
296 root 1.4
297    
298     void
299 root 1.12 place_specials_in_map (maptile *map, char **layout, random_map_params *RP)
300 root 1.4 {
301 root 1.6 maptile *special_map;
302 root 1.4 int ix, iy; /* map insertion locatons */
303     int special_type; /* type of special to make */
304    
305 root 1.19 special_type = rndm (NUM_OF_SPECIAL_TYPES);
306 root 1.4
307     switch (special_type)
308     {
309 root 1.19 case SPECIAL_SUBMAP:
310     /* includes a special map into the random map being made. */
311     special_map = find_style ("/styles/specialmaps", 0, RP->difficulty);
312 root 1.4
313 root 1.19 if (!special_map)
314     return;
315    
316     if (find_spot_for_submap (map, layout, &ix, &iy, special_map->width, special_map->height))
317     include_map_in_map (map, special_map, ix, iy);
318 root 1.12
319 root 1.19 break;
320 root 1.4
321 root 1.19 case SPECIAL_FOUNTAIN:
322 root 1.12 /* Make a special fountain: an unpickable potion disguised as
323     a fountain, or rather, colocated with a fountain. */
324 root 1.19 place_fountain_with_specials (map);
325     break;
326 root 1.4
327 root 1.19 case SPECIAL_EXIT:
328 root 1.12 /* Make an exit to another random map, e.g. a gloryhole. */
329 root 1.19 place_special_exit (map, 0, RP);
330     break;
331 root 1.4 }
332 elmex 1.1
333     }