Crossfire Server, Branches 1.12  R18729
treasure.c
Go to the documentation of this file.
1 /*
2  * static char *rcsid_treasure_c =
3  * "$Id: treasure.c 11578 2009-02-23 22:02:27Z lalo $";
4  */
5 
6 /*
7  CrossFire, A Multiplayer game for X-windows
8 
9  Copyright (C) 2001 Mark Wedel & Crossfire Development Team
10  Copyright (C) 1992 Frank Tore Johansen
11 
12  This program is free software; you can redistribute it and/or modify
13  it under the terms of the GNU General Public License as published by
14  the Free Software Foundation; either version 2 of the License, or
15  (at your option) any later version.
16 
17  This program is distributed in the hope that it will be useful,
18  but WITHOUT ANY WARRANTY; without even the implied warranty of
19  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20  GNU General Public License for more details.
21 
22  You should have received a copy of the GNU General Public License
23  along with this program; if not, write to the Free Software
24  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 
26  The authors can be reached via e-mail at crossfire-devel@real-time.com
27 */
28 
29 /* placing treasure in maps, where appropriate. */
30 
36 #include <global.h>
37 #include <random_map.h>
38 #include <rproto.h>
39 
46 #define CONCENTRATED 1 /* all the treasure is at the C's for onions. */
47 #define HIDDEN 2 /* doors to treasure are hidden. */
48 #define KEYREQUIRED 4 /* chest has a key, which is placed randomly in the map. */
49 #define DOORED 8 /* treasure has doors around it. */
50 #define TRAPPED 16 /* trap dropped in same location as chest. */
51 #define SPARSE 32 /* 1/2 as much treasure as default */
52 #define RICH 64 /* 2x as much treasure as default */
53 #define FILLED 128 /* Fill/tile the entire map with treasure */
54 #define LAST_OPTION 64 /* set this to the last real option, for random */
55 
57 #define NO_PASS_DOORS 0
58 #define PASS_DOORS 1
59 
60 static object **surround_by_doors(mapstruct *map, char **layout, int x, int y, int opts);
61 
73 int wall_blocked(mapstruct *m, int x, int y) {
74  int r;
75 
76  if (OUT_OF_REAL_MAP(m, x, y))
77  return 1;
79  return r;
80 }
81 
101 void place_treasure(mapstruct *map, char **layout, char *treasure_style, int treasureoptions, RMParms *RP) {
102  char styledirname[256];
103  char stylefilepath[256];
104  mapstruct *style_map = NULL;
105  int num_treasures;
106 
107  /* bail out if treasure isn't wanted. */
108  if (treasure_style)
109  if (!strcmp(treasure_style, "none"))
110  return;
111  if (treasureoptions <= 0)
112  treasureoptions = RANDOM()%(2*LAST_OPTION);
113 
114  /* filter out the mutually exclusive options */
115  if ((treasureoptions&RICH) && (treasureoptions&SPARSE)) {
116  if (RANDOM()%2)
117  treasureoptions -= 1;
118  else
119  treasureoptions -= 2;
120  }
121 
122  /* pick the number of treasures */
123  if (treasureoptions&SPARSE)
124  num_treasures = BC_RANDOM(RP->total_map_hp/600+RP->difficulty/2+1);
125  else if (treasureoptions&RICH)
126  num_treasures = BC_RANDOM(RP->total_map_hp/150+2*RP->difficulty+1);
127  else
128  num_treasures = BC_RANDOM(RP->total_map_hp/300+RP->difficulty+1);
129 
130  if (num_treasures <= 0)
131  return;
132 
133  /* get the style map */
134  snprintf(styledirname, sizeof(styledirname), "%s", "/styles/treasurestyles");
135  snprintf(stylefilepath, sizeof(stylefilepath), "%s/%s", styledirname, treasure_style);
136  style_map = find_style(styledirname, treasure_style, -1);
137 
138  /* all the treasure at one spot in the map. */
139  if (treasureoptions&CONCENTRATED) {
140  /* map_layout_style global, and is previously set */
141  switch (RP->map_layout_style) {
142  case ONION_LAYOUT:
143  case SPIRAL_LAYOUT:
144  case SQUARE_SPIRAL_LAYOUT: {
145  int i, j;
146 
147  /* search the onion for C's or '>', and put treasure there. */
148  for (i = 0; i < RP->Xsize; i++) {
149  for (j = 0; j < RP->Ysize; j++) {
150  if (layout[i][j] == 'C' || layout[i][j] == '>') {
151  int tdiv = RP->symmetry_used;
152  object **doorlist;
153  object *chest;
154 
155  if (tdiv == 3)
156  tdiv = 2; /* this symmetry uses a divisor of 2*/
157  /* don't put a chest on an exit. */
158  chest = place_chest(treasureoptions, i, j, map, style_map, num_treasures/tdiv, RP);
159  if (!chest)
160  continue; /* if no chest was placed NEXT */
161  if (treasureoptions&(DOORED|HIDDEN)) {
162  doorlist = find_doors_in_room(map, i, j, RP);
163  lock_and_hide_doors(doorlist, map, treasureoptions, RP);
164  free(doorlist);
165  }
166  }
167  }
168  }
169  break;
170  }
171  default: {
172  int i, j, tries;
173  object *chest;
174  object **doorlist;
175 
176  i = j = -1;
177  tries = 0;
178  while (i == -1 && tries < 100) {
179  i = RANDOM()%(RP->Xsize-2)+1;
180  j = RANDOM()%(RP->Ysize-2)+1;
181  find_enclosed_spot(map, &i, &j, RP);
182  if (wall_blocked(map, i, j))
183  i = -1;
184  tries++;
185  }
186  chest = place_chest(treasureoptions, i, j, map, style_map, num_treasures, RP);
187  if (!chest)
188  return;
189  i = chest->x;
190  j = chest->y;
191  if (treasureoptions&(DOORED|HIDDEN)) {
192  doorlist = surround_by_doors(map, layout, i, j, treasureoptions);
193  lock_and_hide_doors(doorlist, map, treasureoptions, RP);
194  free(doorlist);
195  }
196  }
197  }
198  } else { /* DIFFUSE treasure layout */
199  int ti, i, j;
200 
201  for (ti = 0; ti < num_treasures; ti++) {
202  i = RANDOM()%(RP->Xsize-2)+1;
203  j = RANDOM()%(RP->Ysize-2)+1;
204  place_chest(treasureoptions, i, j, map, style_map, 1, RP);
205  }
206  }
207 }
208 
232 object *place_chest(int treasureoptions, int x, int y, mapstruct *map, mapstruct *style_map, int n_treasures, RMParms *RP) {
233  object *the_chest;
234  int i, xl, yl;
235  treasurelist *tlist;
236 
237  the_chest = create_archetype("chest"); /* was "chest_2" */
238 
239  /* first, find a place to put the chest. */
240  i = find_first_free_spot(the_chest, map, x, y);
241  if (i == -1) {
242  free_object(the_chest);
243  return NULL;
244  }
245  xl = x+freearr_x[i];
246  yl = y+freearr_y[i];
247 
248  /* if the placement is blocked, return a fail. */
249  if (wall_blocked(map, xl, yl)) {
250  free_object(the_chest);
251  return NULL;
252  }
253 
254  tlist = find_treasurelist("chest");
255  the_chest->randomitems = tlist;
256  the_chest->stats.hp = n_treasures;
257 
258  /* stick a trap in the chest if required */
259  if (treasureoptions&TRAPPED) {
260  mapstruct *trap_map = find_style("/styles/trapstyles", "traps", -1);
261  object *the_trap;
262 
263  if (trap_map) {
264  the_trap = pick_random_object(trap_map);
265  the_trap->stats.Cha = 10+RP->difficulty;
266  the_trap->level = BC_RANDOM((3*RP->difficulty)/2);
267  if (the_trap) {
268  object *new_trap;
269 
270  new_trap = arch_to_object(the_trap->arch);
271  copy_object(new_trap, the_trap);
272  new_trap->x = x;
273  new_trap->y = y;
274  insert_ob_in_ob(new_trap, the_chest);
275  }
276  }
277  }
278 
279  /* set the chest lock code, and call the keyplacer routine with
280  the lockcode. It's not worth bothering to lock the chest if
281  there's only 1 treasure....*/
282  if ((treasureoptions&KEYREQUIRED) && n_treasures > 1) {
283  char keybuf[256];
284 
285  snprintf(keybuf, sizeof(keybuf), "%d", (int)RANDOM());
286  if (keyplace(map, x, y, keybuf, PASS_DOORS, 1, RP))
287  the_chest->slaying = add_string(keybuf);
288  }
289 
290  /* actually place the chest. */
291  the_chest->x = xl;
292  the_chest->y = yl;
293  insert_ob_in_map(the_chest, map, NULL, 0);
294  return the_chest;
295 }
296 
311 object *find_closest_monster(mapstruct *map, int x, int y, RMParms *RP) {
312  int i;
313 
314  for (i = 0; i < SIZEOFFREE; i++) {
315  int lx, ly;
316 
317  lx = x+freearr_x[i];
318  ly = y+freearr_y[i];
319  /* boundscheck */
320  if (lx >= 0 && ly >= 0 && lx < RP->Xsize && ly < RP->Ysize)
321  /* don't bother searching this square unless the map says life exists.*/
322  if (GET_MAP_FLAGS(map, lx, ly)&P_IS_ALIVE) {
323  object *the_monster = GET_MAP_OB(map, lx, ly);
324 
325  for (; the_monster != NULL && (!QUERY_FLAG(the_monster, FLAG_MONSTER)); the_monster = the_monster->above)
326  ;
327  if (the_monster && QUERY_FLAG(the_monster, FLAG_MONSTER))
328  return the_monster;
329  }
330  }
331  return NULL;
332 }
333 
361 int keyplace(mapstruct *map, int x, int y, char *keycode, int door_flag, int n_keys, RMParms *RP) {
362  int i, j;
363  int kx, ky;
364  object *the_keymaster; /* the monster that gets the key. */
365  object *the_key;
366  char keybuf[256];
367 
368  /* get a key and set its keycode */
369  the_key = create_archetype("key2");
370  the_key->slaying = add_string(keycode);
371  free_string(the_key->name);
372  snprintf(keybuf, 256, "key from level %d of %s", RP->dungeon_level, RP->dungeon_name[0] != '\0' ? RP->dungeon_name : "a random map");
373  the_key->name = add_string(keybuf);
374 
375  if (door_flag == PASS_DOORS) {
376  int tries = 0;
377 
378  the_keymaster = NULL;
379  while (tries < 15 && the_keymaster == NULL) {
380  i = (RANDOM()%(RP->Xsize-2))+1;
381  j = (RANDOM()%(RP->Ysize-2))+1;
382  tries++;
383  the_keymaster = find_closest_monster(map, i, j, RP);
384  }
385  /* if we don't find a good keymaster, drop the key on the ground. */
386  if (the_keymaster == NULL) {
387  int freeindex;
388 
389  freeindex = -1;
390  for (tries = 0; tries < 15 && freeindex == -1; tries++) {
391  kx = (RANDOM()%(RP->Xsize-2))+1;
392  ky = (RANDOM()%(RP->Ysize-2))+1;
393  freeindex = find_first_free_spot(the_key, map, kx, ky);
394  }
395  if (freeindex != -1) {
396  kx += freearr_x[freeindex];
397  ky += freearr_y[freeindex];
398  }
399  }
400  } else { /* NO_PASS_DOORS --we have to work harder.*/
401  /* don't try to keyplace if we're sitting on a blocked square and
402  * NO_PASS_DOORS is set.
403  */
404  if (n_keys == 1) {
405  if (wall_blocked(map, x, y))
406  return 0;
407  the_keymaster = find_monster_in_room(map, x, y, RP);
408  if (the_keymaster == NULL) /* if fail, find a spot to drop the key. */
409  if (!find_spot_in_room(map, x, y, &kx, &ky, RP))
410  return 0;
411  } else {
412  /* It can happen that spots around that point are all blocked, so
413  * try to look farther away if needed
414  */
415  int sum = 0; /* count how many keys we actually place */
416  int distance = 1;
417 
418  while (distance < 5) {
419  /* I'm lazy, so just try to place in all 4 directions. */
420  sum += keyplace(map, x+distance, y, keycode, NO_PASS_DOORS, 1, RP);
421  sum += keyplace(map, x, y+distance, keycode, NO_PASS_DOORS, 1, RP);
422  sum += keyplace(map, x-distance, y, keycode, NO_PASS_DOORS, 1, RP);
423  sum += keyplace(map, x, y-distance, keycode, NO_PASS_DOORS, 1, RP);
424  if (sum < 2) { /* we might have made a disconnected map-place more keys. */
425  /* diagonally this time. */
426  keyplace(map, x+distance, y+distance, keycode, NO_PASS_DOORS, 1, RP);
427  keyplace(map, x+distance, y-distance, keycode, NO_PASS_DOORS, 1, RP);
428  keyplace(map, x-distance, y+distance, keycode, NO_PASS_DOORS, 1, RP);
429  keyplace(map, x-distance, y-distance, keycode, NO_PASS_DOORS, 1, RP);
430  }
431  if (sum > 0)
432  return 1;
433  distance++;
434  }
435  return 0;
436  }
437  }
438 
439  if (the_keymaster == NULL) {
440  the_key->x = kx;
441  the_key->y = ky;
442  insert_ob_in_map(the_key, map, NULL, 0);
443  return 1;
444  }
445 
446  insert_ob_in_ob(the_key, the_keymaster);
447  return 1;
448 }
449 
465 object *find_monster_in_room_recursive(char **layout, mapstruct *map, int x, int y, RMParms *RP) {
466  int i, j;
467  object *the_monster;
468 
469  /* bounds check x and y */
470  if (!(x >= 0 && y >= 0 && x < RP->Xsize && y < RP->Ysize))
471  return NULL;
472 
473  /* if the square is blocked or searched already, leave */
474  if (layout[x][y] != 0)
475  return NULL;
476 
477  /* check the current square for a monster. If there is one,
478  set theMonsterToFind and return it. */
479  layout[x][y] = 1;
480  if (GET_MAP_FLAGS(map, x, y)&P_IS_ALIVE) {
481  the_monster = GET_MAP_OB(map, x, y);
482  /* check off this point */
483  for (; the_monster != NULL && (!QUERY_FLAG(the_monster, FLAG_ALIVE)); the_monster = the_monster->above)
484  ;
485  if (the_monster && QUERY_FLAG(the_monster, FLAG_ALIVE)) {
486  return the_monster;
487  }
488  }
489 
490  /* now search all the 8 squares around recursively for a monster, in random order */
491  for (i = RANDOM()%8, j = 0; j < 8; i++, j++) {
492  the_monster = find_monster_in_room_recursive(layout, map, x+freearr_x[i%8+1], y+freearr_y[i%8+1], RP);
493  if (the_monster != NULL)
494  return the_monster;
495  }
496  return NULL;
497 }
498 
513 object *find_monster_in_room(mapstruct *map, int x, int y, RMParms *RP) {
514  char **layout2;
515  int i, j;
516  object *theMonsterToFind;
517 
518  layout2 = (char **)calloc(sizeof(char *), RP->Xsize);
519  /* allocate and copy the layout, converting C to 0. */
520  for (i = 0; i < RP->Xsize; i++) {
521  layout2[i] = (char *)calloc(sizeof(char), RP->Ysize);
522  for (j = 0; j < RP->Ysize; j++) {
523  if (wall_blocked(map, i, j))
524  layout2[i][j] = '#';
525  }
526  }
527  theMonsterToFind = find_monster_in_room_recursive(layout2, map, x, y, RP);
528 
529  /* deallocate the temp. layout */
530  for (i = 0; i < RP->Xsize; i++) {
531  free(layout2[i]);
532  }
533  free(layout2);
534 
535  return theMonsterToFind;
536 }
537 
539 typedef struct free_spots_struct {
544 
559 static void find_spot_in_room_recursive(char **layout, int x, int y, RMParms *RP, free_spots_struct *spots) {
560  int i, j;
561 
562  /* bounds check x and y */
563  if (!(x >= 0 && y >= 0 && x < RP->Xsize && y < RP->Ysize))
564  return;
565 
566  /* if the square is blocked or searched already, leave */
567  if (layout[x][y] != 0)
568  return;
569 
570  /* set the current square as checked, and add it to the list.
571  check off this point */
572  layout[x][y] = 1;
576  /* now search all the 8 squares around recursively for free spots, in random order */
577  for (i = RANDOM()%8, j = 0; j < 8; i++, j++) {
578  find_spot_in_room_recursive(layout, x+freearr_x[i%8+1], y+freearr_y[i%8+1], RP, spots);
579  }
580 }
581 
600 int find_spot_in_room(mapstruct *map, int x, int y, int *kx, int *ky, RMParms *RP) {
601  char **layout2;
602  int i, j;
603  free_spots_struct spots;
604 
606  spots.room_free_spots_x = (int *)calloc(sizeof(int), RP->Xsize*RP->Ysize);
607  spots.room_free_spots_y = (int *)calloc(sizeof(int), RP->Xsize*RP->Ysize);
608 
609  layout2 = (char **)calloc(sizeof(char *), RP->Xsize);
610  /* allocate and copy the layout, converting C to 0. */
611  for (i = 0; i < RP->Xsize; i++) {
612  layout2[i] = (char *)calloc(sizeof(char), RP->Ysize);
613  for (j = 0; j < RP->Ysize; j++) {
614  if (wall_blocked(map, i, j))
615  layout2[i][j] = '#';
616  }
617  }
618 
619  /* setup num_free_spots and room_free_spots */
620  find_spot_in_room_recursive(layout2, x, y, RP, &spots);
621 
622  if (spots.number_of_free_spots_in_room > 0) {
623  i = RANDOM()%spots.number_of_free_spots_in_room;
624  *kx = spots.room_free_spots_x[i];
625  *ky = spots.room_free_spots_y[i];
626  }
627 
628  /* deallocate the temp. layout */
629  for (i = 0; i < RP->Xsize; i++) {
630  free(layout2[i]);
631  }
632  free(layout2);
633  free(spots.room_free_spots_x);
634  free(spots.room_free_spots_y);
635 
636  if (spots.number_of_free_spots_in_room > 0)
637  return 1;
638  return 0;
639 }
640 
653 void find_enclosed_spot(mapstruct *map, int *cx, int *cy, RMParms *RP) {
654  int x, y;
655  int i;
656 
657  x = *cx;
658  y = *cy;
659 
660  for (i = 0; i <= SIZEOFFREE1; i++) {
661  int lx, ly, sindex;
662  lx = x+freearr_x[i];
663  ly = y+freearr_y[i];
664  sindex = surround_flag3(map, lx, ly, RP);
665  /* if it's blocked on 3 sides, it's enclosed */
666  if (sindex == 7 || sindex == 11 || sindex == 13 || sindex == 14) {
667  *cx = lx;
668  *cy = ly;
669  return;
670  }
671  }
672 
673  /* OK, if we got here, we're obviously someplace where there's no enclosed
674  spots--try to find someplace which is 2x enclosed. */
675  for (i = 0; i <= SIZEOFFREE1; i++) {
676  int lx, ly, sindex;
677 
678  lx = x+freearr_x[i];
679  ly = y+freearr_y[i];
680  sindex = surround_flag3(map, lx, ly, RP);
681  /* if it's blocked on 3 sides, it's enclosed */
682  if (sindex == 3 || sindex == 5 || sindex == 9 || sindex == 6 || sindex == 10 || sindex == 12) {
683  *cx = lx;
684  *cy = ly;
685  return;
686  }
687  }
688 
689  /* settle for one surround point */
690  for (i = 0; i <= SIZEOFFREE1; i++) {
691  int lx, ly, sindex;
692 
693  lx = x+freearr_x[i];
694  ly = y+freearr_y[i];
695  sindex = surround_flag3(map, lx, ly, RP);
696  /* if it's blocked on 3 sides, it's enclosed */
697  if (sindex) {
698  *cx = lx;
699  *cy = ly;
700  return;
701  }
702  }
703 
704  /* give up and return the closest free spot. */
705  i = find_first_free_spot(&find_archetype("chest")->clone, map, x, y);
706  if (i != -1 && i <= SIZEOFFREE1) {
707  *cx = x+freearr_x[i];
708  *cy = y+freearr_y[i];
709  return;
710  }
711  /* indicate failure */
712  *cx = *cy = -1;
713 }
714 
722 void remove_monsters(int x, int y, mapstruct *map) {
723  object *tmp;
724 
725  for (tmp = GET_MAP_OB(map, x, y); tmp != NULL; tmp = tmp->above)
726  if (QUERY_FLAG(tmp, FLAG_ALIVE)) {
727  if (tmp->head)
728  tmp = tmp->head;
729  remove_ob(tmp);
730  free_object(tmp);
731  tmp = GET_MAP_OB(map, x, y);
732  if (tmp == NULL)
733  break;
734  };
735 }
736 
755 static object **surround_by_doors(mapstruct *map, char **layout, int x, int y, int opts) {
756  int i;
757  const char *doors[2];
758  object **doorlist;
759  int ndoors_made = 0;
760  doorlist = (object **)calloc(9, sizeof(object *)); /* 9 doors so we can hold termination null */
761 
762  /* this is a list we pick from, for horizontal and vertical doors */
763  if (opts&DOORED) {
764  doors[0] = "locked_door2";
765  doors[1] = "locked_door1";
766  } else {
767  doors[0] = "door_1";
768  doors[1] = "door_2";
769  }
770 
771  /* place doors in all the 8 adjacent unblocked squares. */
772  for (i = 1; i < 9; i++) {
773  int x1 = x+freearr_x[i], y1 = y+freearr_y[i];
774 
775  if (!wall_blocked(map, x1, y1)
776  || layout[x1][y1] == '>') {/* place a door */
777  object *new_door = create_archetype((freearr_x[i] == 0) ? doors[1] : doors[0]);
778 
779  new_door->x = x+freearr_x[i];
780  new_door->y = y+freearr_y[i];
781  remove_monsters(new_door->x, new_door->y, map);
782  insert_ob_in_map(new_door, map, NULL, 0);
783  doorlist[ndoors_made] = new_door;
784  ndoors_made++;
785  }
786  }
787  return doorlist;
788 }
789 
801 static object *door_in_square(mapstruct *map, int x, int y) {
802  object *tmp;
803 
804  for (tmp = GET_MAP_OB(map, x, y); tmp != NULL; tmp = tmp->above)
805  if (tmp->type == DOOR || tmp->type == LOCKED_DOOR)
806  return tmp;
807  return NULL;
808 }
809 
824 void find_doors_in_room_recursive(char **layout, mapstruct *map, int x, int y, object **doorlist, int *ndoors, RMParms *RP) {
825  int i, j;
826  object *door;
827 
828  /* bounds check x and y */
829  if (!(x >= 0 && y >= 0 && x < RP->Xsize && y < RP->Ysize))
830  return;
831 
832  /* if the square is blocked or searched already, leave */
833  if (layout[x][y] == 1)
834  return;
835 
836  /* check off this point */
837  if (layout[x][y] == '#') { /* there could be a door here */
838  layout[x][y] = 1;
839  door = door_in_square(map, x, y);
840  if (door != NULL) {
841  doorlist[*ndoors] = door;
842  if (*ndoors > 254) { /* eek! out of memory */
843  LOG(llevError, "find_doors_in_room_recursive:Too many doors for memory allocated!\n");
844  return;
845  }
846  *ndoors = *ndoors+1;
847  }
848  } else {
849  layout[x][y] = 1;
850  /* now search all the 8 squares around recursively for free spots, in random order */
851  for (i = RANDOM()%8, j = 0; j < 8; i++, j++) {
852  find_doors_in_room_recursive(layout, map, x+freearr_x[i%8+1], y+freearr_y[i%8+1], doorlist, ndoors, RP);
853  }
854  }
855 }
856 
871 object **find_doors_in_room(mapstruct *map, int x, int y, RMParms *RP) {
872  char **layout2;
873  object **doorlist;
874  int i, j;
875  int ndoors = 0;
876 
877  doorlist = (object **)calloc(sizeof(int), 256);
878 
879 
880  layout2 = (char **)calloc(sizeof(char *), RP->Xsize);
881  /* allocate and copy the layout, converting C to 0. */
882  for (i = 0; i < RP->Xsize; i++) {
883  layout2[i] = (char *)calloc(sizeof(char), RP->Ysize);
884  for (j = 0; j < RP->Ysize; j++) {
885  if (wall_blocked(map, i, j))
886  layout2[i][j] = '#';
887  }
888  }
889 
890  /* setup num_free_spots and room_free_spots */
891  find_doors_in_room_recursive(layout2, map, x, y, doorlist, &ndoors, RP);
892 
893  /* deallocate the temp. layout */
894  for (i = 0; i < RP->Xsize; i++) {
895  free(layout2[i]);
896  }
897  free(layout2);
898  return doorlist;
899 }
900 
910 static void remove_adjacent_doors(object *door) {
911  mapstruct *m = door->map;
912  int x = door->x;
913  int y = door->y;
914  int i, flags;
915  object *tmp;
916 
917  for (i = 1; i <= 8; i++) {
918  flags = get_map_flags(m, NULL, x+freearr_x[i], y+freearr_y[i], NULL, NULL);
919  if (flags&P_OUT_OF_MAP)
920  continue;
921 
922  /* Old style doors are living objects. So if P_IS_ALIVE is not
923  * set, can not be a door on this space.
924  */
925  if (flags&P_IS_ALIVE) {
926  for (tmp = GET_MAP_OB(m, x+freearr_x[i], y+freearr_y[i]); tmp; tmp = tmp->above) {
927  if (tmp->type == DOOR) {
928  remove_ob(tmp);
929  free_object(tmp);
930  break;
931  }
932  }
933  }
934  }
935 }
936 
952 void lock_and_hide_doors(object **doorlist, mapstruct *map, int opts, RMParms *RP) {
953  object *door;
954  int i;
955 
956  /* lock the doors and hide the keys. */
957  if (opts&DOORED) {
958  for (i = 0, door = doorlist[0]; doorlist[i] != NULL; i++) {
959  object *new_door = create_archetype("locked_door1");
960  char keybuf[256];
961 
962  door = doorlist[i];
963  new_door->face = door->face;
964  new_door->x = door->x;
965  new_door->y = door->y;
966  remove_ob(door);
967  free_object(door);
968  doorlist[i] = new_door;
969  insert_ob_in_map(new_door, map, NULL, 0);
970 
971  snprintf(keybuf, 256, "%d", (int)RANDOM());
972  if (keyplace(map, new_door->x, new_door->y, keybuf, NO_PASS_DOORS, 2, RP))
973  new_door->slaying = add_string(keybuf);
974  }
975  for (i = 0; doorlist[i] != NULL; i++)
976  remove_adjacent_doors(doorlist[i]);
977  }
978 
979  /* change the faces of the doors and surrounding walls to hide them. */
980  if (opts&HIDDEN) {
981  for (i = 0, door = doorlist[0]; doorlist[i] != NULL; i++) {
982  object *wallface;
983 
984  door = doorlist[i];
985  wallface = retrofit_joined_wall(map, door->x, door->y, 1, RP);
986  if (wallface != NULL) {
987  retrofit_joined_wall(map, door->x-1, door->y, 0, RP);
988  retrofit_joined_wall(map, door->x+1, door->y, 0, RP);
989  retrofit_joined_wall(map, door->x, door->y-1, 0, RP);
990  retrofit_joined_wall(map, door->x, door->y+1, 0, RP);
991  door->face = wallface->face;
992  if (!QUERY_FLAG(wallface, FLAG_REMOVED))
993  remove_ob(wallface);
994  free_object(wallface);
995  }
996  }
997  }
998 }
static void find_spot_in_room_recursive(char **layout, int x, int y, RMParms *RP, free_spots_struct *spots)
Definition: treasure.c:559
int get_map_flags(mapstruct *oldmap, mapstruct **newmap, sint16 x, sint16 y, sint16 *nx, sint16 *ny)
Definition: map.c:330
archetype * find_archetype(const char *name)
Definition: arch.c:700
object ** find_doors_in_room(mapstruct *map, int x, int y, RMParms *RP)
Definition: treasure.c:871
#define ONION_LAYOUT
Definition: random_map.h:90
void find_enclosed_spot(mapstruct *map, int *cx, int *cy, RMParms *RP)
Definition: treasure.c:653
void find_doors_in_room_recursive(char **layout, mapstruct *map, int x, int y, object **doorlist, int *ndoors, RMParms *RP)
Definition: treasure.c:824
void remove_monsters(int x, int y, mapstruct *map)
Definition: treasure.c:722
void lock_and_hide_doors(object **doorlist, mapstruct *map, int opts, RMParms *RP)
Definition: treasure.c:952
void place_treasure(mapstruct *map, char **layout, char *treasure_style, int treasureoptions, RMParms *RP)
Definition: treasure.c:101
#define DOOR
Definition: define.h:135
treasurelist * find_treasurelist(const char *name)
Definition: treasure.c:295
int number_of_free_spots_in_room
Definition: treasure.c:542
void free_string(sstring str)
Definition: shstr.c:272
struct free_spots_struct free_spots_struct
int keyplace(mapstruct *map, int x, int y, char *keycode, int door_flag, int n_keys, RMParms *RP)
Definition: treasure.c:361
struct treasureliststruct * randomitems
Definition: object.h:236
short freearr_x[SIZEOFFREE]
Definition: object.c:75
const char * slaying
Definition: object.h:172
#define NO_PASS_DOORS
Definition: treasure.c:57
struct obj * above
Definition: object.h:146
int find_spot_in_room(mapstruct *map, int x, int y, int *kx, int *ky, RMParms *RP)
Definition: treasure.c:600
#define OUT_OF_REAL_MAP(M, X, Y)
Definition: map.h:238
sint16 x
Definition: object.h:179
int distance(const object *ob1, const object *ob2)
Definition: object.c:3364
#define KEYREQUIRED
Definition: treasure.c:48
object * pick_random_object(mapstruct *style)
Definition: style.c:275
#define RICH
Definition: treasure.c:52
#define FLAG_REMOVED
Definition: define.h:528
sint16 hp
Definition: living.h:81
short freearr_y[SIZEOFFREE]
Definition: object.c:81
#define SPARSE
Definition: treasure.c:51
#define SPIRAL_LAYOUT
Definition: random_map.h:92
#define CONCENTRATED
Definition: treasure.c:46
void remove_ob(object *op)
Definition: object.c:1515
#define FLAG_ALIVE
Definition: define.h:526
int map_layout_style
Definition: random_map.h:76
#define DOORED
Definition: treasure.c:49
object * create_archetype(const char *name)
Definition: arch.c:625
long unsigned int total_map_hp
Definition: random_map.h:77
int surround_flag3(mapstruct *map, int i, int j, RMParms *RP)
Definition: wall.c:120
object * find_closest_monster(mapstruct *map, int x, int y, RMParms *RP)
Definition: treasure.c:311
int * room_free_spots_x
Definition: treasure.c:540
#define LAST_OPTION
Definition: treasure.c:54
struct mapdef * map
Definition: object.h:155
int find_first_free_spot(const object *ob, mapstruct *m, int x, int y)
Definition: object.c:3240
const char * name
Definition: object.h:167
char dungeon_name[RM_SIZE]
Definition: random_map.h:57
object * retrofit_joined_wall(mapstruct *the_map, int i, int j, int insert_flag, RMParms *RP)
Definition: wall.c:362
static object ** surround_by_doors(mapstruct *map, char **layout, int x, int y, int opts)
Definition: treasure.c:755
object * find_monster_in_room(mapstruct *map, int x, int y, RMParms *RP)
Definition: treasure.c:513
int dungeon_level
Definition: random_map.h:69
sint8 Cha
Definition: living.h:78
object * place_chest(int treasureoptions, int x, int y, mapstruct *map, mapstruct *style_map, int n_treasures, RMParms *RP)
Definition: treasure.c:232
#define SIZEOFFREE
Definition: define.h:441
#define P_OUT_OF_MAP
Definition: map.h:272
#define GET_MAP_MOVE_BLOCK(M, X, Y)
Definition: map.h:213
sint16 y
Definition: object.h:179
#define LOCKED_DOOR
Definition: define.h:132
#define SQUARE_SPIRAL_LAYOUT
Definition: random_map.h:95
#define QUERY_FLAG(xyz, p)
Definition: define.h:514
static void remove_adjacent_doors(object *door)
Definition: treasure.c:910
object * insert_ob_in_ob(object *op, object *where)
Definition: object.c:2510
int symmetry_used
Definition: random_map.h:79
static object * door_in_square(mapstruct *map, int x, int y)
Definition: treasure.c:801
object * insert_ob_in_map(object *op, mapstruct *m, object *originator, int flag)
Definition: object.c:1992
int Ysize
Definition: random_map.h:60
int wall_blocked(mapstruct *m, int x, int y)
Definition: treasure.c:73
#define MOVE_BLOCK_DEFAULT
Definition: define.h:717
static const flag_definition flags[]
int Xsize
Definition: random_map.h:59
#define GET_MAP_FLAGS(M, X, Y)
Definition: map.h:182
#define PASS_DOORS
Definition: treasure.c:58
int snprintf(char *dest, int max, const char *format,...)
Definition: porting.c:498
#define TRAPPED
Definition: treasure.c:50
living stats
Definition: object.h:219
struct archt * arch
Definition: object.h:263
int * room_free_spots_y
Definition: treasure.c:541
sstring add_string(const char *str)
Definition: shstr.c:116
#define BC_RANDOM(x)
Definition: random_map.h:136
#define GET_MAP_OB(M, X, Y)
Definition: map.h:193
#define FLAG_MONSTER
Definition: define.h:541
#define SIZEOFFREE1
Definition: define.h:439
struct obj * head
Definition: object.h:154
void LOG(LogLevel logLevel, const char *format,...)
Definition: logger.c:63
int difficulty
Definition: random_map.h:66
mapstruct * find_style(const char *dirname, const char *stylename, int difficulty)
Definition: style.c:177
void copy_object(object *op2, object *op)
Definition: object.c:758
void free_object(object *ob)
Definition: object.c:1238
Definition: map.h:346
#define P_IS_ALIVE
Definition: map.h:258
New_Face * face
Definition: object.h:183
sint16 level
Definition: object.h:202
object * arch_to_object(archetype *at)
Definition: arch.c:576
uint8 type
Definition: object.h:189
object * find_monster_in_room_recursive(char **layout, mapstruct *map, int x, int y, RMParms *RP)
Definition: treasure.c:465
#define HIDDEN
Definition: treasure.c:47