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.20 by root, Thu Jan 18 00:06:56 2007 UTC vs.
Revision 1.67 by root, Sat Nov 17 23:40:02 2018 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines