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.3 by root, Sun Sep 3 00:18:41 2006 UTC vs.
Revision 1.42 by root, Thu Sep 25 04:35:50 2008 UTC

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

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines