ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/deliantra/server/random_maps/treasure.C
(Generate patch)

Comparing deliantra/server/random_maps/treasure.C (file contents):
Revision 1.4 by root, Sun Sep 10 16:06:37 2006 UTC vs.
Revision 1.48 by root, Sun Nov 29 17:41:07 2009 UTC

1
2/* 1/*
3 * static char *rcsid_treasure_c = 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
4 * "$Id: treasure.C,v 1.4 2006/09/10 16:06:37 root Exp $"; 3 *
4 * Copyright (©) 2005,2006,2007,2008 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2001,2007 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992,2007 Frank Tore Johansen
7 *
8 * Deliantra is free software: you can redistribute it and/or modify it under
9 * the terms of the Affero GNU General Public License as published by the
10 * Free Software Foundation, either version 3 of the License, or (at your
11 * 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 Affero GNU General Public License
19 * and the GNU General Public License along with this program. If not, see
20 * <http://www.gnu.org/licenses/>.
21 *
22 * The authors can be reached via e-mail to <support@deliantra.net>
5 */ 23 */
6 24
7/*
8 CrossFire, A Multiplayer game for X-windows
9
10 Copyright (C) 2001 Mark Wedel & Crossfire Development Team
11 Copyright (C) 1992 Frank Tore Johansen
12
13 This program is free software; you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 2 of the License, or
16 (at your option) any later version.
17
18 This program is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with this program; if not, write to the Free Software
25 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26
27 The authors can be reached via e-mail at crossfire-devel@real-time.com
28*/
29
30/* placing treasure in maps, where appropriate. */ 25/* placing treasure in maps, where appropriate. */
31
32
33 26
34#include <global.h> 27#include <global.h>
35#include <random_map.h> 28#include <random_map.h>
36#include <rproto.h> 29#include <rproto.h>
37 30
48#define LAST_OPTION 64 /* set this to the last real option, for random */ 41#define LAST_OPTION 64 /* set this to the last real option, for random */
49 42
50#define NO_PASS_DOORS 0 43#define NO_PASS_DOORS 0
51#define PASS_DOORS 1 44#define PASS_DOORS 1
52 45
46static object *find_closest_monster (maptile *map, int x, int y, random_map_params *RP);
47static object *find_monster_in_room (maptile *map, int x, int y, random_map_params *RP);
48static void find_spot_in_room_recursive (char **layout, int x, int y, random_map_params *RP);
49static void find_spot_in_room (maptile *map, int x, int y, int *kx, int *ky, random_map_params *RP);
50static object *place_chest (int treasureoptions, int x, int y, maptile *map, maptile *style_map, int n_treasures, random_map_params *RP);
51static object **find_doors_in_room (maptile *map, int x, int y, random_map_params *RP);
52static void lock_and_hide_doors (object **doorlist, maptile *map, int opts, random_map_params *RP);
53static void find_enclosed_spot (maptile *map, int *cx, int *cy, random_map_params *RP);
54static object **surround_by_doors (maptile *map, char **layout, int x, int y, int opts);
55
56/* a macro to get a strongly centered random distribution,
57 from 0 to x, centered at x/2 */
58static int
59bc_random (int x)
60{
61 return (rmg_rndm (x) + rmg_rndm (x) + rmg_rndm (x)) / 3;
62}
63
64static object *
65gen_key (const shstr &keycode)
66{
67 /* get a key and set its keycode */
68 object *key = archetype::get (shstr_key_random_map);
69 key->slaying = keycode;
70 return key;
71}
72
73/* places keys in the map, preferably in something alive.
74 keycode is the key's code,
75 door_flag is either PASS_DOORS or NO_PASS_DOORS.
76 NO_PASS_DOORS won't cross doors or walls to keyplace, PASS_DOORS will.
77 if n_keys is 1, it will place 1 key. if n_keys >1, it will place 2-4 keys:
78 it will place 2-4 keys regardless of what nkeys is provided nkeys > 1.
79
80 The idea is that you call keyplace on x,y where a door is, and it'll make
81 sure a key is placed on both sides of the door.
82*/
83static int
84keyplace (maptile *map, int x, int y, const shstr &keycode, int door_flag, int n_keys, random_map_params *RP)
85{
86 int i, j;
87 int kx = 0, ky = 0;
88 object *the_keymaster; /* the monster that gets the key. */
89 object *the_key = gen_key (keycode);
90
91 if (door_flag == PASS_DOORS)
92 {
93 int tries = 0;
94
95 the_keymaster = 0;
96 while (tries < 15 && !the_keymaster)
97 {
98 i = rmg_rndm (RP->Xsize - 2) + 1;
99 j = rmg_rndm (RP->Ysize - 2) + 1;
100 tries++;
101 the_keymaster = find_closest_monster (map, i, j, RP);
102 }
103
104 /* if we don't find a good keymaster, drop the key on the ground. */
105 if (!the_keymaster)
106 {
107 int freeindex;
108
109 freeindex = -1;
110 for (tries = 0; tries < 15 && freeindex == -1; tries++)
111 {
112 kx = rmg_rndm (RP->Xsize - 2) + 1;
113 ky = rmg_rndm (RP->Ysize - 2) + 1;
114 freeindex = find_free_spot (the_key, map, kx, ky, 1, SIZEOFFREE1 + 1);
115 }
116
117 // can freeindex ever be < 0?
118 if (freeindex >= 0)
119 {
120 kx += freearr_x [freeindex];
121 ky += freearr_y [freeindex];
122 }
123 }
124 }
125 else
126 { /* NO_PASS_DOORS --we have to work harder. */
127 /* don't try to keyplace if we're sitting on a blocked square and
128 NO_PASS_DOORS is set. */
129 if (n_keys == 1)
130 {
131 if (wall_blocked (map, x, y))
132 {
133 the_key->destroy ();
134 return 0;
135 }
136
137 the_keymaster = find_monster_in_room (map, x, y, RP);
138 if (!the_keymaster) /* if fail, find a spot to drop the key. */
139 find_spot_in_room (map, x, y, &kx, &ky, RP);
140 }
141 else
142 {
143 int sum = 0; /* count how many keys we actually place */
144
145 /* I'm lazy, so just try to place in all 4 directions. */
146 sum += keyplace (map, x + 1, y, keycode, NO_PASS_DOORS, 1, RP);
147 sum += keyplace (map, x, y + 1, keycode, NO_PASS_DOORS, 1, RP);
148 sum += keyplace (map, x - 1, y, keycode, NO_PASS_DOORS, 1, RP);
149 sum += keyplace (map, x, y - 1, keycode, NO_PASS_DOORS, 1, RP);
150
151 if (sum < 2) /* we might have made a disconnected map-place more keys. */
152 { /* diagonally this time. */
153 keyplace (map, x + 1, y + 1, keycode, NO_PASS_DOORS, 1, RP);
154 keyplace (map, x + 1, y - 1, keycode, NO_PASS_DOORS, 1, RP);
155 keyplace (map, x - 1, y + 1, keycode, NO_PASS_DOORS, 1, RP);
156 keyplace (map, x - 1, y - 1, keycode, NO_PASS_DOORS, 1, RP);
157 }
158
159 the_key->destroy ();
160 return 1;
161 }
162 }
163
164 if (the_keymaster)
165 the_keymaster->head_ ()->insert (the_key);
166 else
167 {
168 the_key->x = kx;
169 the_key->y = ky;
170 insert_ob_in_map (the_key, map, NULL, 0);
171 }
172
173 return 1;
174}
53 175
54/* returns true if square x,y has P_NO_PASS set, which is true for walls 176/* returns true if square x,y has P_NO_PASS set, which is true for walls
55 * and doors but not monsters. 177 * and doors but not monsters.
56 * This function is not map tile aware. 178 * This function is not map tile aware.
57 */ 179 */
58
59int 180int
60wall_blocked (mapstruct *m, int x, int y) 181wall_blocked (maptile *m, int x, int y)
61{ 182{
62 int r;
63
64 if (OUT_OF_REAL_MAP (m, x, y)) 183 if (OUT_OF_REAL_MAP (m, x, y))
65 return 1; 184 return 1;
185
186 m->at (x, y).update ();
66 r = GET_MAP_MOVE_BLOCK (m, x, y) & ~MOVE_BLOCK_DEFAULT; 187 return GET_MAP_MOVE_BLOCK (m, x, y) & MOVE_WALK;
67 return r;
68} 188}
69 189
70/* place treasures in the map, given the 190/* place treasures in the map, given the
71map, (required) 191map, (required)
72layout, (required) 192layout, (required)
73treasure style (may be empty or NULL, or "none" to cause no treasure.) 193treasure style (may be empty or NULL, or "none" to cause no treasure.)
74treasureoptions (may be 0 for random choices or positive) 194treasureoptions (may be 0 for random choices or positive)
75*/ 195*/
76
77void 196void
78place_treasure (mapstruct *map, char **layout, char *treasure_style, int treasureoptions, RMParms * RP) 197place_treasure (maptile *map, char **layout, char *treasure_style, int treasureoptions, random_map_params *RP)
79{ 198{
80 char styledirname[256]; 199 char styledirname[1024];
81 char stylefilepath[256]; 200 char stylefilepath[1024];
82 mapstruct *style_map = 0; 201 maptile *style_map = 0;
83 int num_treasures; 202 int num_treasures;
84 203
85 /* bail out if treasure isn't wanted. */ 204 /* bail out if treasure isn't wanted. */
86 if (treasure_style) 205 if (treasure_style)
87 if (!strcmp (treasure_style, "none")) 206 if (!strcmp (treasure_style, "none"))
88 return; 207 return;
208
89 if (treasureoptions <= 0) 209 if (treasureoptions <= 0)
90 treasureoptions = RANDOM () % (2 * LAST_OPTION); 210 treasureoptions = rmg_rndm (2 * LAST_OPTION);
91 211
92 /* filter out the mutually exclusive options */ 212 /* filter out the mutually exclusive options */
93 if ((treasureoptions & RICH) && (treasureoptions & SPARSE)) 213 if ((treasureoptions & RICH) && (treasureoptions & SPARSE))
94 { 214 {
95 if (RANDOM () % 2) 215 if (rmg_rndm (2))
96 treasureoptions -= 1; 216 treasureoptions -= 1;
97 else 217 else
98 treasureoptions -= 2; 218 treasureoptions -= 2;
99 } 219 }
100 220
101 /* pick the number of treasures */ 221 /* pick the number of treasures */
102 if (treasureoptions & SPARSE) 222 if (treasureoptions & SPARSE)
103 num_treasures = BC_RANDOM (RP->total_map_hp / 600 + RP->difficulty / 2 + 1); 223 num_treasures = bc_random (RP->total_map_hp / 600 + RP->difficulty / 2 + 1);
104 else if (treasureoptions & RICH) 224 else if (treasureoptions & RICH)
105 num_treasures = BC_RANDOM (RP->total_map_hp / 150 + 2 * RP->difficulty + 1); 225 num_treasures = bc_random (RP->total_map_hp / 150 + 2 * RP->difficulty + 1);
106 else 226 else
107 num_treasures = BC_RANDOM (RP->total_map_hp / 300 + RP->difficulty + 1); 227 num_treasures = bc_random (RP->total_map_hp / 300 + RP->difficulty + 1);
108 228
109 if (num_treasures <= 0) 229 if (num_treasures <= 0)
110 return; 230 return;
111 231
112 /* get the style map */ 232 /* get the style map */
113 sprintf (styledirname, "%s", "/styles/treasurestyles"); 233 sprintf (styledirname, "%s", "/styles/treasurestyles");
114 sprintf (stylefilepath, "%s/%s", styledirname, treasure_style); 234 sprintf (stylefilepath, "%s/%s", styledirname, treasure_style);
115 style_map = find_style (styledirname, treasure_style, -1); 235 style_map = find_style (styledirname, treasure_style, -1);
116 236
237 if (!style_map)
238 {
239 LOG (llevError, "unable to load style map %s %s.\n", styledirname, treasure_style);
240 return;
241 }
242
117 /* all the treasure at one spot in the map. */ 243 /* all the treasure at one spot in the map. */
118 if (treasureoptions & CONCENTRATED) 244 if (treasureoptions & CONCENTRATED)
119 { 245 {
120
121 /* map_layout_style global, and is previously set */ 246 /* map_layout_style global, and is previously set */
122 switch (RP->map_layout_style) 247 switch (RP->map_layout_style)
123 { 248 {
124 case ONION_LAYOUT: 249 case LAYOUT_ONION:
125 case SPIRAL_LAYOUT: 250 case LAYOUT_SPIRAL:
126 case SQUARE_SPIRAL_LAYOUT: 251 case LAYOUT_SQUARE_SPIRAL:
127 { 252 {
128 int i, j; 253 int i, j;
129 254
130 /* search the onion for C's or '>', and put treasure there. */ 255 /* search the onion for C's or '>', and put treasure there. */
131 for (i = 0; i < RP->Xsize; i++) 256 for (i = 0; i < RP->Xsize; i++)
132 { 257 {
133 for (j = 0; j < RP->Ysize; j++) 258 for (j = 0; j < RP->Ysize; j++)
134 { 259 {
135 if (layout[i][j] == 'C' || layout[i][j] == '>') 260 if (layout[i][j] == 'C' || layout[i][j] == '>')
136 { 261 {
137 int tdiv = RP->symmetry_used; 262 int tdiv = RP->symmetry_used;
138 object **doorlist;
139 object *chest; 263 object *chest;
140 264
141 if (tdiv == 3) 265 if (tdiv == 3)
142 tdiv = 2; /* this symmetry uses a divisor of 2 */ 266 tdiv = 2; /* this symmetry uses a divisor of 2 */
267
143 /* don't put a chest on an exit. */ 268 /* don't put a chest on an exit. */
144 chest = place_chest (treasureoptions, i, j, map, style_map, num_treasures / tdiv, RP); 269 chest = place_chest (treasureoptions, i, j, map, style_map, num_treasures / tdiv, RP);
270
145 if (!chest) 271 if (!chest)
146 continue; /* if no chest was placed NEXT */ 272 continue; /* if no chest was placed NEXT */
273
147 if (treasureoptions & (DOORED | HIDDEN)) 274 if (treasureoptions & (DOORED | HIDDEN))
148 { 275 {
149 doorlist = find_doors_in_room (map, i, j, RP); 276 object **doorlist = find_doors_in_room (map, i, j, RP);
150 lock_and_hide_doors (doorlist, map, treasureoptions, RP); 277 lock_and_hide_doors (doorlist, map, treasureoptions, RP);
151 free (doorlist); 278 free (doorlist);
152 } 279 }
153 } 280 }
154 } 281 }
155 } 282 }
156 break; 283 break;
157 } 284 }
285
158 default: 286 default:
159 { 287 {
160 int i, j, tries; 288 int i, j, tries;
161 object *chest; 289 object *chest;
162 object **doorlist; 290 object **doorlist;
163 291
164 i = j = -1; 292 i = j = -1;
165 tries = 0; 293 tries = 0;
166 while (i == -1 && tries < 100) 294 while (i == -1 && tries < 100)
167 { 295 {
168 i = RANDOM () % (RP->Xsize - 2) + 1; 296 i = rmg_rndm (RP->Xsize - 2) + 1;
169 j = RANDOM () % (RP->Ysize - 2) + 1; 297 j = rmg_rndm (RP->Ysize - 2) + 1;
170 find_enclosed_spot (map, &i, &j, RP); 298 find_enclosed_spot (map, &i, &j, RP);
299
171 if (wall_blocked (map, i, j)) 300 if (wall_blocked (map, i, j))
172 i = -1; 301 i = -1;
302
173 tries++; 303 tries++;
174 } 304 }
305
175 chest = place_chest (treasureoptions, i, j, map, style_map, num_treasures, RP); 306 chest = place_chest (treasureoptions, i, j, map, style_map, num_treasures, RP);
307
176 if (!chest) 308 if (!chest)
177 return; 309 return;
310
178 i = chest->x; 311 i = chest->x;
179 j = chest->y; 312 j = chest->y;
180 if (treasureoptions & (DOORED | HIDDEN)) 313 if (treasureoptions & (DOORED | HIDDEN))
181 { 314 {
182 doorlist = surround_by_doors (map, layout, i, j, treasureoptions); 315 doorlist = surround_by_doors (map, layout, i, j, treasureoptions);
183 lock_and_hide_doors (doorlist, map, treasureoptions, RP); 316 lock_and_hide_doors (doorlist, map, treasureoptions, RP);
184 free (doorlist); 317 free (doorlist);
185 } 318 }
186 } 319 }
187 } 320 }
188 } 321 }
189 else 322 else
190 { /* DIFFUSE treasure layout */ 323 { /* DIFFUSE treasure layout */
191 int ti, i, j; 324 int ti, i, j;
192 325
193 for (ti = 0; ti < num_treasures; ti++) 326 for (ti = 0; ti < num_treasures; ti++)
194 { 327 {
195 i = RANDOM () % (RP->Xsize - 2) + 1; 328 i = rmg_rndm (RP->Xsize - 2) + 1;
196 j = RANDOM () % (RP->Ysize - 2) + 1; 329 j = rmg_rndm (RP->Ysize - 2) + 1;
197 place_chest (treasureoptions, i, j, map, style_map, 1, RP); 330 place_chest (treasureoptions, i, j, map, style_map, 1, RP);
198 } 331 }
199 } 332 }
200} 333}
201
202
203 334
204/* put a chest into the map, near x and y, with the treasure style 335/* put a chest into the map, near x and y, with the treasure style
205 determined (may be null, or may be a treasure list from lib/treasures, 336 determined (may be null, or may be a treasure list from lib/treasures,
206 if the global variable "treasurestyle" is set to that treasure list's name */ 337 if the global variable "treasurestyle" is set to that treasure list's name */
207 338static object *
208object *
209place_chest (int treasureoptions, int x, int y, mapstruct *map, mapstruct *style_map, int n_treasures, RMParms * RP) 339place_chest (int treasureoptions, int x, int y, maptile *map, maptile *style_map, int n_treasures, random_map_params *RP)
210{ 340{
211 object *the_chest;
212 int i, xl, yl;
213
214 the_chest = get_archetype ("chest"); /* was "chest_2" */ 341 object *the_chest = archetype::get (shstr_chest); /* was "chest_2" */
215 342
216 /* first, find a place to put the chest. */ 343 /* first, find a place to put the chest. */
217 i = find_first_free_spot (the_chest, map, x, y); 344 int i = find_first_free_spot (the_chest, map, x, y); // this call uses the main rng
218 if (i == -1) 345 if (i == -1)
219 { 346 {
220 free_object (the_chest); 347 the_chest->destroy ();
221 return NULL; 348 return NULL;
222 } 349 }
350
223 xl = x + freearr_x[i]; 351 int xl = x + freearr_x[i];
224 yl = y + freearr_y[i]; 352 int yl = y + freearr_y[i];
225 353
226 /* if the placement is blocked, return a fail. */ 354 /* if the placement is blocked, return a fail. */
227 if (wall_blocked (map, xl, yl)) 355 if (wall_blocked (map, xl, yl))
228 return 0; 356 return 0;
229
230 357
231 /* put the treasures in the chest. */ 358 /* put the treasures in the chest. */
232 /* if(style_map) { */ 359 /* if(style_map) { */
233#if 0 /* don't use treasure style maps for now! */ 360#if 0 /* don't use treasure style maps for now! */
234 int ti; 361 int ti;
237 treasurelist *tlist = find_treasurelist (RP->treasurestyle); 364 treasurelist *tlist = find_treasurelist (RP->treasurestyle);
238 365
239 if (tlist != NULL) 366 if (tlist != NULL)
240 for (ti = 0; ti < n_treasures; ti++) 367 for (ti = 0; ti < n_treasures; ti++)
241 { /* use the treasure list */ 368 { /* use the treasure list */
242 object *new_treasure = pick_random_object (style_map); 369 object *new_treasure = style_map->pick_random_object (rmg_rndm);
243 370
244 insert_ob_in_ob (arch_to_object (new_treasure->arch), the_chest); 371 insert_ob_in_ob (new_treasure->arch->instance (), the_chest);
245 } 372 }
246 else 373 else
247 { /* use the style map */ 374 { /* use the style map */
248 the_chest->randomitems = tlist; 375 the_chest->randomitems = tlist;
249 the_chest->stats.hp = n_treasures; 376 the_chest->stats.hp = n_treasures;
250 } 377 }
251#endif 378#endif
252 else
253 { /* neither style_map no treasure list given */ 379 { /* neither style_map no treasure list given */
254 treasurelist *tlist = find_treasurelist ("chest"); 380 treasurelist *tlist = treasurelist::find ("chest");
255 381
256 the_chest->randomitems = tlist; 382 the_chest->randomitems = tlist;
257 the_chest->stats.hp = n_treasures; 383 the_chest->stats.hp = n_treasures;
258 } 384 }
259 385
260 /* stick a trap in the chest if required */ 386 /* stick a trap in the chest if required */
261 if (treasureoptions & TRAPPED) 387 if (treasureoptions & TRAPPED)
262 { 388 {
263 mapstruct *trap_map = find_style ("/styles/trapstyles", "traps", -1); 389 maptile *trap_map = find_style ("/styles/trapstyles", "traps", -1);
264 object *the_trap;
265 390
266 if (trap_map) 391 if (trap_map)
267 { 392 {
268 the_trap = pick_random_object (trap_map); 393 object *the_trap = trap_map->pick_random_object (rmg_rndm);
394
269 the_trap->stats.Cha = 10 + RP->difficulty; 395 the_trap->stats.Cha = 10 + RP->difficulty;
270 the_trap->level = BC_RANDOM ((3 * RP->difficulty) / 2); 396 the_trap->level = bc_random ((3 * RP->difficulty) / 2);
397
271 if (the_trap) 398 if (the_trap)
272 { 399 {
273 object *new_trap; 400 object *new_trap = the_trap->arch->instance ();//TODO: why not clone?
274 401
275 new_trap = arch_to_object (the_trap->arch);
276 copy_object (new_trap, the_trap);
277 new_trap->x = x; 402 new_trap->x = x;
278 new_trap->y = y; 403 new_trap->y = y;
279 insert_ob_in_ob (new_trap, the_chest); 404 insert_ob_in_ob (new_trap, the_chest);
280 } 405 }
281 } 406 }
282 } 407 }
283 408
284 /* set the chest lock code, and call the keyplacer routine with 409 /* set the chest lock code, and call the keyplacer routine with
285 the lockcode. It's not worth bothering to lock the chest if 410 the lockcode. It's not worth bothering to lock the chest if
286 there's only 1 treasure.... */ 411 there's only 1 treasure.... */
287
288 if ((treasureoptions & KEYREQUIRED) && n_treasures > 1) 412 if ((treasureoptions & KEYREQUIRED) && n_treasures > 1)
289 { 413 {
290 char keybuf[256]; 414 the_chest->slaying = format ("RMG-%d-%d", (int)rmg_rndm (1000000000), (int)rmg_rndm (1000000000));
291
292 sprintf (keybuf, "%d", (int) RANDOM ());
293 the_chest->slaying = keybuf;
294 keyplace (map, x, y, keybuf, PASS_DOORS, 1, RP); 415 keyplace (map, x, y, the_chest->slaying, PASS_DOORS, 1, RP);
295 } 416 }
296 417
297 /* actually place the chest. */ 418 /* actually place the chest. */
298 the_chest->x = xl; 419 the_chest->x = xl;
299 the_chest->y = yl; 420 the_chest->y = yl;
300 insert_ob_in_map (the_chest, map, NULL, 0); 421 insert_ob_in_map (the_chest, map, NULL, 0);
301 return the_chest; 422 return the_chest;
302} 423}
303 424
304
305/* finds the closest monster and returns him, regardless of doors 425/* finds the closest monster and returns him, regardless of doors or walls */
306 or walls */ 426static object *
307object *
308find_closest_monster (mapstruct *map, int x, int y, RMParms * RP) 427find_closest_monster (maptile *map, int x, int y, random_map_params *RP)
309{ 428{
310 int i; 429 int i;
311 430
312 for (i = 0; i < SIZEOFFREE; i++) 431 for (i = 0; i < SIZEOFFREE; i++)
313 { 432 {
318 /* boundscheck */ 437 /* boundscheck */
319 if (lx >= 0 && ly >= 0 && lx < RP->Xsize && ly < RP->Ysize) 438 if (lx >= 0 && ly >= 0 && lx < RP->Xsize && ly < RP->Ysize)
320 /* don't bother searching this square unless the map says life exists. */ 439 /* don't bother searching this square unless the map says life exists. */
321 if (GET_MAP_FLAGS (map, lx, ly) & P_IS_ALIVE) 440 if (GET_MAP_FLAGS (map, lx, ly) & P_IS_ALIVE)
322 { 441 {
323 object *the_monster = get_map_ob (map, lx, ly); 442 object *the_monster = GET_MAP_OB (map, lx, ly);
324 443
325 for (; the_monster != NULL && (!QUERY_FLAG (the_monster, FLAG_MONSTER)); the_monster = the_monster->above); 444 for (; the_monster != NULL && (!QUERY_FLAG (the_monster, FLAG_MONSTER)); the_monster = the_monster->above);
326 if (the_monster && QUERY_FLAG (the_monster, FLAG_MONSTER)) 445 if (the_monster && QUERY_FLAG (the_monster, FLAG_MONSTER))
327 return the_monster; 446 return the_monster;
328 } 447 }
329 } 448 }
330 return NULL; 449 return NULL;
331} 450}
332 451
333
334
335/* places keys in the map, preferably in something alive.
336 keycode is the key's code,
337 door_flag is either PASS_DOORS or NO_PASS_DOORS.
338 NO_PASS_DOORS won't cross doors or walls to keyplace, PASS_DOORS will.
339 if n_keys is 1, it will place 1 key. if n_keys >1, it will place 2-4 keys:
340 it will place 2-4 keys regardless of what nkeys is provided nkeys > 1.
341
342 The idea is that you call keyplace on x,y where a door is, and it'll make
343 sure a key is placed on both sides of the door.
344*/
345
346int
347keyplace (mapstruct *map, int x, int y, char *keycode, int door_flag, int n_keys, RMParms * RP)
348{
349 int i, j;
350 int kx, ky;
351 object *the_keymaster; /* the monster that gets the key. */
352 object *the_key;
353
354 /* get a key and set its keycode */
355 the_key = get_archetype ("key2");
356 the_key->slaying = keycode;
357
358 if (door_flag == PASS_DOORS)
359 {
360 int tries = 0;
361
362 the_keymaster = NULL;
363 while (tries < 15 && the_keymaster == NULL)
364 {
365 i = (RANDOM () % (RP->Xsize - 2)) + 1;
366 j = (RANDOM () % (RP->Ysize - 2)) + 1;
367 tries++;
368 the_keymaster = find_closest_monster (map, i, j, RP);
369 }
370 /* if we don't find a good keymaster, drop the key on the ground. */
371 if (the_keymaster == NULL)
372 {
373 int freeindex;
374
375 freeindex = -1;
376 for (tries = 0; tries < 15 && freeindex == -1; tries++)
377 {
378 kx = (RANDOM () % (RP->Xsize - 2)) + 1;
379 ky = (RANDOM () % (RP->Ysize - 2)) + 1;
380 freeindex = find_first_free_spot (the_key, map, kx, ky);
381 }
382 if (freeindex != -1)
383 {
384 kx += freearr_x[freeindex];
385 ky += freearr_y[freeindex];
386 }
387 }
388 }
389 else
390 { /* NO_PASS_DOORS --we have to work harder. */
391 /* don't try to keyplace if we're sitting on a blocked square and
392 NO_PASS_DOORS is set. */
393 if (n_keys == 1)
394 {
395 if (wall_blocked (map, x, y))
396 return 0;
397 the_keymaster = find_monster_in_room (map, x, y, RP);
398 if (the_keymaster == NULL) /* if fail, find a spot to drop the key. */
399 find_spot_in_room (map, x, y, &kx, &ky, RP);
400 }
401 else
402 {
403 int sum = 0; /* count how many keys we actually place */
404
405 /* I'm lazy, so just try to place in all 4 directions. */
406 sum += keyplace (map, x + 1, y, keycode, NO_PASS_DOORS, 1, RP);
407 sum += keyplace (map, x, y + 1, keycode, NO_PASS_DOORS, 1, RP);
408 sum += keyplace (map, x - 1, y, keycode, NO_PASS_DOORS, 1, RP);
409 sum += keyplace (map, x, y - 1, keycode, NO_PASS_DOORS, 1, RP);
410 if (sum < 2) /* we might have made a disconnected map-place more keys. */
411 { /* diagnoally this time. */
412 keyplace (map, x + 1, y + 1, keycode, NO_PASS_DOORS, 1, RP);
413 keyplace (map, x + 1, y - 1, keycode, NO_PASS_DOORS, 1, RP);
414 keyplace (map, x - 1, y + 1, keycode, NO_PASS_DOORS, 1, RP);
415 keyplace (map, x - 1, y - 1, keycode, NO_PASS_DOORS, 1, RP);
416 }
417 return 1;
418 }
419 }
420
421 if (the_keymaster == NULL)
422 {
423 the_key->x = kx;
424 the_key->y = ky;
425 insert_ob_in_map (the_key, map, NULL, 0);
426 return 1;
427 }
428
429 insert_ob_in_ob (the_key, the_keymaster);
430 return 1;
431}
432
433
434
435/* both find_monster_in_room routines need to have access to this. */ 452/* both find_monster_in_room routines need to have access to this. */
436 453
437object *theMonsterToFind; 454static object *theMonsterToFind;
438 455
439/* a recursive routine which will return a monster, eventually,if there is one. 456/* a recursive routine which will return a monster, eventually,if there is one.
440 it does a check-off on the layout, converting 0's to 1's */ 457 it does a check-off on the layout, converting 0's to 1's */
441 458static object *
442object *
443find_monster_in_room_recursive (char **layout, mapstruct *map, int x, int y, RMParms * RP) 459find_monster_in_room_recursive (char **layout, maptile *map, int x, int y, random_map_params *RP)
444{ 460{
445 int i, j; 461 int i, j;
446 462
447 /* if we've found a monster already, leave */ 463 /* if we've found a monster already, leave */
448 if (theMonsterToFind != NULL) 464 if (theMonsterToFind != NULL)
459 /* check the current square for a monster. If there is one, 475 /* check the current square for a monster. If there is one,
460 set theMonsterToFind and return it. */ 476 set theMonsterToFind and return it. */
461 layout[x][y] = 1; 477 layout[x][y] = 1;
462 if (GET_MAP_FLAGS (map, x, y) & P_IS_ALIVE) 478 if (GET_MAP_FLAGS (map, x, y) & P_IS_ALIVE)
463 { 479 {
464 object *the_monster = get_map_ob (map, x, y); 480 object *the_monster = GET_MAP_OB (map, x, y);
465 481
466 /* check off this point */ 482 /* check off this point */
467 for (; the_monster != NULL && (!QUERY_FLAG (the_monster, FLAG_ALIVE)); the_monster = the_monster->above); 483 for (; the_monster != NULL && (!QUERY_FLAG (the_monster, FLAG_ALIVE)); the_monster = the_monster->above);
468 if (the_monster && QUERY_FLAG (the_monster, FLAG_ALIVE)) 484 if (the_monster && QUERY_FLAG (the_monster, FLAG_ALIVE))
469 { 485 {
471 return theMonsterToFind; 487 return theMonsterToFind;
472 } 488 }
473 } 489 }
474 490
475 /* now search all the 8 squares around recursively for a monster,in random order */ 491 /* now search all the 8 squares around recursively for a monster,in random order */
476 for (i = RANDOM () % 8, j = 0; j < 8 && theMonsterToFind == NULL; i++, j++) 492 for (i = rmg_rndm (8), j = 0; j < 8 && theMonsterToFind == NULL; i++, j++)
477 { 493 {
478 theMonsterToFind = find_monster_in_room_recursive (layout, map, x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1], RP); 494 theMonsterToFind = find_monster_in_room_recursive (layout, map, x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1], RP);
479 if (theMonsterToFind != NULL) 495 if (theMonsterToFind != NULL)
480 return theMonsterToFind; 496 return theMonsterToFind;
481 } 497 }
498
482 return theMonsterToFind; 499 return theMonsterToFind;
483} 500}
484
485 501
486/* sets up some data structures: the _recursive form does the 502/* sets up some data structures: the _recursive form does the
487 real work. */ 503 real work. */
488 504static object *
489object *
490find_monster_in_room (mapstruct *map, int x, int y, RMParms * RP) 505find_monster_in_room (maptile *map, int x, int y, random_map_params *RP)
491{ 506{
492 char **layout2; 507 Layout layout2 (RP);
493 int i, j; 508
509 layout2->clear ();
510
511 /* allocate and copy the layout, converting C to 0. */
512 for (int i = 0; i < layout2->w; i++)
513 for (int j = 0; j < layout2->h; j++)
514 if (wall_blocked (map, i, j))
515 layout2[i][j] = '#';
494 516
495 theMonsterToFind = 0; 517 theMonsterToFind = 0;
496 layout2 = (char **) calloc (sizeof (char *), RP->Xsize);
497 /* allocate and copy the layout, converting C to 0. */
498 for (i = 0; i < RP->Xsize; i++)
499 {
500 layout2[i] = (char *) calloc (sizeof (char), RP->Ysize);
501 for (j = 0; j < RP->Ysize; j++)
502 {
503 if (wall_blocked (map, i, j))
504 layout2[i][j] = '#';
505 }
506 }
507 theMonsterToFind = find_monster_in_room_recursive (layout2, map, x, y, RP); 518 theMonsterToFind = find_monster_in_room_recursive (layout2, map, x, y, RP);
508 519
509 /* deallocate the temp. layout */ 520 layout2.free ();
510 for (i = 0; i < RP->Xsize; i++)
511 {
512 free (layout2[i]);
513 }
514 free (layout2);
515 521
516 return theMonsterToFind; 522 return theMonsterToFind;
517} 523}
518 524
519
520
521
522/* a datastructure needed by find_spot_in_room and find_spot_in_room_recursive */ 525/* a datastructure needed by find_spot_in_room and find_spot_in_room_recursive */
523int *room_free_spots_x; 526static int *room_free_spots_x;
524int *room_free_spots_y; 527static int *room_free_spots_y;
525int number_of_free_spots_in_room; 528static int number_of_free_spots_in_room;
526 529
527/* the workhorse routine, which finds the free spots in a room: 530/* the workhorse routine, which finds the free spots in a room:
528a datastructure of free points is set up, and a position chosen from 531a datastructure of free points is set up, and a position chosen from
529that datastructure. */ 532that datastructure. */
530 533static void
531void
532find_spot_in_room_recursive (char **layout, int x, int y, RMParms * RP) 534find_spot_in_room_recursive (char **layout, int x, int y, random_map_params *RP)
533{ 535{
534 int i, j; 536 int i, j;
535 537
536 /* bounds check x and y */ 538 /* bounds check x and y */
537 if (!(x >= 0 && y >= 0 && x < RP->Xsize && y < RP->Ysize)) 539 if (!(x >= 0 && y >= 0 && x < RP->Xsize && y < RP->Ysize))
546 /* check off this point */ 548 /* check off this point */
547 layout[x][y] = 1; 549 layout[x][y] = 1;
548 room_free_spots_x[number_of_free_spots_in_room] = x; 550 room_free_spots_x[number_of_free_spots_in_room] = x;
549 room_free_spots_y[number_of_free_spots_in_room] = y; 551 room_free_spots_y[number_of_free_spots_in_room] = y;
550 number_of_free_spots_in_room++; 552 number_of_free_spots_in_room++;
553
551 /* now search all the 8 squares around recursively for free spots,in random order */ 554 /* now search all the 8 squares around recursively for free spots,in random order */
552 for (i = RANDOM () % 8, j = 0; j < 8 && theMonsterToFind == NULL; i++, j++) 555 for (i = rmg_rndm (8), j = 0; j < 8 && theMonsterToFind == NULL; i++, j++)
553 {
554 find_spot_in_room_recursive (layout, x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1], RP); 556 find_spot_in_room_recursive (layout, x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1], RP);
555 }
556 557
557} 558}
558 559
559/* find a random non-blocked spot in this room to drop a key. */ 560/* find a random non-blocked spot in this room to drop a key. */
560void 561static void
561find_spot_in_room (mapstruct *map, int x, int y, int *kx, int *ky, RMParms * RP) 562find_spot_in_room (maptile *map, int x, int y, int *kx, int *ky, random_map_params *RP)
562{ 563{
563 char **layout2; 564 char **layout2;
564 int i, j; 565 int i, j;
565 566
566 number_of_free_spots_in_room = 0; 567 number_of_free_spots_in_room = 0;
571 /* allocate and copy the layout, converting C to 0. */ 572 /* allocate and copy the layout, converting C to 0. */
572 for (i = 0; i < RP->Xsize; i++) 573 for (i = 0; i < RP->Xsize; i++)
573 { 574 {
574 layout2[i] = (char *) calloc (sizeof (char), RP->Ysize); 575 layout2[i] = (char *) calloc (sizeof (char), RP->Ysize);
575 for (j = 0; j < RP->Ysize; j++) 576 for (j = 0; j < RP->Ysize; j++)
576 {
577 if (wall_blocked (map, i, j)) 577 if (wall_blocked (map, i, j))
578 layout2[i][j] = '#'; 578 layout2[i][j] = '#';
579 }
580 } 579 }
581 580
582 /* setup num_free_spots and room_free_spots */ 581 /* setup num_free_spots and room_free_spots */
583 find_spot_in_room_recursive (layout2, x, y, RP); 582 find_spot_in_room_recursive (layout2, x, y, RP);
584 583
585 if (number_of_free_spots_in_room > 0) 584 if (number_of_free_spots_in_room > 0)
586 { 585 {
587 i = RANDOM () % number_of_free_spots_in_room; 586 i = rmg_rndm (number_of_free_spots_in_room);
588 *kx = room_free_spots_x[i]; 587 *kx = room_free_spots_x[i];
589 *ky = room_free_spots_y[i]; 588 *ky = room_free_spots_y[i];
590 } 589 }
591 590
592 /* deallocate the temp. layout */ 591 /* deallocate the temp. layout */
593 for (i = 0; i < RP->Xsize; i++) 592 for (i = 0; i < RP->Xsize; i++)
594 {
595 free (layout2[i]); 593 free (layout2[i]);
596 } 594
597 free (layout2); 595 free (layout2);
598 free (room_free_spots_x); 596 free (room_free_spots_x);
599 free (room_free_spots_y); 597 free (room_free_spots_y);
600} 598}
601 599
602 600
603/* searches the map for a spot with walls around it. The more 601/* searches the map for a spot with walls around it. The more
604 walls the better, but it'll settle for 1 wall, or even 0, but 602 walls the better, but it'll settle for 1 wall, or even 0, but
605 it'll return 0 if no FREE spots are found.*/ 603 it'll return 0 if no FREE spots are found.*/
606 604static void
607void
608find_enclosed_spot (mapstruct *map, int *cx, int *cy, RMParms * RP) 605find_enclosed_spot (maptile *map, int *cx, int *cy, random_map_params *RP)
609{ 606{
610 int x, y; 607 int x, y;
611 int i; 608 int i;
612 609
613 x = *cx; 610 x = *cx;
662 *cy = ly; 659 *cy = ly;
663 return; 660 return;
664 } 661 }
665 } 662 }
666 /* give up and return the closest free spot. */ 663 /* give up and return the closest free spot. */
667 i = find_first_free_spot (&find_archetype ("chest")->clone, map, x, y); 664 i = find_free_spot (archetype::find (shstr_chest), map, x, y, 1, SIZEOFFREE1 + 1);
668 if (i != -1 && i <= SIZEOFFREE1) 665
666 if (i != -1)
669 { 667 {
670 *cx = x + freearr_x[i]; 668 *cx = x + freearr_x[i];
671 *cy = y + freearr_y[i]; 669 *cy = y + freearr_y[i];
672 return; 670 }
671 else
673 } 672 {
674 /* indicate failure */ 673 /* indicate failure */
674 *cx = -1;
675 *cx = *cy = -1; 675 *cy = -1;
676 }
676} 677}
677 678
678 679static void
679void
680remove_monsters (int x, int y, mapstruct *map) 680remove_monsters (int x, int y, maptile *map)
681{ 681{
682 object *tmp; 682 for (object *tmp = GET_MAP_OB (map, x, y); tmp; )
683
684 for (tmp = get_map_ob (map, x, y); tmp != NULL; tmp = tmp->above)
685 if (QUERY_FLAG (tmp, FLAG_ALIVE))
686 { 683 {
687 if (tmp->head) 684 object *next = tmp->above;
688 tmp = tmp->head; 685
689 remove_ob (tmp); 686 if (tmp->flag [FLAG_ALIVE])
690 free_object (tmp); 687 tmp->head_ ()->destroy ();
691 tmp = get_map_ob (map, x, y); 688
692 if (tmp == NULL) 689 tmp = next;
693 break;
694 }; 690 }
695} 691}
696
697 692
698/* surrounds the point x,y by doors, so as to enclose something, like 693/* surrounds the point x,y by doors, so as to enclose something, like
699 a chest. It only goes as far as the 8 squares surrounding, and 694 a chest. It only goes as far as the 8 squares surrounding, and
700 it'll remove any monsters it finds.*/ 695 it'll remove any monsters it finds.*/
701 696static object **
702object **
703surround_by_doors (mapstruct *map, char **layout, int x, int y, int opts) 697surround_by_doors (maptile *map, char **layout, int x, int y, int opts)
704{ 698{
705 int i; 699 int i;
706 char *doors[2]; 700 const char *doors[2];
707 object **doorlist; 701 object **doorlist;
708 int ndoors_made = 0; 702 int ndoors_made = 0;
709 doorlist = (object **) calloc (9, sizeof (object *)); /* 9 doors so we can hold termination null */ 703 doorlist = (object **) calloc (9, sizeof (object *)); /* 9 doors so we can hold termination null */
710 704
711 /* this is a list we pick from, for horizontal and vertical doors */ 705 /* this is a list we pick from, for horizontal and vertical doors */
723 /* place doors in all the 8 adjacent unblocked squares. */ 717 /* place doors in all the 8 adjacent unblocked squares. */
724 for (i = 1; i < 9; i++) 718 for (i = 1; i < 9; i++)
725 { 719 {
726 int x1 = x + freearr_x[i], y1 = y + freearr_y[i]; 720 int x1 = x + freearr_x[i], y1 = y + freearr_y[i];
727 721
728 if (!wall_blocked (map, x1, y1) || layout[x1][y1] == '>') 722 if (!wall_blocked (map, x1, y1) && layout[x1][y1] == '>')
729 { /* place a door */ 723 { /* place a door */
724 remove_monsters (x1, y1, map);
725
730 object *new_door = get_archetype ((freearr_x[i] == 0) ? doors[1] : doors[0]); 726 object *new_door = get_archetype (freearr_x[i] == 0 ? doors[1] : doors[0]);
731 727 map->insert (new_door, x1, y1);
732 new_door->x = x + freearr_x[i];
733 new_door->y = y + freearr_y[i];
734 remove_monsters (new_door->x, new_door->y, map);
735 insert_ob_in_map (new_door, map, NULL, 0);
736 doorlist[ndoors_made] = new_door; 728 doorlist[ndoors_made] = new_door;
737 ndoors_made++; 729 ndoors_made++;
738 } 730 }
739 } 731 }
732
740 return doorlist; 733 return doorlist;
741} 734}
742 735
743
744/* returns the first door in this square, or NULL if there isn't a door. */ 736/* returns the first door in this square, or NULL if there isn't a door. */
745object * 737static object *
746door_in_square (mapstruct *map, int x, int y) 738door_in_square (maptile *map, int x, int y)
747{ 739{
748 object *tmp;
749
750 for (tmp = get_map_ob (map, x, y); tmp != NULL; tmp = tmp->above) 740 for (object *tmp = GET_MAP_OB (map, x, y); tmp; tmp = tmp->above)
751 if (tmp->type == DOOR || tmp->type == LOCKED_DOOR) 741 if (tmp->type == DOOR || tmp->type == LOCKED_DOOR)
752 return tmp; 742 return tmp;
743
753 return NULL; 744 return NULL;
754} 745}
755 746
756
757/* the workhorse routine, which finds the doors in a room */ 747/* the workhorse routine, which finds the doors in a room */
758void 748static void
759find_doors_in_room_recursive (char **layout, mapstruct *map, int x, int y, object **doorlist, int *ndoors, RMParms * RP) 749find_doors_in_room_recursive (char **layout, maptile *map, int x, int y, object **doorlist, int *ndoors, random_map_params *RP)
760{ 750{
761 int i, j; 751 int i, j;
762 object *door; 752 object *door;
763 753
764 /* bounds check x and y */ 754 /* bounds check x and y */
772 /* check off this point */ 762 /* check off this point */
773 if (layout[x][y] == '#') 763 if (layout[x][y] == '#')
774 { /* there could be a door here */ 764 { /* there could be a door here */
775 layout[x][y] = 1; 765 layout[x][y] = 1;
776 door = door_in_square (map, x, y); 766 door = door_in_square (map, x, y);
777 if (door != NULL) 767 if (door)
778 { 768 {
779 doorlist[*ndoors] = door; 769 doorlist[*ndoors] = door;
770
780 if (*ndoors > 254) /* eek! out of memory */ 771 if (*ndoors > 1022) /* eek! out of memory */
781 { 772 {
782 LOG (llevError, "find_doors_in_room_recursive:Too many doors for memory allocated!\n"); 773 LOG (llevError, "find_doors_in_room_recursive:Too many doors for memory allocated!\n");
783 return; 774 return;
784 } 775 }
776
785 *ndoors = *ndoors + 1; 777 *ndoors = *ndoors + 1;
786 } 778 }
787 } 779 }
788 else 780 else
789 { 781 {
790 layout[x][y] = 1; 782 layout[x][y] = 1;
783
791 /* now search all the 8 squares around recursively for free spots,in random order */ 784 /* now search all the 8 squares around recursively for free spots,in random order */
792 for (i = RANDOM () % 8, j = 0; j < 8 && theMonsterToFind == NULL; i++, j++) 785 for (i = rmg_rndm (8), j = 0; j < 8 && !theMonsterToFind; i++, j++)
793 { 786 find_doors_in_room_recursive (layout, map,
794 find_doors_in_room_recursive (layout, map, x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1], doorlist, ndoors, RP); 787 x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1],
795 } 788 doorlist, ndoors, RP);
796 } 789 }
797} 790}
798 791
799/* find a random non-blocked spot in this room to drop a key. */ 792/* find a random non-blocked spot in this room to drop a key. */
800object ** 793static object **
801find_doors_in_room (mapstruct *map, int x, int y, RMParms * RP) 794find_doors_in_room (maptile *map, int x, int y, random_map_params *RP)
802{ 795{
803 char **layout2;
804 object **doorlist;
805 int i, j; 796 int i, j;
806 int ndoors = 0; 797 int ndoors = 0;
807 798
808 doorlist = (object **) calloc (sizeof (int), 256); 799 object **doorlist = (object **)calloc (sizeof (int), 1024);
809 800
801 LayoutData layout2 (RP->Xsize, RP->Ysize);
802 layout2.clear ();
810 803
811 layout2 = (char **) calloc (sizeof (char *), RP->Xsize);
812 /* allocate and copy the layout, converting C to 0. */ 804 /* allocate and copy the layout, converting C to 0. */
813 for (i = 0; i < RP->Xsize; i++) 805 for (i = 0; i < RP->Xsize; i++)
814 {
815 layout2[i] = (char *) calloc (sizeof (char), RP->Ysize);
816 for (j = 0; j < RP->Ysize; j++) 806 for (j = 0; j < RP->Ysize; j++)
817 { 807 layout2[i][j] = wall_blocked (map, i, j) ? '#' : 0;
818 if (wall_blocked (map, i, j))
819 layout2[i][j] = '#';
820 }
821 }
822 808
823 /* setup num_free_spots and room_free_spots */ 809 /* setup num_free_spots and room_free_spots */
824 find_doors_in_room_recursive (layout2, map, x, y, doorlist, &ndoors, RP); 810 find_doors_in_room_recursive (layout2, map, x, y, doorlist, &ndoors, RP);
825 811
826 /* deallocate the temp. layout */
827 for (i = 0; i < RP->Xsize; i++)
828 {
829 free (layout2[i]);
830 }
831 free (layout2);
832 return doorlist; 812 return doorlist;
833} 813}
834
835
836 814
837/* locks and/or hides all the doors in doorlist, or does nothing if 815/* locks and/or hides all the doors in doorlist, or does nothing if
838 opts doesn't say to lock/hide doors. */ 816 opts doesn't say to lock/hide doors. */
839 817static void
840void
841lock_and_hide_doors (object **doorlist, mapstruct *map, int opts, RMParms * RP) 818lock_and_hide_doors (object **doorlist, maptile *map, int opts, random_map_params *RP)
842{ 819{
843 object *door; 820 object *door;
844 int i; 821 int i;
845 822
846 /* lock the doors and hide the keys. */ 823 /* lock the doors and hide the keys. */
847 824
848 if (opts & DOORED) 825 if (opts & DOORED)
849 { 826 {
850 for (i = 0, door = doorlist[0]; doorlist[i] != NULL; i++) 827 for (i = 0, door = doorlist[0]; doorlist[i]; i++)
851 { 828 {
852 object *new_door = get_archetype ("locked_door1"); 829 object *new_door = get_archetype (shstr_locked_door1);
853 char keybuf[256];
854 830
855 door = doorlist[i]; 831 door = doorlist[i];
856 new_door->face = door->face; 832 new_door->face = door->face;
857 new_door->x = door->x; 833 new_door->x = door->x;
858 new_door->y = door->y; 834 new_door->y = door->y;
859 remove_ob (door); 835 door->destroy ();
860 free_object (door);
861 doorlist[i] = new_door; 836 doorlist[i] = new_door;
862 insert_ob_in_map (new_door, map, NULL, 0); 837 insert_ob_in_map (new_door, map, NULL, 0);
863 sprintf (keybuf, "%d", (int) RANDOM ()); 838 new_door->slaying = format ("RMG-%d-%d", (int)rmg_rndm (1000000000), (int)rmg_rndm (1000000000));
864 new_door->slaying = keybuf;
865 keyplace (map, new_door->x, new_door->y, keybuf, NO_PASS_DOORS, 2, RP); 839 keyplace (map, new_door->x, new_door->y, new_door->slaying, NO_PASS_DOORS, 2, RP);
866 } 840 }
867 } 841 }
868 842
869 /* change the faces of the doors and surrounding walls to hide them. */ 843 /* change the faces of the doors and surrounding walls to hide them. */
870 if (opts & HIDDEN) 844 if (opts & HIDDEN)
879 { 853 {
880 retrofit_joined_wall (map, door->x - 1, door->y, 0, RP); 854 retrofit_joined_wall (map, door->x - 1, door->y, 0, RP);
881 retrofit_joined_wall (map, door->x + 1, door->y, 0, RP); 855 retrofit_joined_wall (map, door->x + 1, door->y, 0, RP);
882 retrofit_joined_wall (map, door->x, door->y - 1, 0, RP); 856 retrofit_joined_wall (map, door->x, door->y - 1, 0, RP);
883 retrofit_joined_wall (map, door->x, door->y + 1, 0, RP); 857 retrofit_joined_wall (map, door->x, door->y + 1, 0, RP);
858
884 door->face = wallface->face; 859 door->face = wallface->face;
885 if (!QUERY_FLAG (wallface, FLAG_REMOVED)) 860
886 remove_ob (wallface); 861 wallface->destroy ();
887 free_object (wallface);
888 } 862 }
889 } 863 }
890 } 864 }
891} 865}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines