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.56 by root, Fri Jul 2 03:40:14 2010 UTC vs.
Revision 1.62 by root, Tue Jan 3 11:25:34 2012 UTC

1/* 1/*
2 * This file is part of Deliantra, the Roguelike Realtime MMORPG. 2 * This file is part of Deliantra, the Roguelike Realtime MMORPG.
3 * 3 *
4 * Copyright (©) 2005,2006,2007,2008,2009,2010 Marc Alexander Lehmann / Robin Redeker / the Deliantra team 4 * Copyright (©) 2005,2006,2007,2008,2009,2010,2011,2012 Marc Alexander Lehmann / Robin Redeker / the Deliantra team
5 * Copyright (©) 2001 Mark Wedel & Crossfire Development Team 5 * Copyright (©) 2001 Mark Wedel & Crossfire Development Team
6 * Copyright (©) 1992 Frank Tore Johansen 6 * Copyright (©) 1992 Frank Tore Johansen
7 * 7 *
8 * Deliantra is free software: you can redistribute it and/or modify it under 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 9 * the terms of the Affero GNU General Public License as published by the
23 */ 23 */
24 24
25/* placing treasure in maps, where appropriate. */ 25/* placing treasure in maps, where appropriate. */
26 26
27#include <global.h> 27#include <global.h>
28#include <random_map.h> 28#include <rmg.h>
29#include <rproto.h> 29#include <rproto.h>
30 30
31/* some defines for various options which can be set. */ 31/* some defines for various options which can be set. */
32 32
33#define CONCENTRATED 1 /* all the treasure is at the C's for onions. */ 33#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 */ 41#define LAST_OPTION 64 /* set this to the last real option, for random */
42 42
43#define NO_PASS_DOORS 0 43#define NO_PASS_DOORS 0
44#define PASS_DOORS 1 44#define PASS_DOORS 1
45 45
46static object *find_closest_monster (maptile *map, int x, int y, random_map_params *RP); 46static object *find_closest_monster (maptile *map, int x, int y);
47static object *find_monster_in_room (maptile *map, int x, int y, random_map_params *RP); 47static object *find_monster_in_room (maptile *map, int x, int y);
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); 48static 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); 49static 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); 50static 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); 51static 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); 52static void find_enclosed_spot (maptile *map, int *cx, int *cy);
54static object **surround_by_doors (maptile *map, char **layout, int x, int y, int opts); 53static object **surround_by_doors (maptile *map, char **maze, int x, int y, int opts);
55 54
56/* a macro to get a strongly centered random distribution, 55/* a macro to get a strongly centered random distribution,
57 from 0 to x, centered at x/2 */ 56 from 0 to x, centered at x/2 */
58static int 57static int
59bc_random (int x) 58bc_random (int x)
79 78
80 The idea is that you call keyplace on x,y where a door is, and it'll make 79 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. 80 sure a key is placed on both sides of the door.
82*/ 81*/
83static int 82static int
84keyplace (maptile *map, int x, int y, const shstr &keycode, int door_flag, int n_keys, random_map_params *RP) 83keyplace (maptile *map, int x, int y, const shstr &keycode, int door_flag, int n_keys)
85{ 84{
86 int i, j; 85 int i, j;
87 int kx = 0, ky = 0; 86 int kx = 0, ky = 0;
88 object *the_keymaster; /* the monster that gets the key. */ 87 object *the_keymaster; /* the monster that gets the key. */
89 object *the_key = gen_key (keycode); 88 object *the_key = gen_key (keycode);
93 int tries = 0; 92 int tries = 0;
94 93
95 the_keymaster = 0; 94 the_keymaster = 0;
96 while (tries < 15 && !the_keymaster) 95 while (tries < 15 && !the_keymaster)
97 { 96 {
98 i = rmg_rndm (RP->Xsize - 2) + 1; 97 i = rmg_rndm (map->width - 2) + 1;
99 j = rmg_rndm (RP->Ysize - 2) + 1; 98 j = rmg_rndm (map->height - 2) + 1;
100 tries++; 99 tries++;
101 the_keymaster = find_closest_monster (map, i, j, RP); 100 the_keymaster = find_closest_monster (map, i, j);
102 } 101 }
103 102
104 /* if we don't find a good keymaster, drop the key on the ground. */ 103 /* if we don't find a good keymaster, drop the key on the ground. */
105 if (!the_keymaster) 104 if (!the_keymaster)
106 { 105 {
107 int freeindex; 106 int freeindex;
108 107
109 freeindex = -1; 108 freeindex = -1;
110 for (tries = 0; tries < 15 && freeindex == -1; tries++) 109 for (tries = 0; tries < 15 && freeindex == -1; tries++)
111 { 110 {
112 kx = rmg_rndm (RP->Xsize - 2) + 1; 111 kx = rmg_rndm (map->width - 2) + 1;
113 ky = rmg_rndm (RP->Ysize - 2) + 1; 112 ky = rmg_rndm (map->height - 2) + 1;
114 freeindex = rmg_find_free_spot (the_key, map, kx, ky, 1, SIZEOFFREE1 + 1); 113 freeindex = rmg_find_free_spot (the_key, map, kx, ky, 1, SIZEOFFREE1 + 1);
115 } 114 }
116 115
117 // can freeindex ever be < 0? 116 // can freeindex ever be < 0?
118 if (freeindex >= 0) 117 if (freeindex >= 0)
132 { 131 {
133 the_key->destroy (); 132 the_key->destroy ();
134 return 0; 133 return 0;
135 } 134 }
136 135
137 the_keymaster = find_monster_in_room (map, x, y, RP); 136 the_keymaster = find_monster_in_room (map, x, y);
138 if (!the_keymaster) /* if fail, find a spot to drop the key. */ 137 if (!the_keymaster) /* if fail, find a spot to drop the key. */
139 find_spot_in_room (map, x, y, &kx, &ky, RP); 138 find_spot_in_room (map, x, y, &kx, &ky);
140 } 139 }
141 else 140 else
142 { 141 {
143 int sum = 0; /* count how many keys we actually place */ 142 int sum = 0; /* count how many keys we actually place */
144 143
145 /* I'm lazy, so just try to place in all 4 directions. */ 144 /* 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); 145 sum += keyplace (map, x + 1, y, keycode, NO_PASS_DOORS, 1);
147 sum += keyplace (map, x, y + 1, keycode, NO_PASS_DOORS, 1, RP); 146 sum += keyplace (map, x, y + 1, keycode, NO_PASS_DOORS, 1);
148 sum += keyplace (map, x - 1, y, keycode, NO_PASS_DOORS, 1, RP); 147 sum += keyplace (map, x - 1, y, keycode, NO_PASS_DOORS, 1);
149 sum += keyplace (map, x, y - 1, keycode, NO_PASS_DOORS, 1, RP); 148 sum += keyplace (map, x, y - 1, keycode, NO_PASS_DOORS, 1);
150 149
151 if (sum < 2) /* we might have made a disconnected map-place more keys. */ 150 if (sum < 2) /* we might have made a disconnected map-place more keys. */
152 { /* diagonally this time. */ 151 { /* diagonally this time. */
153 keyplace (map, x + 1, y + 1, keycode, NO_PASS_DOORS, 1, RP); 152 keyplace (map, x + 1, y + 1, keycode, NO_PASS_DOORS, 1);
154 keyplace (map, x + 1, y - 1, keycode, NO_PASS_DOORS, 1, RP); 153 keyplace (map, x + 1, y - 1, keycode, NO_PASS_DOORS, 1);
155 keyplace (map, x - 1, y + 1, keycode, NO_PASS_DOORS, 1, RP); 154 keyplace (map, x - 1, y + 1, keycode, NO_PASS_DOORS, 1);
156 keyplace (map, x - 1, y - 1, keycode, NO_PASS_DOORS, 1, RP); 155 keyplace (map, x - 1, y - 1, keycode, NO_PASS_DOORS, 1);
157 } 156 }
158 157
159 the_key->destroy (); 158 the_key->destroy ();
160 return 1; 159 return 1;
161 } 160 }
187 return GET_MAP_MOVE_BLOCK (m, x, y) & MOVE_WALK; 186 return GET_MAP_MOVE_BLOCK (m, x, y) & MOVE_WALK;
188} 187}
189 188
190/* place treasures in the map, given the 189/* place treasures in the map, given the
191map, (required) 190map, (required)
192layout, (required) 191maze, (required)
193treasure style (may be empty or NULL, or "none" to cause no treasure.) 192treasure style (may be empty or NULL, or "none" to cause no treasure.)
194treasureoptions (may be 0 for random choices or positive) 193treasureoptions (may be 0 for random choices or positive)
195*/ 194*/
196void 195void
197place_treasure (maptile *map, char **layout, const char *treasure_style, int treasureoptions, random_map_params *RP) 196place_treasure (maptile *map, layout &maze, const char *treasure_style, int treasureoptions, random_map_params *RP)
198{ 197{
199 int num_treasures; 198 int num_treasures;
200 199
201 /* bail out if treasure isn't wanted. */ 200 /* bail out if treasure isn't wanted. */
202 if (treasure_style) 201 if (treasure_style)
250 /* search the onion for C's or '>', and put treasure there. */ 249 /* search the onion for C's or '>', and put treasure there. */
251 for (i = 0; i < RP->Xsize; i++) 250 for (i = 0; i < RP->Xsize; i++)
252 { 251 {
253 for (j = 0; j < RP->Ysize; j++) 252 for (j = 0; j < RP->Ysize; j++)
254 { 253 {
255 if (layout[i][j] == 'C' || layout[i][j] == '>') 254 if (maze[i][j] == 'C' || maze[i][j] == '>')
256 { 255 {
257 int tdiv = RP->symmetry_used; 256 int tdiv = RP->symmetry_used;
258 object *chest; 257 object *chest;
259 258
260 if (tdiv == 3) 259 if (tdiv == 3)
266 if (!chest) 265 if (!chest)
267 continue; /* if no chest was placed NEXT */ 266 continue; /* if no chest was placed NEXT */
268 267
269 if (treasureoptions & (DOORED | HIDDEN)) 268 if (treasureoptions & (DOORED | HIDDEN))
270 { 269 {
271 object **doorlist = find_doors_in_room (map, i, j, RP); 270 object **doorlist = find_doors_in_room (map, i, j);
272 lock_and_hide_doors (doorlist, map, treasureoptions, RP); 271 lock_and_hide_doors (doorlist, map, treasureoptions, RP);
273 free (doorlist); 272 free (doorlist);
274 } 273 }
275 } 274 }
276 } 275 }
288 tries = 0; 287 tries = 0;
289 while (i == -1 && tries < 100) 288 while (i == -1 && tries < 100)
290 { 289 {
291 i = rmg_rndm (RP->Xsize - 2) + 1; 290 i = rmg_rndm (RP->Xsize - 2) + 1;
292 j = rmg_rndm (RP->Ysize - 2) + 1; 291 j = rmg_rndm (RP->Ysize - 2) + 1;
292
293 find_enclosed_spot (map, &i, &j, RP); 293 find_enclosed_spot (map, &i, &j);
294 294
295 if (wall_blocked (map, i, j)) 295 if (wall_blocked (map, i, j))
296 i = -1; 296 i = -1;
297 297
298 tries++; 298 tries++;
305 305
306 i = chest->x; 306 i = chest->x;
307 j = chest->y; 307 j = chest->y;
308 if (treasureoptions & (DOORED | HIDDEN)) 308 if (treasureoptions & (DOORED | HIDDEN))
309 { 309 {
310 doorlist = surround_by_doors (map, layout, i, j, treasureoptions); 310 doorlist = surround_by_doors (map, maze, i, j, treasureoptions);
311 lock_and_hide_doors (doorlist, map, treasureoptions, RP); 311 lock_and_hide_doors (doorlist, map, treasureoptions, RP);
312 free (doorlist); 312 free (doorlist);
313 } 313 }
314 } 314 }
315 } 315 }
316 } 316 }
317 else 317 else
318 { /* DIFFUSE treasure layout */ 318 { /* DIFFUSE treasure maze */
319 int ti, i, j; 319 int ti, i, j;
320 320
321 for (ti = 0; ti < num_treasures; ti++) 321 for (ti = 0; ti < num_treasures; ti++)
322 { 322 {
323 i = rmg_rndm (RP->Xsize - 2) + 1; 323 i = rmg_rndm (RP->Xsize - 2) + 1;
405 the lockcode. It's not worth bothering to lock the chest if 405 the lockcode. It's not worth bothering to lock the chest if
406 there's only 1 treasure.... */ 406 there's only 1 treasure.... */
407 if ((treasureoptions & KEYREQUIRED) && n_treasures > 1) 407 if ((treasureoptions & KEYREQUIRED) && n_treasures > 1)
408 { 408 {
409 the_chest->slaying = format ("RMG-%d-%d", (int)rmg_rndm (1000000000), (int)rmg_rndm (1000000000)); 409 the_chest->slaying = format ("RMG-%d-%d", (int)rmg_rndm (1000000000), (int)rmg_rndm (1000000000));
410 keyplace (map, x, y, the_chest->slaying, PASS_DOORS, 1, RP); 410 keyplace (map, x, y, the_chest->slaying, PASS_DOORS, 1);
411 } 411 }
412 412
413 /* actually place the chest. */ 413 /* actually place the chest. */
414 the_chest->x = xl; 414 the_chest->x = xl;
415 the_chest->y = yl; 415 the_chest->y = yl;
417 return the_chest; 417 return the_chest;
418} 418}
419 419
420/* finds the closest monster and returns him, regardless of doors or walls */ 420/* finds the closest monster and returns him, regardless of doors or walls */
421static object * 421static object *
422find_closest_monster (maptile *map, int x, int y, random_map_params *RP) 422find_closest_monster (maptile *map, int x, int y)
423{ 423{
424 int i; 424 int i;
425 425
426 for (i = 0; i < SIZEOFFREE; i++) 426 for (i = 0; i < SIZEOFFREE; i++)
427 { 427 {
428 int lx, ly; 428 int lx, ly;
429 429
430 lx = x + freearr_x[i]; 430 lx = x + freearr_x[i];
431 ly = y + freearr_y[i]; 431 ly = y + freearr_y[i];
432 /* boundscheck */ 432 /* boundscheck */
433 if (lx >= 0 && ly >= 0 && lx < RP->Xsize && ly < RP->Ysize) 433 if (lx >= 0 && ly >= 0 && lx < map->width && ly < map->height)
434 /* don't bother searching this square unless the map says life exists. */ 434 /* don't bother searching this square unless the map says life exists. */
435 if (GET_MAP_FLAGS (map, lx, ly) & P_IS_ALIVE) 435 if (GET_MAP_FLAGS (map, lx, ly) & P_IS_ALIVE)
436 { 436 {
437 object *the_monster = GET_MAP_OB (map, lx, ly); 437 object *the_monster = GET_MAP_OB (map, lx, ly);
438 438
439 for (; the_monster != NULL && (!the_monster->flag [FLAG_MONSTER]); the_monster = the_monster->above); 439 for (; the_monster && !the_monster->flag [FLAG_MONSTER]; the_monster = the_monster->above)
440 ;
441
440 if (the_monster && the_monster->flag [FLAG_MONSTER]) 442 if (the_monster && the_monster->flag [FLAG_MONSTER])
441 return the_monster; 443 return the_monster;
442 } 444 }
443 } 445 }
444 return NULL; 446 return NULL;
447/* both find_monster_in_room routines need to have access to this. */ 449/* both find_monster_in_room routines need to have access to this. */
448 450
449static object *theMonsterToFind; 451static object *theMonsterToFind;
450 452
451/* a recursive routine which will return a monster, eventually,if there is one. 453/* a recursive routine which will return a monster, eventually,if there is one.
452 it does a check-off on the layout, converting 0's to 1's */ 454 it does a check-off on the maze, converting 0's to 1's */
453static object * 455static object *
454find_monster_in_room_recursive (char **layout, maptile *map, int x, int y, random_map_params *RP) 456find_monster_in_room_recursive (layout &maze, maptile *map, int x, int y)
455{ 457{
456 int i, j; 458 int i, j;
457 459
458 /* if we've found a monster already, leave */ 460 /* if we've found a monster already, leave */
459 if (theMonsterToFind != NULL) 461 if (theMonsterToFind != NULL)
460 return theMonsterToFind; 462 return theMonsterToFind;
461 463
462 /* bounds check x and y */ 464 /* bounds check x and y */
463 if (!(x >= 0 && y >= 0 && x < RP->Xsize && y < RP->Ysize)) 465 if (!(x >= 0 && y >= 0 && x < maze.w && y < maze.h))
464 return theMonsterToFind; 466 return theMonsterToFind;
465 467
466 /* if the square is blocked or searched already, leave */ 468 /* if the square is blocked or searched already, leave */
467 if (layout[x][y] != 0) 469 if (maze[x][y] != 0)
468 return theMonsterToFind; /* might be NULL, that's fine. */ 470 return theMonsterToFind; /* might be NULL, that's fine. */
469 471
470 /* check the current square for a monster. If there is one, 472 /* check the current square for a monster. If there is one,
471 set theMonsterToFind and return it. */ 473 set theMonsterToFind and return it. */
472 layout[x][y] = 1; 474 maze[x][y] = 1;
473 if (GET_MAP_FLAGS (map, x, y) & P_IS_ALIVE) 475 if (GET_MAP_FLAGS (map, x, y) & P_IS_ALIVE)
474 { 476 {
475 object *the_monster = GET_MAP_OB (map, x, y); 477 object *the_monster = GET_MAP_OB (map, x, y);
476 478
477 /* check off this point */ 479 /* check off this point */
478 for (; the_monster != NULL && (!the_monster->flag [FLAG_ALIVE]); the_monster = the_monster->above); 480 for (; the_monster && (!the_monster->flag [FLAG_ALIVE]); the_monster = the_monster->above);
479 if (the_monster && the_monster->flag [FLAG_ALIVE]) 481 if (the_monster && the_monster->flag [FLAG_ALIVE])
480 { 482 {
481 theMonsterToFind = the_monster; 483 theMonsterToFind = the_monster;
482 return theMonsterToFind; 484 return theMonsterToFind;
483 } 485 }
484 } 486 }
485 487
486 /* now search all the 8 squares around recursively for a monster,in random order */ 488 /* now search all the 8 squares around recursively for a monster,in random order */
487 for (i = rmg_rndm (8), j = 0; j < 8 && theMonsterToFind == NULL; i++, j++) 489 for (i = rmg_rndm (8), j = 0; j < 8 && !theMonsterToFind; i++, j++)
488 { 490 {
489 theMonsterToFind = find_monster_in_room_recursive (layout, map, x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1], RP); 491 theMonsterToFind = find_monster_in_room_recursive (maze, map, x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1]);
490 if (theMonsterToFind != NULL) 492 if (theMonsterToFind)
491 return theMonsterToFind; 493 return theMonsterToFind;
492 } 494 }
493 495
494 return theMonsterToFind; 496 return theMonsterToFind;
495} 497}
496 498
497/* sets up some data structures: the _recursive form does the 499/* sets up some data structures: the _recursive form does the
498 real work. */ 500 real work. */
499static object * 501static object *
500find_monster_in_room (maptile *map, int x, int y, random_map_params *RP) 502find_monster_in_room (maptile *map, int x, int y)
501{ 503{
502 Layout layout2 (map->width, map->height); 504 layout layout2 (map->width, map->height);
503 505
504 // find walls 506 // find walls
505 for (int i = 0; i < layout2.w; i++) 507 for (int i = 0; i < layout2.w; i++)
506 for (int j = 0; j < layout2.h; j++) 508 for (int j = 0; j < layout2.h; j++)
507 layout2[i][j] = wall_blocked (map, i, j) ? '#' : 0; 509 layout2[i][j] = wall_blocked (map, i, j) ? '#' : 0;
508 510
509 theMonsterToFind = 0; 511 theMonsterToFind = 0;
510 theMonsterToFind = find_monster_in_room_recursive (layout2, map, x, y, RP); 512 theMonsterToFind = find_monster_in_room_recursive (layout2, map, x, y);
511 513
512 return theMonsterToFind; 514 return theMonsterToFind;
513} 515}
514
515/* a datastructure needed by find_spot_in_room and find_spot_in_room_recursive */
516static int *room_free_spots_x;
517static int *room_free_spots_y;
518static int number_of_free_spots_in_room;
519 516
520/* the workhorse routine, which finds the free spots in a room: 517/* the workhorse routine, which finds the free spots in a room:
521a datastructure of free points is set up, and a position chosen from 518a datastructure of free points is set up, and a position chosen from
522that datastructure. */ 519that datastructure. */
523static void 520static void
524find_spot_in_room_recursive (char **layout, int x, int y, random_map_params *RP) 521find_spot_in_room_recursive (layout &maze, fixed_stack<point> &spots, int x, int y)
525{ 522{
526 int i, j;
527
528 /* bounds check x and y */ 523 /* bounds check x and y */
529 if (!(x >= 0 && y >= 0 && x < RP->Xsize && y < RP->Ysize)) 524 if (!(x >= 0 && y >= 0 && x < maze.w && y < maze.h))
530 return; 525 return;
531 526
532 /* if the square is blocked or searched already, leave */ 527 /* if the square is blocked or searched already, leave */
533 if (layout[x][y] != 0) 528 if (maze[x][y] != 0)
534 return; 529 return;
535 530
536 /* set the current square as checked, and add it to the list. 531 /* set the current square as checked, and add it to the list.
537 set theMonsterToFind and return it. */ 532 set theMonsterToFind and return it. */
538 /* check off this point */ 533 /* check off this point */
539 layout[x][y] = 1; 534 maze[x][y] = 1;
540 room_free_spots_x[number_of_free_spots_in_room] = x; 535 spots.push (point (x, y));
541 room_free_spots_y[number_of_free_spots_in_room] = y;
542 number_of_free_spots_in_room++;
543 536
544 /* now search all the 8 squares around recursively for free spots,in random order */ 537 /* now search all the 8 squares around recursively for free spots,in random order */
545 for (i = rmg_rndm (8), j = 0; j < 8 && theMonsterToFind == NULL; i++, j++) 538 for (int i = rmg_rndm (8), j = 0; j < 8 && !theMonsterToFind; i++, j++)
546 find_spot_in_room_recursive (layout, x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1], RP); 539 find_spot_in_room_recursive (maze, spots, x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1]);
547 540
548} 541}
549 542
550/* find a random non-blocked spot in this room to drop a key. */ 543/* find a random non-blocked spot in this room to drop a key. */
551static void 544static void
552find_spot_in_room (maptile *map, int x, int y, int *kx, int *ky, random_map_params *RP) 545find_spot_in_room (maptile *map, int x, int y, int *kx, int *ky)
553{ 546{
554 char **layout2; 547 fixed_stack<point> spots (map->width * map->height);
555 int i, j;
556 548
557 number_of_free_spots_in_room = 0; 549 layout layout2 (map->width, map->height);
558 room_free_spots_x = (int *) calloc (sizeof (int), RP->Xsize * RP->Ysize);
559 room_free_spots_y = (int *) calloc (sizeof (int), RP->Xsize * RP->Ysize);
560 550
561 layout2 = (char **) calloc (sizeof (char *), RP->Xsize);
562 /* allocate and copy the layout, converting C to 0. */ 551 /* allocate and copy the maze, converting C to 0. */
563 for (i = 0; i < RP->Xsize; i++) 552 for (int i = 0; i < map->width; i++)
564 { 553 for (int j = 0; j < map->height; j++)
565 layout2[i] = (char *) calloc (sizeof (char), RP->Ysize); 554 layout2 [i][j] = wall_blocked (map, i, j) ? '#' : 0;
566 for (j = 0; j < RP->Ysize; j++)
567 if (wall_blocked (map, i, j))
568 layout2[i][j] = '#';
569 }
570 555
571 /* setup num_free_spots and room_free_spots */ 556 /* setup num_free_spots and room_free_spots */
572 find_spot_in_room_recursive (layout2, x, y, RP); 557 find_spot_in_room_recursive (layout2, spots, x, y);
573 558
574 if (number_of_free_spots_in_room > 0) 559 if (spots.size)
575 {
576 i = rmg_rndm (number_of_free_spots_in_room);
577 *kx = room_free_spots_x[i];
578 *ky = room_free_spots_y[i];
579 } 560 {
561 point p = spots [rmg_rndm (spots.size)];
580 562
581 /* deallocate the temp. layout */ 563 *kx = p.x;
582 for (i = 0; i < RP->Xsize; i++) 564 *ky = p.y;
583 free (layout2[i]); 565 }
584
585 free (layout2);
586 free (room_free_spots_x);
587 free (room_free_spots_y);
588} 566}
589
590 567
591/* searches the map for a spot with walls around it. The more 568/* searches the map for a spot with walls around it. The more
592 walls the better, but it'll settle for 1 wall, or even 0, but 569 walls the better, but it'll settle for 1 wall, or even 0, but
593 it'll return 0 if no FREE spots are found.*/ 570 it'll return 0 if no FREE spots are found.*/
594static void 571static void
595find_enclosed_spot (maptile *map, int *cx, int *cy, random_map_params *RP) 572find_enclosed_spot (maptile *map, int *cx, int *cy)
596{ 573{
597 int x, y; 574 int x, y;
598 int i; 575 int i;
599 576
600 x = *cx; 577 x = *cx;
682 659
683/* surrounds the point x,y by doors, so as to enclose something, like 660/* surrounds the point x,y by doors, so as to enclose something, like
684 a chest. It only goes as far as the 8 squares surrounding, and 661 a chest. It only goes as far as the 8 squares surrounding, and
685 it'll remove any monsters it finds.*/ 662 it'll remove any monsters it finds.*/
686static object ** 663static object **
687surround_by_doors (maptile *map, char **layout, int x, int y, int opts) 664surround_by_doors (maptile *map, char **maze, int x, int y, int opts)
688{ 665{
689 int i; 666 int i;
690 const char *doors[2]; 667 const char *doors[2];
691 object **doorlist; 668 object **doorlist;
692 int ndoors_made = 0; 669 int ndoors_made = 0;
707 /* place doors in all the 8 adjacent unblocked squares. */ 684 /* place doors in all the 8 adjacent unblocked squares. */
708 for (i = 1; i < 9; i++) 685 for (i = 1; i < 9; i++)
709 { 686 {
710 int x1 = x + freearr_x[i], y1 = y + freearr_y[i]; 687 int x1 = x + freearr_x[i], y1 = y + freearr_y[i];
711 688
712 if (!wall_blocked (map, x1, y1) && layout[x1][y1] == '>') 689 if (!wall_blocked (map, x1, y1) && maze[x1][y1] == '>')
713 { /* place a door */ 690 { /* place a door */
714 remove_monsters (x1, y1, map); 691 remove_monsters (x1, y1, map);
715 692
716 object *new_door = get_archetype (freearr_x[i] == 0 ? doors[1] : doors[0]); 693 object *new_door = archetype::get (freearr_x[i] == 0 ? doors[1] : doors[0]);
717 map->insert (new_door, x1, y1); 694 map->insert (new_door, x1, y1);
718 doorlist[ndoors_made] = new_door; 695 doorlist[ndoors_made] = new_door;
719 ndoors_made++; 696 ndoors_made++;
720 } 697 }
721 } 698 }
734 return NULL; 711 return NULL;
735} 712}
736 713
737/* the workhorse routine, which finds the doors in a room */ 714/* the workhorse routine, which finds the doors in a room */
738static void 715static void
739find_doors_in_room_recursive (char **layout, maptile *map, int x, int y, object **doorlist, int *ndoors, random_map_params *RP) 716find_doors_in_room_recursive (layout &maze, maptile *map, int x, int y, object **doorlist, int *ndoors)
740{ 717{
741 int i, j; 718 int i, j;
742 object *door; 719 object *door;
743 720
744 /* bounds check x and y */ 721 /* bounds check x and y */
745 if (!(x >= 0 && y >= 0 && x < RP->Xsize && y < RP->Ysize)) 722 if (!(x >= 0 && y >= 0 && x < maze.w && y < maze.h))
746 return; 723 return;
747 724
748 /* if the square is blocked or searched already, leave */ 725 /* if the square is blocked or searched already, leave */
749 if (layout[x][y] == 1) 726 if (maze[x][y] == 1)
750 return; 727 return;
751 728
752 /* check off this point */ 729 /* check off this point */
753 if (layout[x][y] == '#') 730 if (maze[x][y] == '#')
754 { /* there could be a door here */ 731 { /* there could be a door here */
755 layout[x][y] = 1; 732 maze[x][y] = 1;
756 door = door_in_square (map, x, y); 733 door = door_in_square (map, x, y);
757 if (door) 734 if (door)
758 { 735 {
759 doorlist[*ndoors] = door; 736 doorlist[*ndoors] = door;
760 737
767 *ndoors = *ndoors + 1; 744 *ndoors = *ndoors + 1;
768 } 745 }
769 } 746 }
770 else 747 else
771 { 748 {
772 layout[x][y] = 1; 749 maze[x][y] = 1;
773 750
774 /* now search all the 8 squares around recursively for free spots,in random order */ 751 /* now search all the 8 squares around recursively for free spots,in random order */
775 for (i = rmg_rndm (8), j = 0; j < 8 && !theMonsterToFind; i++, j++) 752 for (i = rmg_rndm (8), j = 0; j < 8 && !theMonsterToFind; i++, j++)
776 find_doors_in_room_recursive (layout, map, 753 find_doors_in_room_recursive (maze, map,
777 x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1], 754 x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1],
778 doorlist, ndoors, RP); 755 doorlist, ndoors);
779 } 756 }
780} 757}
781 758
782/* find a random non-blocked spot in this room to drop a key. */ 759/* find a random non-blocked spot in this room to drop a key. */
783static object ** 760static object **
784find_doors_in_room (maptile *map, int x, int y, random_map_params *RP) 761find_doors_in_room (maptile *map, int x, int y)
785{ 762{
786 int i, j; 763 int i, j;
787 int ndoors = 0; 764 int ndoors = 0;
788 765
789 object **doorlist = (object **)calloc (sizeof (int), 1024); 766 object **doorlist = (object **)calloc (sizeof (int), 1024);
790 767
791 Layout layout2 (RP->Xsize, RP->Ysize); 768 layout layout2 (map->width, map->height);
792 layout2.clear (); 769 layout2.clear ();
793 770
794 /* allocate and copy the layout, converting C to 0. */ 771 /* allocate and copy the maze, converting C to 0. */
795 for (i = 0; i < RP->Xsize; i++) 772 for (i = 0; i < map->width; i++)
796 for (j = 0; j < RP->Ysize; j++) 773 for (j = 0; j < map->height; j++)
797 layout2[i][j] = wall_blocked (map, i, j) ? '#' : 0; 774 layout2[i][j] = wall_blocked (map, i, j) ? '#' : 0;
798 775
799 /* setup num_free_spots and room_free_spots */ 776 /* setup num_free_spots and room_free_spots */
800 find_doors_in_room_recursive (layout2, map, x, y, doorlist, &ndoors, RP); 777 find_doors_in_room_recursive (layout2, map, x, y, doorlist, &ndoors);
801 778
802 return doorlist; 779 return doorlist;
803} 780}
804 781
805/* locks and/or hides all the doors in doorlist, or does nothing if 782/* locks and/or hides all the doors in doorlist, or does nothing if
814 791
815 if (opts & DOORED) 792 if (opts & DOORED)
816 { 793 {
817 for (i = 0, door = doorlist[0]; doorlist[i]; i++) 794 for (i = 0, door = doorlist[0]; doorlist[i]; i++)
818 { 795 {
819 object *new_door = get_archetype (shstr_locked_door1); 796 object *new_door = archetype::get (shstr_locked_door1);
820 797
821 door = doorlist[i]; 798 door = doorlist[i];
822 new_door->face = door->face; 799 new_door->face = door->face;
823 new_door->x = door->x; 800 new_door->x = door->x;
824 new_door->y = door->y; 801 new_door->y = door->y;
825 door->destroy (); 802 door->destroy ();
826 doorlist[i] = new_door; 803 doorlist[i] = new_door;
827 insert_ob_in_map (new_door, map, NULL, 0); 804 insert_ob_in_map (new_door, map, NULL, 0);
828 new_door->slaying = format ("RMG-%d-%d", (int)rmg_rndm (1000000000), (int)rmg_rndm (1000000000)); 805 new_door->slaying = format ("RMG-%d-%d", (int)rmg_rndm (1000000000), (int)rmg_rndm (1000000000));
829 keyplace (map, new_door->x, new_door->y, new_door->slaying, NO_PASS_DOORS, 2, RP); 806 keyplace (map, new_door->x, new_door->y, new_door->slaying, NO_PASS_DOORS, 2);
830 } 807 }
831 } 808 }
832 809
833 /* change the faces of the doors and surrounding walls to hide them. */ 810 /* change the faces of the doors and surrounding walls to hide them. */
834 if (opts & HIDDEN) 811 if (opts & HIDDEN)

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines