00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00034 #include <global.h>
00035 #include <random_map.h>
00036 #include <rproto.h>
00037
00042 #define NUM_OF_SPECIAL_TYPES 4
00043 #define NO_SPECIAL 0
00044 #define SPECIAL_SUBMAP 1
00045 #define SPECIAL_FOUNTAIN 2
00046 #define SPECIAL_EXIT 3
00047
00053 #define GLORY_HOLE 1
00054 #define ORC_ZONE 2
00055 #define MINING_ZONE 3
00056 #define NR_OF_HOLE_TYPES 3
00057
00070 void nuke_map_region(mapstruct *map, int xstart, int ystart, int xsize, int ysize) {
00071 int i, j;
00072 object *tmp;
00073
00074 for (i = xstart; i < xstart+xsize; i++)
00075 for (j = ystart; j < ystart+ysize; j++) {
00076 for (tmp = GET_MAP_OB(map, i, j); tmp != NULL; tmp = tmp->above) {
00077 if (!QUERY_FLAG(tmp, FLAG_IS_FLOOR)) {
00078 if (tmp->head)
00079 tmp = tmp->head;
00080 remove_ob(tmp);
00081 free_object(tmp);
00082 tmp = GET_MAP_OB(map, i, j);
00083 }
00084 if (tmp == NULL)
00085 break;
00086 }
00087 }
00088 }
00089
00100 void include_map_in_map(mapstruct *dest_map, mapstruct *in_map, int x, int y) {
00101 int i, j;
00102 object *tmp;
00103 object *new_ob;
00104
00105
00106 nuke_map_region(dest_map, x, y, MAP_WIDTH(in_map), MAP_HEIGHT(in_map));
00107
00108 for (i = 0; i < MAP_WIDTH(in_map); i++)
00109 for (j = 0; j < MAP_HEIGHT(in_map); j++) {
00110 for (tmp = GET_MAP_OB(in_map, i, j); tmp != NULL; tmp = tmp->above) {
00111
00112
00113 if (tmp->head != NULL)
00114 continue;
00115 new_ob = arch_to_object(tmp->arch);
00116 copy_object_with_inv(tmp, new_ob);
00117 if (QUERY_FLAG(tmp, FLAG_IS_LINKED))
00118 add_button_link(new_ob, dest_map, tmp->path_attuned);
00119 new_ob->x = i+x;
00120 new_ob->y = j+y;
00121 insert_multisquare_ob_in_map(new_ob, dest_map);
00122 }
00123 }
00124 }
00125
00141 int find_spot_for_submap(mapstruct *map, char **layout, int *ix, int *iy, int xsize, int ysize) {
00142 int tries;
00143 int i = 0, j = 0;
00144 int is_occupied = 0;
00145 int l, m;
00146
00147
00148
00149 if (2*xsize > MAP_WIDTH(map) || 2*ysize > MAP_HEIGHT(map))
00150 return 0;
00151
00152
00153 for (tries = 0; tries < 20; tries++) {
00154
00155 i = RANDOM()%(MAP_WIDTH(map)-xsize-2)+1;
00156 j = RANDOM()%(MAP_HEIGHT(map)-ysize-2)+1;
00157 is_occupied = 0;
00158 for (l = i; l < i+xsize; l++)
00159 for (m = j; m < j+ysize; m++)
00160 is_occupied |= layout[l][m];
00161 if (!is_occupied)
00162 break;
00163 }
00164
00165
00166 if (is_occupied) {
00167
00168 for (tries = 0; tries < 10; tries++) {
00169 i = RANDOM()%(MAP_WIDTH(map)-xsize-2)+1;
00170 j = RANDOM()%(MAP_HEIGHT(map)-ysize-2)+1;
00171 is_occupied = 0;
00172 for (l = i; l < i+xsize; l++)
00173 for (m = j; m < j+ysize; m++)
00174 if (layout[l][m] == 'C' || layout[l][m] == '>' || layout[l][m] == '<')
00175 is_occupied |= 1;
00176 }
00177 }
00178 if (is_occupied)
00179 return 0;
00180 *ix = i;
00181 *iy = j;
00182 return 1;
00183 }
00184
00192 void place_fountain_with_specials(mapstruct *map) {
00193 int ix, iy, i = -1, tries = 0;
00194 mapstruct *fountain_style = find_style("/styles/misc", "fountains", -1);
00195 object *fountain = create_archetype("fountain");
00196 object *potion = get_object();
00197
00198 copy_object(pick_random_object(fountain_style), potion);
00199 while (i < 0 && tries < 10) {
00200 ix = RANDOM()%(MAP_WIDTH(map)-2)+1;
00201 iy = RANDOM()%(MAP_HEIGHT(map)-2)+1;
00202 i = find_first_free_spot(fountain, map, ix, iy);
00203 tries++;
00204 };
00205 if (i == -1) {
00206 free_object(fountain);
00207 free_object(potion);
00208 return;
00209 }
00210 ix += freearr_x[i];
00211 iy += freearr_y[i];
00212 potion->face = fountain->face;
00213 SET_FLAG(potion, FLAG_NO_PICK);
00214 SET_FLAG(potion, FLAG_IDENTIFIED);
00215 potion->name = add_string("fountain");
00216 potion->name_pl = add_string("fountain");
00217 potion->x = ix;
00218 potion->y = iy;
00219 potion->material = M_ADAMANT;
00220 fountain->x = ix;
00221 fountain->y = iy;
00222 insert_ob_in_map(fountain, map, NULL, 0);
00223 insert_ob_in_map(potion, map, NULL, 0);
00224 }
00225
00235 void place_special_exit(mapstruct *map, int hole_type, RMParms *RP) {
00236 int ix, iy, i = -1;
00237 char buf[HUGE_BUF];
00238 const char *style, *decor, *mon;
00239 mapstruct *exit_style = find_style("/styles/misc", "obscure_exits", -1);
00240 int g_xsize, g_ysize;
00241 object *the_exit = get_object();
00242
00243 if (!exit_style)
00244 return;
00245
00246 copy_object(pick_random_object(exit_style), the_exit);
00247
00248 while (i < 0) {
00249 ix = RANDOM()%(MAP_WIDTH(map)-2)+1;
00250 iy = RANDOM()%(MAP_HEIGHT(map)-2)+1;
00251 i = find_first_free_spot(the_exit, map, ix, iy);
00252 }
00253
00254 ix += freearr_x[i];
00255 iy += freearr_y[i];
00256 the_exit->x = ix;
00257 the_exit->y = iy;
00258
00259 if (!hole_type)
00260 hole_type = RANDOM()%NR_OF_HOLE_TYPES+1;
00261
00262 switch (hole_type) {
00263 case GLORY_HOLE: {
00264 g_xsize = RANDOM()%3+4+RP->difficulty/4;
00265 g_ysize = RANDOM()%3+4+RP->difficulty/4;
00266 style = "onion";
00267 decor = "wealth2";
00268 mon = "none";
00269 break;
00270 }
00271
00272 case ORC_ZONE: {
00273 g_xsize = RANDOM()%3+4+RP->difficulty/4;
00274 g_ysize = RANDOM()%3+4+RP->difficulty/4;
00275 style = "onion";
00276 decor = "wealth2";
00277 mon = "orc";
00278 break;
00279 }
00280
00281 case MINING_ZONE: {
00282 g_xsize = RANDOM()%9+4+RP->difficulty/4;
00283 g_ysize = RANDOM()%9+4+RP->difficulty/4;
00284 style = "maze";
00285 decor = "minerals2";
00286 mon = "none";
00287 break;
00288 }
00289
00290 default:
00291 LOG(llevError, "place_special_exit: undefined hole type %d\n", hole_type);
00292 return;
00293 break;
00294 }
00295
00296
00297
00298
00299 if (g_xsize < MIN_RANDOM_MAP_SIZE)
00300 g_xsize = MIN_RANDOM_MAP_SIZE;
00301 if (g_ysize < MIN_RANDOM_MAP_SIZE)
00302 g_ysize = MIN_RANDOM_MAP_SIZE;
00303
00304 write_parameters_to_string(buf, g_xsize, g_ysize, RP->wallstyle, RP->floorstyle, mon,
00305 "none", style, decor, "none", RP->exitstyle, NULL, NULL, NULL,
00306 OPT_WALLS_ONLY, 0, 0, 1, RP->dungeon_level, RP->dungeon_level,
00307 RP->difficulty, RP->difficulty, -1, 1, 0, 0, 0, 0, RP->difficulty_increase);
00308 the_exit->slaying = add_string("/!");
00309 the_exit->msg = add_string(buf);
00310
00311 insert_ob_in_map(the_exit, map, NULL, 0);
00312 }
00313
00323 void place_specials_in_map(mapstruct *map, char **layout, RMParms *RP) {
00324 mapstruct *special_map;
00325 int ix, iy;
00326 int special_type;
00327
00328 special_type = RANDOM()%NUM_OF_SPECIAL_TYPES;
00329 switch (special_type) {
00330
00331 case SPECIAL_SUBMAP: {
00332 special_map = find_style("/styles/specialmaps", NULL, RP->difficulty);
00333 if (special_map == NULL)
00334 return;
00335
00336 if (find_spot_for_submap(map, layout, &ix, &iy, MAP_WIDTH(special_map), MAP_HEIGHT(special_map)))
00337 include_map_in_map(map, special_map, ix, iy);
00338 break;
00339 }
00340
00341
00342
00343
00344 case SPECIAL_FOUNTAIN: {
00345 place_fountain_with_specials(map);
00346 break;
00347 }
00348
00349
00350 case SPECIAL_EXIT: {
00351 place_special_exit(map, 0, RP);
00352 break;
00353 }
00354 }
00355 }