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 (16 years, 10 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

# Content
1 /*
2 * This file is part of Crossfire TRT, the Roguelike Realtime MORPG.
3 *
4 * 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 *
8 * Crossfire TRT is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (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 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * 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 */
23
24 /* Specials in this file:
25 included maps */
26
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 void
46 nuke_map_region (maptile *map, int xstart, int ystart, int xsize, int ysize)
47 {
48 int i, j;
49 object *tmp;
50
51 for (i = xstart; i < xstart + xsize; i++)
52 for (j = ystart; j < ystart + ysize; j++)
53 {
54 for (tmp = GET_MAP_OB (map, i, j); tmp != NULL; tmp = tmp->above)
55 {
56 if (!QUERY_FLAG (tmp, FLAG_IS_FLOOR))
57 {
58 if (tmp->head)
59 tmp = tmp->head;
60 tmp->remove ();
61 tmp->destroy ();
62 tmp = GET_MAP_OB (map, i, j);
63 }
64 if (tmp == NULL)
65 break;
66 }
67 }
68 }
69
70
71
72 /* copy in_map into dest_map at point x,y */
73
74
75 void
76 include_map_in_map (maptile *dest_map, maptile *in_map, int x, int y)
77 {
78 int i, j;
79 object *tmp;
80 object *new_ob;
81
82 /* First, splatter everything in the dest map at the location */
83 nuke_map_region (dest_map, x, y, in_map->width, in_map->height);
84
85 for (i = 0; i < in_map->width; i++)
86 for (j = 0; j < in_map->height; j++)
87 {
88 for (tmp = GET_MAP_OB (in_map, i, j); tmp != NULL; tmp = tmp->above)
89 {
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 }
103 }
104
105 int
106 find_spot_for_submap (maptile *map, char **layout, int *ix, int *iy, int xsize, int ysize)
107 {
108 int tries;
109 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 /* don't even try to place a submap into a map if the big map isn't
114 sufficiently large. */
115 if (2 * xsize > map->width || 2 * ysize > map->height)
116 return 0;
117
118 /* search a bit for a completely free spot. */
119 for (tries = 0; tries < 20; tries++)
120 {
121 /* pick a random location in the layout */
122 i = rndm (map->width - xsize - 2) + 1;
123 j = rndm (map->height - ysize - 2) + 1;
124 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
133 /* if we failed, relax the restrictions */
134
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 i = rndm (map->width - xsize - 2) + 1;
141 j = rndm (map->height - ysize - 2) + 1;
142 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 }
149 if (is_occupied)
150 return 0;
151 *ix = i;
152 *iy = j;
153 return 1;
154 }
155
156
157 void
158 place_fountain_with_specials (maptile *map)
159 {
160 int ix, iy, i = -1, tries = 0;
161 maptile *fountain_style = find_style ("/styles/misc", "fountains", -1);
162
163 if (!fountain_style)
164 {
165 LOG (llevError, "unable to load stylemap /styles/misc fountains\n");
166 return;
167 }
168
169 object *fountain = get_archetype ("fountain");
170 object *potion = object::create ();
171
172 fountain_style->pick_random_object ()->copy_to (potion);
173
174 while (i < 0 && tries < 10)
175 {
176 ix = rndm (map->width - 2) + 1;
177 iy = rndm (map->height - 2) + 1;
178 i = find_free_spot (fountain, map, ix, iy, 1, SIZEOFFREE1 + 1);
179 tries++;
180 }
181
182 if (i == -1)
183 { /* can't place fountain */
184 fountain->destroy ();
185 potion->destroy ();
186 return;
187 }
188
189 ix += freearr_x[i];
190 iy += freearr_y[i];
191 potion->face = fountain->face;
192 SET_FLAG (potion, FLAG_NO_PICK);
193 SET_FLAG (potion, FLAG_IDENTIFIED);
194 potion->name = potion->name_pl = "fountain";
195 potion->x = ix;
196 potion->y = iy;
197 potion->materialname = "adamantium";
198 fountain->x = ix;
199 fountain->y = iy;
200 insert_ob_in_map (fountain, map, NULL, 0);
201 insert_ob_in_map (potion, map, NULL, 0);
202 }
203
204 void
205 place_special_exit (maptile *map, int hole_type, random_map_params *RP)
206 {
207 int ix, iy, i = -1;
208 char buf[16384];
209 const char *style, *decor, *mon;
210 maptile *exit_style = find_style ("/styles/misc", "obscure_exits", -1);
211 int g_xsize, g_ysize;
212
213 if (!exit_style)
214 {
215 LOG (llevError, "unabel to load stylemap /styles/misc obscure_exits\n");
216 return;
217 }
218
219 object *the_exit = object::create ();
220
221 if (!exit_style)
222 return;
223
224 exit_style->pick_random_object ()->copy_to (the_exit);
225
226 while (i < 0)
227 {
228 ix = rndm (map->width - 2) + 1;
229 iy = rndm (map->height - 2) + 1;
230 i = find_free_spot (the_exit, map, ix, iy, 1, SIZEOFFREE1 + 1);
231 }
232
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 hole_type = rndm (NR_OF_HOLE_TYPES) + 1;
240
241 switch (hole_type)
242 {
243 case GLORY_HOLE: /* treasures */
244 {
245 g_xsize = rndm (3) + 4 + RP->difficulty / 4;
246 g_ysize = rndm (3) + 4 + RP->difficulty / 4;
247 style = "onion";
248 decor = "wealth2";
249 mon = "none";
250 break;
251 }
252
253 case ORC_ZONE: /* hole with orcs in it. */
254 {
255 g_xsize = rndm (3) + 4 + RP->difficulty / 4;
256 g_ysize = rndm (3) + 4 + RP->difficulty / 4;
257 style = "onion";
258 decor = "wealth2";
259 mon = "orc";
260 break;
261 }
262
263 case MINING_ZONE: /* hole with orcs in it. */
264 {
265 g_xsize = rndm (9) + 4 + RP->difficulty / 4;
266 g_ysize = rndm (9) + 4 + RP->difficulty / 4;
267 style = "maze";
268 decor = "minerals2";
269 mon = "none";
270 break;
271 }
272
273 default: /* undefined */
274 LOG (llevError, "place_special_exit: undefined hole type %d\n", hole_type);
275 return;
276 break;
277 }
278
279 /* 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 RMOPT_WALLS_ONLY, 0, 0, 1, RP->dungeon_level, RP->dungeon_level,
290 RP->difficulty, RP->difficulty, -1, 1, 0, 0, 0, 0, RP->difficulty_increase);
291 the_exit->slaying = "/!";
292 the_exit->msg = buf;
293
294 insert_ob_in_map (the_exit, map, NULL, 0);
295 }
296
297
298 void
299 place_specials_in_map (maptile *map, char **layout, random_map_params *RP)
300 {
301 maptile *special_map;
302 int ix, iy; /* map insertion locatons */
303 int special_type; /* type of special to make */
304
305 special_type = rndm (NUM_OF_SPECIAL_TYPES);
306
307 switch (special_type)
308 {
309 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
313 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
319 break;
320
321 case SPECIAL_FOUNTAIN:
322 /* Make a special fountain: an unpickable potion disguised as
323 a fountain, or rather, colocated with a fountain. */
324 place_fountain_with_specials (map);
325 break;
326
327 case SPECIAL_EXIT:
328 /* Make an exit to another random map, e.g. a gloryhole. */
329 place_special_exit (map, 0, RP);
330 break;
331 }
332
333 }