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.2 by root, Tue Aug 29 08:01:36 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.2 2006/08/29 08:01:36 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 = add_string(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 = add_string(keycode);
294
295
296 if(door_flag==PASS_DOORS) {
297 int tries=0;
298 the_keymaster=NULL;
299 while(tries<15&&the_keymaster==NULL) {
300 i = (RANDOM()%(RP->Xsize-2))+1;
301 j = (RANDOM()%(RP->Ysize-2))+1;
302 tries++;
303 the_keymaster=find_closest_monster(map,i,j,RP);
304 }
305 /* if we don't find a good keymaster, drop the key on the ground. */
306 if(the_keymaster==NULL) {
307 int freeindex;
308
309 freeindex = -1;
310 for(tries = 0; tries < 15 && freeindex == -1; tries++) {
311 kx = (RANDOM()%(RP->Xsize-2))+1;
312 ky = (RANDOM()%(RP->Ysize-2))+1;
313 freeindex = find_first_free_spot(the_key,map,kx,ky);
314 }
315 if(freeindex != -1) {
316 kx += freearr_x[freeindex];
317 ky += freearr_y[freeindex];
318 }
319 }
320 }
321 else { /* NO_PASS_DOORS --we have to work harder.*/
322 /* don't try to keyplace if we're sitting on a blocked square and
323 NO_PASS_DOORS is set. */
324 if(n_keys==1) {
325 if(wall_blocked(map,x,y)) return 0;
326 the_keymaster=find_monster_in_room(map,x,y,RP);
327 if(the_keymaster==NULL) /* if fail, find a spot to drop the key. */
328 find_spot_in_room(map,x,y,&kx,&ky,RP);
329 }
330 else {
331 int sum=0; /* count how many keys we actually place */
332 /* I'm lazy, so just try to place in all 4 directions. */
333 sum +=keyplace(map,x+1,y,keycode,NO_PASS_DOORS,1,RP);
334 sum +=keyplace(map,x,y+1,keycode,NO_PASS_DOORS,1,RP);
335 sum +=keyplace(map,x-1,y,keycode,NO_PASS_DOORS,1,RP);
336 sum +=keyplace(map,x,y-1,keycode,NO_PASS_DOORS,1,RP);
337 if(sum < 2) /* we might have made a disconnected map-place more keys. */
338 { /* diagnoally this time. */
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 keyplace(map,x-1,y-1,keycode,NO_PASS_DOORS,1,RP);
343 }
344 return 1;
345 }
346 }
347
348 if(the_keymaster==NULL) {
349 the_key->x = kx;
350 the_key->y = ky;
351 insert_ob_in_map(the_key,map,NULL,0);
352 return 1;
353 }
354
355 insert_ob_in_ob(the_key,the_keymaster);
356 return 1;
357}
358
359
360
361/* 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. */
362 444
363object *theMonsterToFind; 445object *theMonsterToFind;
364 446
365/* 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.
366 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 */
367 449
450object *
368object *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{
369 int i,j; 453 int i, j;
454
370 /* if we've found a monster already, leave */ 455 /* if we've found a monster already, leave */
371 if(theMonsterToFind!=NULL) return theMonsterToFind; 456 if (theMonsterToFind != NULL)
457 return theMonsterToFind;
372 458
373 /* bounds check x and y */ 459 /* bounds check x and y */
374 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;
375 462
376 /* 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)
377 if(layout[x][y]!=0) return theMonsterToFind; /* might be NULL, that's fine.*/ 465 return theMonsterToFind; /* might be NULL, that's fine. */
378 466
379 /* check the current square for a monster. If there is one, 467 /* check the current square for a monster. If there is one,
380 set theMonsterToFind and return it. */ 468 set theMonsterToFind and return it. */
381 layout[x][y]=1; 469 layout[x][y] = 1;
382 if(GET_MAP_FLAGS(map,x,y) & P_IS_ALIVE) { 470 if (GET_MAP_FLAGS (map, x, y) & P_IS_ALIVE)
471 {
383 object *the_monster = get_map_ob(map,x,y); 472 object *the_monster = GET_MAP_OB (map, x, y);
473
384 /* check off this point */ 474 /* check off this point */
385 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);
386 if(the_monster && QUERY_FLAG(the_monster,FLAG_ALIVE)) { 476 if (the_monster && QUERY_FLAG (the_monster, FLAG_ALIVE))
477 {
387 theMonsterToFind=the_monster; 478 theMonsterToFind = the_monster;
388 return theMonsterToFind; 479 return theMonsterToFind;
389 } 480 }
390 } 481 }
391 482
392 /* 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 */
393 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 {
394 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);
395 if(theMonsterToFind!=NULL) return theMonsterToFind; 487 if (theMonsterToFind != NULL)
488 return theMonsterToFind;
396 } 489 }
490
397 return theMonsterToFind; 491 return theMonsterToFind;
398} 492}
399
400 493
401/* sets up some data structures: the _recursive form does the 494/* sets up some data structures: the _recursive form does the
402 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);
403 500
404object *find_monster_in_room(mapstruct *map,int x,int y,RMParms *RP) { 501 layout2->clear ();
405 char **layout2; 502
406 int i,j;
407 theMonsterToFind=0;
408 layout2 = (char **) calloc(sizeof(char *),RP->Xsize);
409 /* allocate and copy the layout, converting C to 0. */ 503 /* allocate and copy the layout, converting C to 0. */
410 for(i=0;i<RP->Xsize;i++) { 504 for (int i = 0; i < layout2->w; i++)
411 layout2[i]=(char *)calloc(sizeof(char),RP->Ysize); 505 for (int j = 0; j < layout2->h; j++)
412 for(j=0;j<RP->Ysize;j++) { 506 if (wall_blocked (map, i, j))
413 if(wall_blocked(map,i,j)) layout2[i][j] = '#'; 507 layout2[i][j] = '#';
414 } 508
415 } 509 theMonsterToFind = 0;
416 theMonsterToFind = find_monster_in_room_recursive(layout2,map,x,y,RP); 510 theMonsterToFind = find_monster_in_room_recursive (layout2, map, x, y, RP);
417 511
418 /* deallocate the temp. layout */ 512 layout2.free ();
419 for(i=0;i<RP->Xsize;i++) {
420 free(layout2[i]);
421 }
422 free(layout2);
423 513
424 return theMonsterToFind; 514 return theMonsterToFind;
425} 515}
426
427 516
428
429
430/* 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 */
431int *room_free_spots_x; 518int *room_free_spots_x;
432int *room_free_spots_y; 519int *room_free_spots_y;
433int number_of_free_spots_in_room; 520int number_of_free_spots_in_room;
434 521
435/* the workhorse routine, which finds the free spots in a room: 522/* the workhorse routine, which finds the free spots in a room:
436a 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
437that datastructure. */ 524that datastructure. */
438 525void
439void 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{
440 int i,j; 528 int i, j;
441 529
442 /* bounds check x and y */ 530 /* bounds check x and y */
443 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;
444 533
445 /* if the square is blocked or searched already, leave */ 534 /* if the square is blocked or searched already, leave */
446 if(layout[x][y]!=0) return; 535 if (layout[x][y] != 0)
536 return;
447 537
448 /* 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.
449 set theMonsterToFind and return it. */ 539 set theMonsterToFind and return it. */
450 /* check off this point */ 540 /* check off this point */
451 layout[x][y]=1; 541 layout[x][y] = 1;
452 room_free_spots_x[number_of_free_spots_in_room]=x; 542 room_free_spots_x[number_of_free_spots_in_room] = x;
453 room_free_spots_y[number_of_free_spots_in_room]=y; 543 room_free_spots_y[number_of_free_spots_in_room] = y;
454 number_of_free_spots_in_room++; 544 number_of_free_spots_in_room++;
545
455 /* 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 */
456 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++)
457 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);
458 }
459 549
460} 550}
461 551
462/* 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
463void 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{
464 char **layout2; 556 char **layout2;
465 int i,j; 557 int i, j;
558
466 number_of_free_spots_in_room=0; 559 number_of_free_spots_in_room = 0;
467 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);
468 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);
469 562
470 layout2 = (char **) calloc(sizeof(char *),RP->Xsize); 563 layout2 = (char **) calloc (sizeof (char *), RP->Xsize);
471 /* allocate and copy the layout, converting C to 0. */ 564 /* allocate and copy the layout, converting C to 0. */
472 for(i=0;i<RP->Xsize;i++) { 565 for (i = 0; i < RP->Xsize; i++)
566 {
473 layout2[i]=(char *)calloc(sizeof(char),RP->Ysize); 567 layout2[i] = (char *) calloc (sizeof (char), RP->Ysize);
474 for(j=0;j<RP->Ysize;j++) { 568 for (j = 0; j < RP->Ysize; j++)
475 if(wall_blocked(map,i,j)) layout2[i][j] = '#'; 569 if (wall_blocked (map, i, j))
476 } 570 layout2[i][j] = '#';
477 } 571 }
478 572
479 /* setup num_free_spots and room_free_spots */ 573 /* setup num_free_spots and room_free_spots */
480 find_spot_in_room_recursive(layout2,x,y,RP); 574 find_spot_in_room_recursive (layout2, x, y, RP);
481 575
482 if(number_of_free_spots_in_room > 0) { 576 if (number_of_free_spots_in_room > 0)
577 {
483 i = RANDOM()%number_of_free_spots_in_room; 578 i = rmg_rndm (number_of_free_spots_in_room);
484 *kx = room_free_spots_x[i]; 579 *kx = room_free_spots_x[i];
485 *ky = room_free_spots_y[i]; 580 *ky = room_free_spots_y[i];
486 } 581 }
487 582
488 /* deallocate the temp. layout */ 583 /* deallocate the temp. layout */
489 for(i=0;i<RP->Xsize;i++) { 584 for (i = 0; i < RP->Xsize; i++)
490 free(layout2[i]); 585 free (layout2[i]);
491 } 586
492 free(layout2); 587 free (layout2);
493 free(room_free_spots_x); 588 free (room_free_spots_x);
494 free(room_free_spots_y); 589 free (room_free_spots_y);
495} 590}
496 591
497 592
498/* 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
499 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
500 it'll return 0 if no FREE spots are found.*/ 595 it'll return 0 if no FREE spots are found.*/
501 596void
502void 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{
503 int x,y; 599 int x, y;
504 int i; 600 int i;
601
505 x = *cx;y=*cy; 602 x = *cx;
603 y = *cy;
506 604
507 for(i=0;i<=SIZEOFFREE1;i++) { 605 for (i = 0; i <= SIZEOFFREE1; i++)
606 {
508 int lx,ly,sindex; 607 int lx, ly, sindex;
608
509 lx = x +freearr_x[i]; 609 lx = x + freearr_x[i];
510 ly = y +freearr_y[i]; 610 ly = y + freearr_y[i];
511 sindex = surround_flag3(map,lx,ly,RP); 611 sindex = surround_flag3 (map, lx, ly, RP);
512 /* if it's blocked on 3 sides, it's enclosed */ 612 /* if it's blocked on 3 sides, it's enclosed */
513 if(sindex==7 || sindex == 11 || sindex == 13 || sindex == 14) { 613 if (sindex == 7 || sindex == 11 || sindex == 13 || sindex == 14)
514 *cx= lx;*cy= ly; 614 {
615 *cx = lx;
616 *cy = ly;
515 return; 617 return;
516 } 618 }
517 } 619 }
518 620
519 /* 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
520 spots--try to find someplace which is 2x enclosed. */ 622 spots--try to find someplace which is 2x enclosed. */
521 for(i=0;i<=SIZEOFFREE1;i++) { 623 for (i = 0; i <= SIZEOFFREE1; i++)
624 {
522 int lx,ly,sindex; 625 int lx, ly, sindex;
626
523 lx = x +freearr_x[i]; 627 lx = x + freearr_x[i];
524 ly = y +freearr_y[i]; 628 ly = y + freearr_y[i];
525 sindex = surround_flag3(map,lx,ly,RP); 629 sindex = surround_flag3 (map, lx, ly, RP);
526 /* if it's blocked on 3 sides, it's enclosed */ 630 /* if it's blocked on 3 sides, it's enclosed */
527 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)
528 *cx= lx;*cy= ly; 632 {
633 *cx = lx;
634 *cy = ly;
529 return; 635 return;
530 } 636 }
531 } 637 }
532 638
533 /* settle for one surround point */ 639 /* settle for one surround point */
534 for(i=0;i<=SIZEOFFREE1;i++) { 640 for (i = 0; i <= SIZEOFFREE1; i++)
641 {
535 int lx,ly,sindex; 642 int lx, ly, sindex;
643
536 lx = x +freearr_x[i]; 644 lx = x + freearr_x[i];
537 ly = y +freearr_y[i]; 645 ly = y + freearr_y[i];
538 sindex = surround_flag3(map,lx,ly,RP); 646 sindex = surround_flag3 (map, lx, ly, RP);
539 /* if it's blocked on 3 sides, it's enclosed */ 647 /* if it's blocked on 3 sides, it's enclosed */
540 if(sindex) { 648 if (sindex)
541 *cx= lx;*cy= ly; 649 {
650 *cx = lx;
651 *cy = ly;
542 return; 652 return;
543 } 653 }
544 } 654 }
545 /* give up and return the closest free spot. */ 655 /* give up and return the closest free spot. */
546 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);
547 if(i!=-1&&i<=SIZEOFFREE1) { 657
658 if (i != -1)
659 {
548 *cx = x +freearr_x[i]; 660 *cx = x + freearr_x[i];
549 *cy = y +freearr_y[i]; 661 *cy = y + freearr_y[i];
550 return;
551 } 662 }
663 else
664 {
552 /* indicate failure */ 665 /* indicate failure */
553 *cx=*cy=-1; 666 *cx = -1;
667 *cy = -1;
668 }
554} 669}
555 670
556 671void
557void remove_monsters(int x,int y,mapstruct *map) { 672remove_monsters (int x, int y, maptile *map)
673{
558 object *tmp; 674 object *tmp;
559 675
560 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)
561 if(QUERY_FLAG(tmp,FLAG_ALIVE)) { 677 if (QUERY_FLAG (tmp, FLAG_ALIVE))
562 if(tmp->head) tmp=tmp->head; 678 {
563 remove_ob(tmp); 679 if (tmp->head)
564 free_object(tmp); 680 tmp = tmp->head;
565 tmp=get_map_ob(map,x,y); 681 tmp->remove ();
682 tmp->destroy ();
683 tmp = GET_MAP_OB (map, x, y);
566 if(tmp==NULL) break; 684 if (tmp == NULL)
685 break;
567 }; 686 };
568} 687}
569
570 688
571/* 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
572 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
573 it'll remove any monsters it finds.*/ 691 it'll remove any monsters it finds.*/
574 692object **
575object ** 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{
576 int i; 695 int i;
577 char *doors[2]; 696 const char *doors[2];
578 object **doorlist; 697 object **doorlist;
579 int ndoors_made=0; 698 int ndoors_made = 0;
580 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 */
581 700
582 /* 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 */
583 if(opts&DOORED) { 702 if (opts & DOORED)
703 {
584 doors[0]="locked_door2"; 704 doors[0] = "locked_door2";
585 doors[1]="locked_door1"; 705 doors[1] = "locked_door1";
586 } 706 }
587 else { 707 else
708 {
588 doors[0]="door_1"; 709 doors[0] = "door_1";
589 doors[1]="door_2"; 710 doors[1] = "door_2";
590 } 711 }
591 712
592 /* place doors in all the 8 adjacent unblocked squares. */ 713 /* place doors in all the 8 adjacent unblocked squares. */
593 for(i=1;i<9;i++) { 714 for (i = 1; i < 9; i++)
715 {
594 int x1 = x + freearr_x[i], y1 = y+freearr_y[i]; 716 int x1 = x + freearr_x[i], y1 = y + freearr_y[i];
595 717
596 if(!wall_blocked(map,x1,y1) 718 if (!wall_blocked (map, x1, y1) && layout[x1][y1] == '>')
597 || layout[x1][y1]=='>') {/* place a door */ 719 { /* place a door */
720 remove_monsters (x1, y1, map);
721
598 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]);
599 new_door->x = x + freearr_x[i]; 723 map->insert (new_door, x1, y1);
600 new_door->y = y + freearr_y[i];
601 remove_monsters(new_door->x,new_door->y,map);
602 insert_ob_in_map(new_door,map,NULL,0);
603 doorlist[ndoors_made]=new_door; 724 doorlist[ndoors_made] = new_door;
604 ndoors_made++; 725 ndoors_made++;
605 } 726 }
606 } 727 }
728
607 return doorlist; 729 return doorlist;
608} 730}
609 731
610 732
611/* 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 *
612object *door_in_square(mapstruct *map,int x,int y) { 735door_in_square (maptile *map, int x, int y)
736{
613 object *tmp; 737 object *tmp;
738
614 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)
615 if(tmp->type == DOOR || tmp->type== LOCKED_DOOR) return tmp; 740 if (tmp->type == DOOR || tmp->type == LOCKED_DOOR)
741 return tmp;
616 return NULL; 742 return NULL;
617} 743}
618
619 744
620/* the workhorse routine, which finds the doors in a room */ 745/* the workhorse routine, which finds the doors in a room */
746void
621void 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{
622 int i,j; 749 int i, j;
623 object *door; 750 object *door;
624 751
625 /* bounds check x and y */ 752 /* bounds check x and y */
626 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;
627 755
628 /* if the square is blocked or searched already, leave */ 756 /* if the square is blocked or searched already, leave */
629 if(layout[x][y]==1) return; 757 if (layout[x][y] == 1)
758 return;
630 759
631 /* check off this point */ 760 /* check off this point */
632 if(layout[x][y]=='#') { /* there could be a door here */ 761 if (layout[x][y] == '#')
762 { /* there could be a door here */
633 layout[x][y]=1; 763 layout[x][y] = 1;
634 door=door_in_square(map,x,y); 764 door = door_in_square (map, x, y);
635 if(door!=NULL) { 765 if (door)
766 {
636 doorlist[*ndoors]=door; 767 doorlist[*ndoors] = door;
768
637 if(*ndoors>254) /* eek! out of memory */ 769 if (*ndoors > 1022) /* eek! out of memory */
638 { 770 {
639 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");
640 return; 772 return;
641 } 773 }
774
642 *ndoors=*ndoors+1; 775 *ndoors = *ndoors + 1;
643 } 776 }
644 } 777 }
645 else { 778 else
779 {
646 layout[x][y]=1; 780 layout[x][y] = 1;
781
647 /* 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 */
648 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++)
649 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,
650 } 785 x + freearr_x[i % 8 + 1], y + freearr_y[i % 8 + 1],
786 doorlist, ndoors, RP);
651 } 787 }
652} 788}
653 789
654/* 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. */
655object** find_doors_in_room(mapstruct *map,int x,int y,RMParms *RP) { 791object **
656 char **layout2; 792find_doors_in_room (maptile *map, int x, int y, random_map_params *RP)
657 object **doorlist; 793{
658 int i,j; 794 int i, j;
659 int ndoors=0; 795 int ndoors = 0;
660 796
661 doorlist = (object **)calloc(sizeof(int),256); 797 object **doorlist = (object **)calloc (sizeof (int), 1024);
662 798
799 LayoutData layout2 (RP->Xsize, RP->Ysize);
800 layout2.clear ();
663 801
664 layout2 = (char **) calloc(sizeof(char *),RP->Xsize);
665 /* allocate and copy the layout, converting C to 0. */ 802 /* allocate and copy the layout, converting C to 0. */
666 for(i=0;i<RP->Xsize;i++) { 803 for (i = 0; i < RP->Xsize; i++)
667 layout2[i]=(char *)calloc(sizeof(char),RP->Ysize);
668 for(j=0;j<RP->Ysize;j++) { 804 for (j = 0; j < RP->Ysize; j++)
669 if(wall_blocked(map,i,j)) layout2[i][j] = '#'; 805 layout2[i][j] = wall_blocked (map, i, j) ? '#' : 0;
670 } 806
671 }
672
673 /* setup num_free_spots and room_free_spots */ 807 /* setup num_free_spots and room_free_spots */
674 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);
675 809
676 /* deallocate the temp. layout */
677 for(i=0;i<RP->Xsize;i++) {
678 free(layout2[i]);
679 }
680 free(layout2);
681 return doorlist; 810 return doorlist;
682} 811}
683
684
685 812
686/* 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
687 opts doesn't say to lock/hide doors. */ 814 opts doesn't say to lock/hide doors. */
688 815void
689void 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{
690 object *door; 818 object *door;
691 int i; 819 int i;
820
692 /* lock the doors and hide the keys. */ 821 /* lock the doors and hide the keys. */
693 822
694 if(opts & DOORED) { 823 if (opts & DOORED)
824 {
695 for(i=0,door=doorlist[0];doorlist[i]!=NULL;i++) { 825 for (i = 0, door = doorlist[0]; doorlist[i] != NULL; i++)
826 {
696 object *new_door=get_archetype("locked_door1"); 827 object *new_door = get_archetype (shstr_locked_door1);
697 char keybuf[256]; 828
698 door=doorlist[i]; 829 door = doorlist[i];
699 new_door->face = door->face; 830 new_door->face = door->face;
700 new_door->x = door->x; 831 new_door->x = door->x;
701 new_door->y = door->y; 832 new_door->y = door->y;
702 remove_ob(door); 833 door->remove ();
703 free_object(door); 834 door->destroy ();
704 doorlist[i]=new_door; 835 doorlist[i] = new_door;
705 insert_ob_in_map(new_door,map,NULL,0); 836 insert_ob_in_map (new_door, map, NULL, 0);
706 sprintf(keybuf,"%d",(int)RANDOM()); 837 new_door->slaying = format ("RMG-%d-%d", (int)rmg_rndm (1000000000), (int)rmg_rndm (1000000000));
707 new_door->slaying = add_string(keybuf);
708 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);
709 } 839 }
710 } 840 }
711 841
712 /* 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. */
713 if(opts & HIDDEN) { 843 if (opts & HIDDEN)
844 {
714 for(i=0,door=doorlist[0];doorlist[i]!=NULL;i++) { 845 for (i = 0, door = doorlist[0]; doorlist[i] != NULL; i++)
846 {
715 object *wallface; 847 object *wallface;
848
716 door=doorlist[i]; 849 door = doorlist[i];
717 wallface=retrofit_joined_wall(map,door->x,door->y,1,RP); 850 wallface = retrofit_joined_wall (map, door->x, door->y, 1, RP);
718 if(wallface!=NULL) { 851 if (wallface != NULL)
852 {
719 retrofit_joined_wall(map,door->x-1,door->y,0,RP); 853 retrofit_joined_wall (map, door->x - 1, door->y, 0, RP);
720 retrofit_joined_wall(map,door->x+1,door->y,0,RP); 854 retrofit_joined_wall (map, door->x + 1, door->y, 0, RP);
721 retrofit_joined_wall(map,door->x,door->y-1,0,RP); 855 retrofit_joined_wall (map, door->x, door->y - 1, 0, RP);
722 retrofit_joined_wall(map,door->x,door->y+1,0,RP); 856 retrofit_joined_wall (map, door->x, door->y + 1, 0, RP);
857
723 door->face = wallface->face; 858 door->face = wallface->face;
859
724 if(!QUERY_FLAG(wallface,FLAG_REMOVED)) remove_ob(wallface); 860 if (!QUERY_FLAG (wallface, FLAG_REMOVED))
725 free_object(wallface); 861 wallface->remove ();
862
863 wallface->destroy ();
864 }
726 } 865 }
727 }
728 } 866 }
729} 867}

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines