/* * generate.c: initialize/create a dungeon or town level * * Copyright (c) 1989 James E. Wilson, Robert A. Koeneke * * This software may be copied and distributed for educational, research, and * not for profit purposes provided that this copyright and statement are * included in all such copies. */ #include "constant.h" #include "config.h" #include "types.h" #include "externs.h" #include "monster.h" #ifdef ibm032 #include #endif #ifdef USG #if !defined(ATARIST_MWC) #ifndef __TURBOC__ #include #else #include #endif #endif #endif #ifdef __MINT__ #include #endif /* Lets do all prototypes correctly.... -CWS */ #ifndef NO_LINT_ARGS #ifdef __STDC__ static void correct_dir(int *, int *, int, int, int, int); static void rand_dir(int *, int *); static void fill_cave(int); static void place_streamer(int, int); static cave_type *test_place_obj(int, int); static void place_open_door(int, int); static void place_broken_door(int, int); static void place_closed_door(int, int); static void place_locked_door(int, int); static void place_stuck_door(int, int); static void place_secret_door(int, int); static void place_door(int, int); static void place_up_stairs(int, int); static void place_down_stairs(int, int); static void place_stairs(int, int, int); static void vault_trap(int, int, int, int, int); static void vault_monster(int, int, int); static void vault_jelly(int, int); static void vault_orc(int, int, int); static void vault_troll(int, int, int); static void vault_undead(int, int); static void vault_dragon(int, int, int, int); static void vault_demon(int, int, int); static void vault_giant(int, int, int); static void build_room(int, int); static void build_type1(int, int); static void build_type5(int, int); static void build_type2(int, int); static void build_type3(int, int); static void vault_nasty(int, int, int, int, int); static void special_pit(int, int, int); static void build_tunnel(int, int, int, int); static int next_to(int, int); static void try_door(int, int); static void new_spot(int16 *, int16 *); static void build_pit(int, int); static void build_store(int, int, int); #else static void correct_dir(); static void rand_dir(); static void fill_cave(); static void place_streamer(); static cave_type *test_place_obj(); static void place_open_door(); static void place_broken_door(); static void place_closed_door(); static void place_locked_door(); static void place_stuck_door(); static void place_secret_door(); static void place_door(); static void place_up_stairs(); static void place_down_stairs(); static void place_stairs(); static void vault_trap(); static void vault_monster(); static void vault_jelly(); static void vault_orc(); static void vault_troll(); static void vault_undead(); static void vault_dragon(); static void vault_demon(); static void vault_giant(); static void build_room(); static void build_type1(); static void build_type5(); static void build_type2(); static void build_type3(); static void vault_nasty(); static void special_pit(); static int next_to(); static void try_door(); static void new_spot(); static void build_pit(); static void build_store(); #endif static void place_boundary(); static void place_destroyed(); static void blank_cave(); static void cave_gen(); static void tlink(); static void mlink(); static void town_gen(); #endif typedef struct coords { int x, y; } coords; static coords doorstk[100]; static int doorindex; extern int rating; extern int peek; /* Always picks a correct direction */ static void correct_dir(rdir, cdir, y1, x1, y2, x2) int *rdir, *cdir; register int y1, x1, y2, x2; { if (y1 < y2) *rdir = 1; else if (y1 == y2) *rdir = 0; else *rdir = (-1); if (x1 < x2) *cdir = 1; else if (x1 == x2) *cdir = 0; else *cdir = (-1); if ((*rdir != 0) && (*cdir != 0)) { if (randint(2) == 1) *rdir = 0; else *cdir = 0; } } /* Chance of wandering direction */ static void rand_dir(rdir, cdir) int *rdir, *cdir; { register int tmp; tmp = randint(4); if (tmp < 3) { *cdir = 0; *rdir = (-3) + (tmp << 1); /* tmp=1 -> *rdir=-1; tmp=2 -> *rdir=1 */ } else { *rdir = 0; *cdir = (-7) + (tmp << 1); /* tmp=3 -> *cdir=-1; tmp=4 -> *cdir=1 */ } } /* Blanks out entire cave -RAK- */ static void blank_cave() { #ifndef USG bzero((char *)&cave[0][0], sizeof(cave)); #else #ifdef MAC /* On the mac, cave is a pointer, so sizeof(cave) = 4! */ (void)memset((char *)&cave[0][0], 0, sizeof(cave_type) * MAX_HEIGHT * MAX_WIDTH); #else (void)memset((char *)&cave[0][0], 0, sizeof(cave)); #endif #endif } /* Fills in empty spots with desired rock -RAK- */ /* Note: 9 is a temporary value. */ static void fill_cave(fval) register int fval; { register int i, j; register cave_type *c_ptr; /* no need to check the border of the cave */ for (i = cur_height - 2; i > 0; i--) { c_ptr = &cave[i][1]; for (j = cur_width - 2; j > 0; j--) { if ((c_ptr->fval == NULL_WALL) || (c_ptr->fval == TMP1_WALL) || (c_ptr->fval == TMP2_WALL)) c_ptr->fval = fval; c_ptr++; } } } /* Places indestructible rock around edges of dungeon -RAK- */ static void place_boundary() { register int i; register cave_type *top_ptr, *bottom_ptr; cave_type(*left_ptr)[MAX_WIDTH]; cave_type(*right_ptr)[MAX_WIDTH]; /* put permanent wall on leftmost row and rightmost row */ left_ptr = (cave_type(*)[MAX_WIDTH]) & cave[0][0]; right_ptr = (cave_type(*)[MAX_WIDTH]) & cave[0][cur_width - 1]; for (i = 0; i < cur_height; i++) { ((cave_type *) left_ptr)->fval = BOUNDARY_WALL; left_ptr++; ((cave_type *) right_ptr)->fval = BOUNDARY_WALL; right_ptr++; } /* put permanent wall on top row and bottom row */ top_ptr = &cave[0][0]; bottom_ptr = &cave[cur_height - 1][0]; for (i = 0; i < cur_width; i++) { top_ptr->fval = BOUNDARY_WALL; top_ptr++; bottom_ptr->fval = BOUNDARY_WALL; bottom_ptr++; } } /* Places "streamers" of rock through dungeon -RAK- */ static void place_streamer(fval, treas_chance) int fval, treas_chance; { register int i, tx, ty; int y, x, t1, t2, dir; register cave_type *c_ptr; /* Choose starting point and direction */ y = (cur_height / 2) + 11 - randint(23); x = (cur_width / 2) + 16 - randint(33); dir = randint(8); /* Number 1-4, 6-9 */ if (dir > 4) dir = dir + 1; /* Place streamer into dungeon */ t1 = 2 * DUN_STR_RNG + 1; /* Constants */ t2 = DUN_STR_RNG + 1; do { for (i = 0; i < DUN_STR_DEN; i++) { ty = y + randint(t1) - t2; tx = x + randint(t1) - t2; if (in_bounds(ty, tx)) { c_ptr = &cave[ty][tx]; if (c_ptr->fval == GRANITE_WALL) { c_ptr->fval = fval; if (randint(treas_chance) == 1) place_gold(ty, tx); } } } } while (mmove(dir, &y, &x)); } void repl_spot(y, x, typ) /* copied verbatim from spells.c - damn * thing won't find it. :( :( -DGK */ int y, x, typ; { register cave_type *c_ptr; c_ptr = &cave[y][x]; switch (typ) { case 1: case 2: case 3: c_ptr->fval = CORR_FLOOR; break; case 4: case 7: case 10: c_ptr->fval = GRANITE_WALL; break; case 5: case 8: case 11: c_ptr->fval = MAGMA_WALL; break; case 6: case 9: case 12: c_ptr->fval = QUARTZ_WALL; break; } c_ptr->pl = FALSE; c_ptr->fm = FALSE; c_ptr->lr = FALSE; /* this is no longer part of a room */ if (c_ptr->tptr != 0) (void)delete_object(y, x); if (c_ptr->cptr > 1) delete_monster((int)c_ptr->cptr); } static void place_destroyed() { register int y, x; register int i, j, k; int n; for (n = 1; n <= randint(5); n++) { x = randint(cur_width - 32) + 15; y = randint(cur_height - 32) + 15; for (i = (y - 15); i <= (y + 15); i++) for (j = (x - 15); j <= (x + 15); j++) if (in_bounds(i, j) && (cave[i][j].fval != BOUNDARY_WALL) && ((cave[i][j].tptr == 0) || /* DGK */ ((t_list[cave[i][j].tptr].tval != TV_UP_STAIR) && (t_list[cave[i][j].tptr].tval != TV_DOWN_STAIR) && (!(t_list[cave[i][j].tptr].flags2 & TR_ARTIFACT))))) { k = distance(i, j, y, x); if (i == char_row && j == char_col) repl_spot(i, j, 1); else if (k < 13) repl_spot(i, j, (int)randint(6)); else if (k < 16) repl_spot(i, j, (int)randint(9)); } } } /* Chris Tate (fixer@faxcsl.dcrt.nih.gov) - optimize this code for size! * This code performs the common test in all of the place_* functions, * and returns c_ptr if we can go ahead and place the object, or NULL * if we can't. */ static cave_type * test_place_obj(y, x) int y, x; { cave_type *t; int tv; if (!in_bounds(y,x)) return NULL; t = &cave[y][x]; tv = t_list[t->tptr].tval; if (t->tptr != 0) if (((tv <= TV_MAX_WEAR) && (tv >= TV_MIN_WEAR) && (t_list[t->tptr].flags2 & TR_ARTIFACT)) || (tv == TV_UP_STAIR) || (tv == TV_DOWN_STAIR) || (tv == TV_STORE_DOOR)) return NULL; else delete_object(y,x); /* waste it, it's not important */ return t; } static void place_open_door(y, x) int y, x; { register int cur_pos; register cave_type *c_ptr; if (!(c_ptr = test_place_obj(y,x))) return; cur_pos = popt(); c_ptr->tptr = cur_pos; invcopy(&t_list[cur_pos], OBJ_OPEN_DOOR); c_ptr->fval = CORR_FLOOR; } static void place_broken_door(y, x) int y, x; { register int cur_pos; register cave_type *c_ptr; if (!(c_ptr = test_place_obj(y,x))) return; cur_pos = popt(); c_ptr->tptr = cur_pos; invcopy(&t_list[cur_pos], OBJ_OPEN_DOOR); c_ptr->fval = CORR_FLOOR; t_list[cur_pos].p1 = 1; } static void place_closed_door(y, x) int y, x; { register int cur_pos; register cave_type *c_ptr; if (!(c_ptr = test_place_obj(y,x))) return; cur_pos = popt(); c_ptr->tptr = cur_pos; invcopy(&t_list[cur_pos], OBJ_CLOSED_DOOR); c_ptr->fval = BLOCKED_FLOOR; } static void place_locked_door(y, x) int y, x; { register int cur_pos; register cave_type *c_ptr; if (!(c_ptr = test_place_obj(y,x))) return; cur_pos = popt(); c_ptr->tptr = cur_pos; invcopy(&t_list[cur_pos], OBJ_CLOSED_DOOR); c_ptr->fval = BLOCKED_FLOOR; t_list[cur_pos].p1 = randint(10) + 10; } static void place_stuck_door(y, x) int y, x; { register int cur_pos; register cave_type *c_ptr; if (!(c_ptr = test_place_obj(y,x))) return; cur_pos = popt(); c_ptr->tptr = cur_pos; invcopy(&t_list[cur_pos], OBJ_CLOSED_DOOR); c_ptr->fval = BLOCKED_FLOOR; t_list[cur_pos].p1 = (-randint(10) - 10); } static void place_secret_door(y, x) int y, x; { register int cur_pos; register cave_type *c_ptr; if (!(c_ptr = test_place_obj(y,x))) return; cur_pos = popt(); c_ptr->tptr = cur_pos; invcopy(&t_list[cur_pos], OBJ_SECRET_DOOR); c_ptr->fval = BLOCKED_FLOOR; } static void place_door(y, x) int y, x; { register int tmp; tmp = randint(8); if (tmp < 4) { if (randint(4) == 1) place_broken_door(y, x); else place_open_door(y, x); } else if (tmp < 7) { tmp = randint(100); if (tmp > 25) place_closed_door(y, x); else if (tmp == 3) place_stuck_door(y, x); else place_locked_door(y, x); } else place_secret_door(y, x); } /* Place an up staircase at given y, x -RAK- */ static void place_up_stairs(y, x) int y, x; { register int cur_pos; register cave_type *c_ptr; if (!(c_ptr = test_place_obj(y,x))) return; cur_pos = popt(); c_ptr->tptr = cur_pos; invcopy(&t_list[cur_pos], OBJ_UP_STAIR); } /* Place a down staircase at given y, x -RAK- */ static void place_down_stairs(y, x) int y, x; { register int cur_pos; register cave_type *c_ptr; if (is_quest(dun_level)) { place_up_stairs(y, x); return; } if (!(c_ptr = test_place_obj(y,x))) return; cur_pos = popt(); c_ptr->tptr = cur_pos; invcopy(&t_list[cur_pos], OBJ_DOWN_STAIR); if (dun_level == 0) /* on town level -CWS */ c_ptr->pl = TRUE; } /* Places a staircase 1=up, 2=down -RAK- */ static void place_stairs(typ, num, walls) int typ, num, walls; { register cave_type *cave_ptr; int i, j, flag; register int y1, x1, y2, x2; for (i = 0; i < num; i++) { flag = FALSE; do { j = 0; do { /* Note: don't let y1/x1 be zero, and don't let y2/x2 be equal to * cur_height-1/cur_width-1, these values are always * BOUNDARY_ROCK. */ y1 = randint(cur_height - 14); x1 = randint(cur_width - 14); y2 = y1 + 12; x2 = x1 + 12; do { do { cave_ptr = &cave[y1][x1]; if (cave_ptr->fval <= MAX_OPEN_SPACE && (cave_ptr->tptr == 0) && (next_to_walls(y1, x1) >= walls)) { flag = TRUE; if (typ == 1) place_up_stairs(y1, x1); else place_down_stairs(y1, x1); } x1++; } while ((x1 != x2) && (!flag)); x1 = x2 - 12; y1++; } while ((y1 != y2) && (!flag)); j++; } while ((!flag) && (j <= 30)); walls--; } while (!flag); } } /* Place a trap with a given displacement of point -RAK- */ static void vault_trap(y, x, yd, xd, num) int y, x, yd, xd, num; { register int count, y1, x1; int i, flag; register cave_type *c_ptr; for (i = 0; i < num; i++) { flag = FALSE; count = 0; do { do { /* add another bounds check -CFT */ y1 = y - yd - 1 + randint(2 * yd + 1); x1 = x - xd - 1 + randint(2 * xd + 1); } while (!in_bounds(y1, x1)); c_ptr = &cave[y1][x1]; if ((c_ptr->fval != NULL_WALL) && (c_ptr->fval <= MAX_CAVE_FLOOR) && (c_ptr->tptr == 0)) { place_trap(y1, x1, randint(MAX_TRAP) - 1); flag = TRUE; } count++; } while ((!flag) && (count <= 5)); } } /* Place a monster with a given displacement of point -RAK- */ static void vault_monster(y, x, num) int y, x, num; { register int i; int y1, x1; for (i = 0; i < num; i++) { y1 = y; x1 = x; (void)summon_monster(&y1, &x1, TRUE); } } static void vault_jelly(y, x) int y, x; { int l, m, summon; summon = FALSE; l = m_level[MAX_MONS_LEVEL]; do { m = randint(l) - 1; if (((c_list[m].cchar == 'j') || (c_list[m].cchar == ',') || (c_list[m].cchar == 'i') || (c_list[m].cchar == 'm')) && !(c_list[m].cdefense & EVIL)) { summon = TRUE; place_monster(y, x, m, TRUE); } } while (!summon); } static void vault_orc(y, x, rank) int y, x, rank; { register int i; i = 0; switch (rank) { case 1: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Snaga")) break; i++; } break; case 2: case 3: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Black orc")) break; i++; } break; case 4: case 5: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Uruk-Hai")) break; i++; } break; case 6: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Orc captain")) break; i++; } break; } if (i != MAX_CREATURES) place_monster(y, x, i, FALSE); } static void vault_troll(y, x, rank) int y, x, rank; { register int i; i = 0; switch (rank) { case 1: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Forest troll")) break; i++; } break; case 2: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Stone troll")) break; i++; } break; case 3: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Ice troll")) break; i++; } break; case 4: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Cave troll")) break; i++; } break; case 5: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Water troll")) break; i++; } break; case 6: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Olog-Hai")) break; i++; } break; } if (i != MAX_CREATURES) place_monster(y, x, i, FALSE); } static void vault_undead(y, x) int y, x; { int l, m, summon; summon = FALSE; l = m_level[MAX_MONS_LEVEL]; do { m = randint(l) - 1; if ((c_list[m].cdefense & UNDEAD) && !(c_list[m].cdefense & UNIQUE)) { summon = TRUE; place_monster(y, x, m, TRUE); } } while (!summon); } static void vault_dragon(y, x, rank, type) int y, x, rank, type; { register int i = 0; switch (rank) { case 1: case 2: case 3: switch (type) { case 1: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Young blue dragon")) break; i++; } break; case 2: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Young white dragon")) break; i++; } break; case 3: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Young green dragon")) break; i++; } break; case 4: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Young black dragon")) break; i++; } break; case 5: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Young red dragon")) break; i++; } break; case 6: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Young Multi-Hued Dragon")) break; i++; } break; } break; case 4: case 5: switch (type) { case 1: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Mature blue Dragon")) break; i++; } break; case 2: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Mature white Dragon")) break; i++; } break; case 3: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Mature green Dragon")) break; i++; } break; case 4: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Mature black Dragon")) break; i++; } break; case 5: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Mature red Dragon")) break; i++; } break; case 6: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Mature Multi-Hued Dragon")) break; i++; } break; } break; case 6: switch (type) { case 1: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Ancient blue Dragon")) break; i++; } break; case 2: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Ancient white Dragon")) break; i++; } break; case 3: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Ancient green Dragon")) break; i++; } break; case 4: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Ancient black Dragon")) break; i++; } break; case 5: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Ancient red Dragon")) break; i++; } break; case 6: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Ancient Multi-Hued Dragon")) break; i++; } break; } break; } if (i != MAX_CREATURES) place_monster(y, x, i, FALSE); } static void vault_demon(y, x, rank) int y, x, rank; { register int i = 0; switch (rank) { case 1: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Vrock")) break; i++; } break; case 2: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Hezrou")) break; i++; } break; case 3: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Glabrezu")) break; i++; } break; case 4: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Nalfeshnee")) break; i++; } break; case 5: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Marilith")) break; i++; } break; case 6: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Lesser balrog")) break; i++; } break; } if (i != MAX_CREATURES) place_monster(y, x, i, FALSE); } static void vault_giant(y, x, rank) int y, x, rank; { register int i = 0; switch (rank) { case 1: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Hill giant")) break; i++; } break; case 2: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Frost giant")) break; i++; } break; case 3: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Fire giant")) break; i++; } break; case 4: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Stone giant")) break; i++; } break; case 5: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Cloud giant")) break; i++; } break; case 6: while (i < MAX_CREATURES) { if (!stricmp(c_list[i].name, "Storm giant")) break; i++; } break; } if (i != MAX_CREATURES) place_monster(y, x, i, FALSE); } /* Builds a room at a row, column coordinate -RAK- */ static void build_room(yval, xval) int yval, xval; { register int i, j, y_depth, x_right; int y_height, x_left; int8u floor; register cave_type *c_ptr, *d_ptr; if (dun_level <= randint(25)) floor = LIGHT_FLOOR; /* Floor with light */ else floor = DARK_FLOOR; /* Dark floor */ y_height = yval - randint(4); y_depth = yval + randint(3); x_left = xval - randint(11); x_right = xval + randint(11); /* for paranoia's sake: bounds-check! Memory errors caused by accessing * cave[][] out-of-bounds are nearly impossible to spot! -CFT */ if (y_height < 1) y_height = 1; if (y_depth >= (cur_height - 1)) y_depth = cur_height - 2; if (x_left < 1) x_left = 1; if (x_right >= (cur_width - 1)) x_right = cur_width - 2; /* the x dim of rooms tends to be much larger than the y dim, so don't bother * rewriting the y loop */ for (i = y_height; i <= y_depth; i++) { c_ptr = &cave[i][x_left]; for (j = x_left; j <= x_right; j++) { c_ptr->fval = floor; c_ptr->lr = TRUE; c_ptr++; } } for (i = (y_height - 1); i <= (y_depth + 1); i++) { c_ptr = &cave[i][x_left - 1]; c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; c_ptr = &cave[i][x_right + 1]; c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } c_ptr = &cave[y_height - 1][x_left]; d_ptr = &cave[y_depth + 1][x_left]; for (i = x_left; i <= x_right; i++) { c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; c_ptr++; d_ptr->fval = GRANITE_WALL; d_ptr->lr = TRUE; d_ptr++; } /* Every so often fill a normal room with pillars - Decado */ if (randint(20) == 2) { for (i = y_height; i <= y_depth; i += 2) { for (j = x_left; j <= x_right; j += 2) { c_ptr = &cave[i][j]; c_ptr->fval = TMP1_WALL; c_ptr->lr = TRUE; } } } } /* Builds a room at a row, column coordinate -RAK- */ /* Type 1 unusual rooms are several overlapping rectangular ones */ static void build_type1(yval, xval) int yval, xval; { int y_height, y_depth; int x_left, x_right, limit; register int i0, i, j; int8u floor; register cave_type *c_ptr, *d_ptr; if (dun_level <= randint(25)) floor = LIGHT_FLOOR; /* Floor with light */ else floor = DARK_FLOOR; /* Dark floor */ limit = 1 + randint(2); for (i0 = 0; i0 < limit; i0++) { y_height = yval - randint(4); y_depth = yval + randint(3); x_left = xval - randint(11); x_right = xval + randint(11); /* for paranoia's sake: bounds-check! Memory errors caused by accessing * cave[][] out-of-bounds are nearly impossible to spot! -CFT */ if (y_height < 1) y_height = 1; if (y_depth >= (cur_height - 1)) y_depth = cur_height - 2; if (x_left < 1) x_left = 1; if (x_right >= (cur_width - 1)) x_right = cur_width - 2; /* the x dim of rooms tends to be much larger than the y dim, so don't * bother rewriting the y loop */ for (i = y_height; i <= y_depth; i++) { c_ptr = &cave[i][x_left]; for (j = x_left; j <= x_right; j++) { c_ptr->fval = floor; c_ptr->lr = TRUE; c_ptr++; } } for (i = (y_height - 1); i <= (y_depth + 1); i++) { c_ptr = &cave[i][x_left - 1]; if (c_ptr->fval != floor) { c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } c_ptr = &cave[i][x_right + 1]; if (c_ptr->fval != floor) { c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } } c_ptr = &cave[y_height - 1][x_left]; d_ptr = &cave[y_depth + 1][x_left]; for (i = x_left; i <= x_right; i++) { if (c_ptr->fval != floor) { c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } c_ptr++; if (d_ptr->fval != floor) { d_ptr->fval = GRANITE_WALL; d_ptr->lr = TRUE; } d_ptr++; } } } /* Wish me LUCK! - Decado */ static void build_type5(yval, xval) int yval, xval; { register int x, y, x1, y1, vault; int width = 0, height = 0; char *template = NULL; /* use t to avoid changing template in loop. This should fix some memory * troubles, because now we aren't free()ing with a bad pointer. Thanks * much to gehring@pib1.physik.uni-bonn.edu for pointing this bug out... -CFT */ char *t; char buf[50]; int8u floor; int8u wall; register cave_type *c_ptr; if (dun_level <= randint(25)) floor = LIGHT_FLOOR; /* Floor with light */ else floor = DARK_FLOOR; /* Dark floor */ vault = 0; switch (randint(8)) { case 1: width = 20; height = 12; template = (char *)malloc((size_t) width * height + 1); rating += 5; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s", " %%%%%% ", " %%%..##..%%% ", " %%....####....%% ", " %......#**#......% ", "%...,.##+##+##.,...%", "%.,.,.#*#*&#*#.,.,.%", "%.,.,.#*#&*#*#.,.,.%", "%...,.##+##+##.,...%", " %......#**#......% ", " %%....####....%% ", " %%%..##..%%% ", " %%%%%% "); break; case 2: width = 20; height = 14; template = (char *)malloc((size_t) width * height + 1); rating += 5; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s", " %%%%%%%%%%%%%% ", " %%.##########.%% ", " %%..#..,,,,..#..%% ", "%%,..#.,####,.#..,%%", "%....#.,#**#,.#....%", "%.###+,##&&##,+###.%", "%.#..,,#*&**#,,..#.%", "%.#..,,#**&*#,,..#.%", "%.###+,##&&##,+###.%", "%....#.,#**#,.#....%", "%%,..#.,####,.#..,%%", " %%..#..,,,,..#..%% ", " %%.##########.%% ", " %%%%%%%%%%%%%% "); break; case 3: width = 20; height = 12; template = (char *)malloc((size_t) width * height + 1); rating += 5; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s", " %%%%%%%%%%%% ", " %%%%..........%%%% ", " %...###+##+###...% ", "%%...#,,#,,#,,#...%%", "%.###+##+##+##+###.%", "%.#,,#&&#**#&&#,,#.%", "%.#,,#&&#**#&&#,,#.%", "%.###+##+##+##+###.%", "%%...#,,#,,#,,#...%%", " %...###+##+###...% ", " %%%%..........%%%% ", " %%%%%%%%%%%% "); break; case 4: width = 20; height = 12; template = (char *)malloc((size_t) width * height + 1); rating += 5; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s", "%%%%%%%%%%%%%%%%%%%%", "%*.......&........*%", "%.################.%", "%.#,.,.,.,.,.,.,.#.%", "%.#.############,#.%", "%.#,+,&&+**#&*,#.#&%", "%&#.#,*&#**+&&,+,#.%", "%.#,############.#.%", "%.#.,.,.,.,.,.,.,#.%", "%.################.%", "%*........&.......*%", "%%%%%%%%%%%%%%%%%%%%"); break; case 5: width = 20; height = 12; template = (char *)malloc((size_t) width * height + 1); rating += 5; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s", "%%%%%%%%%%%%%%%%% ", "%,,,##,,,,##....%% ", "%,,,,##,,,,##....%% ", "%#,,,,##,,,,##....%%", "%##,,,,##,,,,##....%", "%.##,,,,,,,,,,#+...%", "%..#+,,,,,,,,,,##..%", "%...##,,,,##,,,,##.%", "%%...##,,,,##,,,,##%", " %%...##,,,,##,,,,#%", " %%...##,,,,##,,,,%", " %%%%%%%%%%%%%%%%%"); break; case 6: width = 20; height = 12; template = (char *)malloc((size_t) width * height + 1); rating += 5; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s", " %%%%%%%%%%%%%%%%%", " %%....##,,,,##,,,%", " %%....##,,,,##,,,,%", "%%....##,,,,##,,,,#%", "%....##,,,,##,,,,##%", "%...+#,,,,,,,,,,##.%", "%..##,,,,,,,,,,+#..%", "%.##,,,,##,,,,##...%", "%##,,,,##,,,,##...%%", "%#,,,,##,,,,##...%% ", "%,,,,##,,,,##...%% ", "%%%%%%%%%%%%%%%%% "); break; case 7: width = 20; height = 12; template = (char *)malloc((size_t) width * height + 1); rating += 5; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s", "%%%%%%%%%%%%%%%%%%%%", "%,################,%", "%^#.*...&..,....,#^%", "%^#...,......&...#^%", "%^#######++#######^%", "%^+.,..&+,*+*....+^%", "%^+..*.,+.&+.,.&.+^%", "%^#######++#######^%", "%^#....,.,.....,.#^%", "%^#..&......*....#^%", "%,################,%", "%%%%%%%%%%%%%%%%%%%%"); break; case 8: vault = TRUE; switch (randint(4)) { case 4: width = 40; height = 18; template = (char *)malloc((size_t) width * height + 1); rating += 25; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%", "%######################################%", "%#*8..&##***++^^^^^^^^^^^^++***##&..*8#%", "%#8..&##,,,,,##^^^^^^^^^^##,,,,,X#&..*#%", "%#..&X#.....,.##^^^^^^^^##..&....##&..#%", "%#.&##..,.&....##^^^^^^##..,...&..##&.#%", "%#&##..*...&.^..##^^^^##..*....,..,##&#%", "%####+#############++#############+####%", "%+....,.,.#&&&&***+88+***&&&&#,.,.,...+%", "%+...,.,.,#&&&&***+88+***&&&&#.,.,....+%", "%####+#############++#############+####%", "%#&##..*....&...##^^^^##...*...&,..X#&#%", "%#.&##..&.^....##^^^^^^##....&....##&.#%", "%#..&##....&..##^^^^^^^^##..,..*.##&..#%", "%#*..&X#,,,,,##^^^^^^^^^^##,,,,,##&..8#%", "%#8*..&##***++^^^^^^^^^^^^++***##&..*8#%", "%######################################%", "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); break; case 3: width = 39; height = 17; template = (char *)malloc((size_t) width * height + 1); rating += 35; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%", "%#####################################%", "%+&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XO#%", "%###################################X#%", "%#OX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&#%", "%#X###################################%", "%#&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XO#%", "%###################################X#%", "%#OX&XOX&XOX&XOOOOOOOOOOOXOX&XOX&XOX&#%", "%#X###################################%", "%#&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XO#%", "%###################################X#%", "%#OX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&#%", "%#X###################################%", "%#&XOX&XOX&XOX&XOX&XOX&XOX&XOX&XOX&X&+%", "%#####################################%", "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); break; case 2: width = 40; height = 18; template = (char *)malloc((size_t) width * height + 1); rating += 30; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%", "%######################################%", "%#,X,X,X,X,X,X,X,X*@@*X,X,X,X,X,X,X,X,#%", "%#+################XX################+#%", "%#.,..,.#&.&.,*##******##*,.&.&#.,...,X%", "%#..,.^^#....,##***@@***##,....#^^..,.X%", "%######+#^&.&##***@XX@***##&.&^#+######%", "%#,.&.^^#+####***@X##X@***####+#^^.,..#%", "%#..,&,.#^^^@#**@X#OO#X@**X@^^^#.,..&,#%", "%#.,....#^^^@X**@X#OO#X@**#@^^^#.&.,..#%", "%#...,^^#+####***@X##X@***####+#^^..,.#%", "%######+#^&.&##***@XX@***##&.&^#+######%", "%X.,..^^#.....##***@@***##,....#^^.,..#%", "%X...,..#&.&.,*##******##*,.&.&#..,..,#%", "%#+################XX################+#%", "%#,X,X,X,X,X,X,X,X*@@*X,X,X,X,X,X,X,X,#%", "%######################################%", "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); break; case 1: width = 40; height = 15; template = (char *)malloc((size_t)width * height + 1); rating += 25; sprintf(template, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%", "%&+.^..^..^..^..^..^..^..^..^..^..^..+&%", "%+####################################+%", "%.#.&.^,#&^&^#****+^*^@^#.*.&..#..*.,#.%", "%^#.,.&^+^&^@#^^^^#@^*^*#....*^+.^...#^%", "%.#*..,.###+####+####+###.&.^..#..&,.#.%", "%^#..^.*#*..^&&@@*#,,,,,####+###,....#^%", "%.##+##############,*O*,#,,,,,,###+###.%", "%^#*&#.&,*.#,*&^*^#,,,,,#,,,,,,#....,#^%", "%.#&,+....*+,*&^*^##########+###.,...+.%", "%^#.,#.*.&.#,*&^*^+.,.&.^*.&^&^#.....#^%", "%.#^*#.,..,#,*&^*^#*.^*.,..&&&^#,..,.#.%", "%+####################################+%", "%&+..^..^..^..^..^..^..^..^..^..^..^.+&%", "%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"); break; } break; } /* check these rooms will fit on the map! */ wall = TMP1_WALL; if (vault) { xval += 4; /* neat kludge deccy... */ yval += 4; wall = BOUNDARY_WALL; if (floor == LIGHT_FLOOR) floor = NT_LIGHT_FLOOR; else floor = NT_DARK_FLOOR; } /* DO NOT CHANGE yval or xval after this check... */ if (!(in_bounds(yval - (height / 2), xval - (width / 2)) && in_bounds(yval + (height / 2), xval + (width / 2)))) { free(template); build_type2(yval, xval); return; } if ((dun_level <= 40) || (randint((dun_level - 30)*(dun_level - 30) + 1) < 400)) good_item_flag = TRUE; /* this is more like it.... -CWS */ t = template; /* this avoids memory troubles... see above -CFT */ for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { x1 = xval - (width / 2) + x; y1 = yval - (height / 2) + y; c_ptr = &cave[y1][x1]; switch (*t++) { case '#': /* lit up wall */ c_ptr->fval = wall; c_ptr->lr = TRUE; break; case 'X': c_ptr->fval = TMP1_WALL; c_ptr->lr = TRUE; break; case '%': /* lit up wall */ c_ptr->fval = GRANITE_WALL; /* Not temp, since this may have doors in */ c_ptr->lr = TRUE; break; case '.': /* lit up/ not lit up floor */ c_ptr->fval = floor; c_ptr->lr = TRUE; break; case '*': /* treasure/trap */ c_ptr->fval = floor; if (randint(20) > 7) { object_level = dun_level; place_object(y1, x1); } else if (randint(10) > 2) place_trap(y1, x1, randint(MAX_TRAP) - 1); else if (randint(2) == 1 && !vault) place_down_stairs(y1, x1); else if (!vault) place_up_stairs(y1, x1); c_ptr->lr = TRUE; break; case '+': /* secret doors */ place_secret_door(y1, x1); c_ptr->lr = TRUE; break; case '^': c_ptr->fval = floor; place_trap(y1, x1, randint(MAX_TRAP) - 1); c_ptr->lr = TRUE; break; case ' ': break; case '&': case '@': case '8': case 'O': case ',': /* do nothing for now... cannot place monster until whole * area is built, OW group monsters screw things up by being * placed where walls will be placed on top of them -CFT */ break; default: #if 0 sprintf(buf, "Cockup='%c'", *t); msg_print(buf); #endif break; } } } /* now we go back and place the monsters, hopefully this makes * everything happy... -CFT */ t = template; /* this avoids memory troubles... see above -CFT */ for (y=0; yfval = floor; place_monster(y1, x1, get_mons_num(dun_level + MON_SUMMON_ADJ + 2 + vault), TRUE); c_ptr->lr = TRUE; break; case '@': /* Meaner monster */ c_ptr->fval = floor; place_monster(y1, x1, get_nmons_num(dun_level + MON_SUMMON_ADJ + 7), TRUE); c_ptr->lr = TRUE; break; case '8': /* Meaner monster */ c_ptr->fval = floor; place_monster(y1, x1, get_nmons_num(dun_level + MON_SUMMON_ADJ + 7), TRUE); place_special(y1, x1, 1); c_ptr->lr = TRUE; break; case 'O': /* Nasty monster and treasure */ c_ptr->fval = floor; place_monster(y1, x1, get_nmons_num(dun_level + MON_SUMMON_ADJ + 40), TRUE); object_level = dun_level + MON_SUMMON_ADJ + 20; place_special(y1, x1, SPECIAL); object_level = dun_level + 7; c_ptr->lr = TRUE; break; case ',': /* Monster/object */ c_ptr->fval = floor; if (randint(2) == 1) place_monster(y1, x1, get_mons_num(dun_level + MON_SUMMON_ADJ + vault), TRUE); if (randint(2) == 1) { object_level = dun_level + 7; place_object(y1, x1); } c_ptr->lr = TRUE; break; case ' ': break; default: #if 0 sprintf(buf, "Cockup='%c'", *t); msg_print(buf); #endif break; } } } free(template); } /* Builds an unusual room at a row, column coordinate -RAK- * * Type 2 unusual rooms all have an inner room: * 1 - Just an inner room with one door * 2 - An inner room within an inner room * 3 - An inner room with pillar(s) * 4 - Inner room has a maze * 5 - A set of four inner rooms */ static void build_type2(yval, xval) int yval, xval; { register int i, j, y_height, x_left; int y_depth, x_right, tmp; int8u floor; register cave_type *c_ptr, *d_ptr; if (dun_level <= randint(25)) floor = LIGHT_FLOOR; /* Floor with light */ else floor = DARK_FLOOR; /* Dark floor */ y_height = yval - 4; y_depth = yval + 4; x_left = xval - 11; x_right = xval + 11; /* paranoia bounds-check... if the room can't fit in the cave, punt out and * build a simpler room type (type1 is already bounds-checked) This should * help solve MORE memory troubles! -CFT */ if (!in_bounds(y_height, x_left) || !in_bounds(y_depth, x_right)) { build_type1(yval, xval); return; } /* the x dim of rooms tends to be much larger than the y dim, so don't bother * rewriting the y loop */ for (i = y_height; i <= y_depth; i++) { c_ptr = &cave[i][x_left]; for (j = x_left; j <= x_right; j++) { c_ptr->fval = floor; c_ptr->lr = TRUE; c_ptr++; } } for (i = (y_height - 1); i <= (y_depth + 1); i++) { c_ptr = &cave[i][x_left - 1]; c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; c_ptr = &cave[i][x_right + 1]; c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } c_ptr = &cave[y_height - 1][x_left]; d_ptr = &cave[y_depth + 1][x_left]; for (i = x_left; i <= x_right; i++) { c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; c_ptr++; d_ptr->fval = GRANITE_WALL; d_ptr->lr = TRUE; d_ptr++; } /* The inner room */ y_height = y_height + 2; y_depth = y_depth - 2; x_left = x_left + 2; x_right = x_right - 2; for (i = (y_height - 1); i <= (y_depth + 1); i++) { cave[i][x_left - 1].fval = TMP1_WALL; cave[i][x_right + 1].fval = TMP1_WALL; } c_ptr = &cave[y_height - 1][x_left]; d_ptr = &cave[y_depth + 1][x_left]; for (i = x_left; i <= x_right; i++) { c_ptr->fval = TMP1_WALL; c_ptr++; d_ptr->fval = TMP1_WALL; d_ptr++; } /* Inner room variations */ switch (randint(5)) { case 1: /* Just an inner room. */ tmp = randint(4); if (tmp < 3) { /* Place a door */ if (tmp == 1) place_secret_door(y_height - 1, xval); else place_secret_door(y_depth + 1, xval); } else { if (tmp == 3) place_secret_door(yval, x_left - 1); else place_secret_door(yval, x_right + 1); } vault_monster(yval, xval, 1); break; case 2: /* Treasure Vault */ tmp = randint(4); if (tmp < 3) { /* Place a door */ if (tmp == 1) place_secret_door(y_height - 1, xval); else place_secret_door(y_depth + 1, xval); } else { if (tmp == 3) place_secret_door(yval, x_left - 1); else place_secret_door(yval, x_right + 1); } for (i = yval - 1; i <= yval + 1; i++) { cave[i][xval - 1].fval = TMP1_WALL; cave[i][xval + 1].fval = TMP1_WALL; } cave[yval - 1][xval].fval = TMP1_WALL; cave[yval + 1][xval].fval = TMP1_WALL; tmp = randint(4); /* Place a door */ if (tmp < 3) place_locked_door(yval - 3 + (tmp << 1), xval); /* 1 -> yval-1; 2 -> yval+1 */ else place_locked_door(yval, xval - 7 + (tmp << 1)); /* Place an object in the treasure vault */ tmp = randint(10); if (tmp > 2) { object_level = dun_level; place_object(yval, xval); } else if (tmp == 2) place_down_stairs(yval, xval); else place_up_stairs(yval, xval); /* Guard the treasure well */ vault_monster(yval, xval, 2 + randint(3)); /* If the monsters don't get 'em. */ vault_trap(yval, xval, 4, 10, 2 + randint(3)); break; case 3: /* Inner pillar(s). */ tmp = randint(4); if (tmp < 3) { /* Place a door */ if (tmp == 1) place_secret_door(y_height - 1, xval); else place_secret_door(y_depth + 1, xval); } else { if (tmp == 3) place_secret_door(yval, x_left - 1); else place_secret_door(yval, x_right + 1); } for (i = yval - 1; i <= yval + 1; i++) { c_ptr = &cave[i][xval - 1]; for (j = xval - 1; j <= xval + 1; j++) { c_ptr->fval = TMP1_WALL; c_ptr++; } } if (randint(2) == 1) { tmp = randint(2); for (i = yval - 1; i <= yval + 1; i++) { c_ptr = &cave[i][xval - 5 - tmp]; for (j = xval - 5 - tmp; j <= xval - 3 - tmp; j++) { c_ptr->fval = TMP1_WALL; c_ptr++; } } for (i = yval - 1; i <= yval + 1; i++) { c_ptr = &cave[i][xval + 3 + tmp]; for (j = xval + 3 + tmp; j <= xval + 5 + tmp; j++) { c_ptr->fval = TMP1_WALL; c_ptr++; } } } if (randint(3) == 1) { /* Inner rooms */ c_ptr = &cave[yval - 1][xval - 5]; d_ptr = &cave[yval + 1][xval - 5]; for (i = xval - 5; i <= xval + 5; i++) { c_ptr->fval = TMP1_WALL; c_ptr++; d_ptr->fval = TMP1_WALL; d_ptr++; } cave[yval][xval - 5].fval = TMP1_WALL; cave[yval][xval + 5].fval = TMP1_WALL; place_secret_door(yval - 3 + (randint(2) << 1), xval - 3); place_secret_door(yval - 3 + (randint(2) << 1), xval + 3); object_level = dun_level; if (randint(3) == 1) place_object(yval, xval - 2); if (randint(3) == 1) place_object(yval, xval + 2); vault_monster(yval, xval - 2, randint(2)); vault_monster(yval, xval + 2, randint(2)); } break; case 4: /* Maze inside. */ tmp = randint(4); if (tmp < 3) { /* Place a door */ if (tmp == 1) place_secret_door(y_height - 1, xval); else place_secret_door(y_depth + 1, xval); } else { if (tmp == 3) place_secret_door(yval, x_left - 1); else place_secret_door(yval, x_right + 1); } for (i = y_height; i <= y_depth; i++) for (j = x_left; j <= x_right; j++) if (0x1 & (j + i)) cave[i][j].fval = TMP1_WALL; /* Monsters just love mazes. */ vault_monster(yval, xval - 5, randint(3)); vault_monster(yval, xval + 5, randint(3)); /* Traps make them entertaining. */ vault_trap(yval, xval - 3, 2, 8, randint(3)); vault_trap(yval, xval + 3, 2, 8, randint(3)); /* Mazes should have some treasure too.. */ for (i = 0; i < 3; i++) random_object(yval, xval, 1); break; case 5: /* Four small rooms. */ for (i = y_height; i <= y_depth; i++) cave[i][xval].fval = TMP1_WALL; c_ptr = &cave[yval][x_left]; for (i = x_left; i <= x_right; i++) { c_ptr->fval = TMP1_WALL; c_ptr++; } if (randint(2) == 1) { i = randint(10); place_secret_door(y_height - 1, xval - i); place_secret_door(y_height - 1, xval + i); place_secret_door(y_depth + 1, xval - i); place_secret_door(y_depth + 1, xval + i); } else { i = randint(3); place_secret_door(yval + i, x_left - 1); place_secret_door(yval - i, x_left - 1); place_secret_door(yval + i, x_right + 1); place_secret_door(yval - i, x_right + 1); } /* Treasure in each one. */ random_object(yval, xval, 2 + randint(2)); /* Gotta have some monsters. */ vault_monster(yval + 2, xval - 4, randint(2)); vault_monster(yval + 2, xval + 4, randint(2)); vault_monster(yval - 2, xval - 4, randint(2)); vault_monster(yval - 2, xval + 4, randint(2)); break; } } /* Builds a room at a row, column coordinate -RAK- */ /* Type 3 unusual rooms are cross shaped */ static void build_type3(yval, xval) int yval, xval; { int y_height, y_depth; int x_left, x_right; register int tmp, i, j; int8u floor; register cave_type *c_ptr; /* quick, basic bounds-check... If too close, then this is better suited to a * simpler room type. -CFT */ if (!in_bounds(yval - 3, xval - 3) || !in_bounds(yval + 3, xval + 3)) { build_type1(yval, xval); return; } if (dun_level <= randint(25)) floor = LIGHT_FLOOR; /* Floor with light */ else floor = DARK_FLOOR; /* Dark floor */ tmp = 2 + randint(2); y_height = yval - tmp; y_depth = yval + tmp; x_left = xval - 1; x_right = xval + 1; /* for paranoia's sake: bounds-check! Memory errors caused by accessing * cave[][] out-of-bounds are nearly impossible to spot! -CFT */ if (y_height < 1) y_height = 1; if (y_depth >= (cur_height - 1)) y_depth = cur_height - 2; for (i = y_height; i <= y_depth; i++) for (j = x_left; j <= x_right; j++) { c_ptr = &cave[i][j]; c_ptr->fval = floor; c_ptr->lr = TRUE; } for (i = (y_height - 1); i <= (y_depth + 1); i++) { c_ptr = &cave[i][x_left - 1]; c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; c_ptr = &cave[i][x_right + 1]; c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } for (i = x_left; i <= x_right; i++) { c_ptr = &cave[y_height - 1][i]; c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; c_ptr = &cave[y_depth + 1][i]; c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } tmp = 2 + randint(9); y_height = yval - 1; y_depth = yval + 1; x_left = xval - tmp; x_right = xval + tmp; /* for paranoia's sake: bounds-check! Memory errors caused by accessing * cave[][] out-of-bounds are nearly impossible to spot! -CFT */ if (x_left < 1) x_left = 1; if (x_right >= (cur_width - 1)) x_right = cur_width - 2; for (i = y_height; i <= y_depth; i++) for (j = x_left; j <= x_right; j++) { c_ptr = &cave[i][j]; c_ptr->fval = floor; c_ptr->lr = TRUE; } for (i = (y_height - 1); i <= (y_depth + 1); i++) { c_ptr = &cave[i][x_left - 1]; if (c_ptr->fval != floor) { c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } c_ptr = &cave[i][x_right + 1]; if (c_ptr->fval != floor) { c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } } for (i = x_left; i <= x_right; i++) { c_ptr = &cave[y_height - 1][i]; if (c_ptr->fval != floor) { c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } c_ptr = &cave[y_depth + 1][i]; if (c_ptr->fval != floor) { c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } } /* Special features. */ switch (randint(4)) { case 1: /* Large middle pillar */ for (i = yval - 1; i <= yval + 1; i++) { c_ptr = &cave[i][xval - 1]; for (j = xval - 1; j <= xval + 1; j++) { c_ptr->fval = TMP1_WALL; c_ptr++; } } break; case 2: /* Inner treasure vault */ for (i = yval - 1; i <= yval + 1; i++) { cave[i][xval - 1].fval = TMP1_WALL; cave[i][xval + 1].fval = TMP1_WALL; } cave[yval - 1][xval].fval = TMP1_WALL; cave[yval + 1][xval].fval = TMP1_WALL; tmp = randint(4); /* Place a door */ if (tmp < 3) place_secret_door(yval - 3 + (tmp << 1), xval); else place_secret_door(yval, xval - 7 + (tmp << 1)); /* Place a treasure in the vault */ object_level = dun_level; place_object(yval, xval); /* Let's guard the treasure well. */ vault_monster(yval, xval, 2 + randint(2)); /* Traps naturally */ vault_trap(yval, xval, 4, 4, 1 + randint(3)); break; case 3: if (randint(3) == 1) { cave[yval - 1][xval - 2].fval = TMP1_WALL; cave[yval + 1][xval - 2].fval = TMP1_WALL; cave[yval - 1][xval + 2].fval = TMP1_WALL; cave[yval + 1][xval + 2].fval = TMP1_WALL; cave[yval - 2][xval - 1].fval = TMP1_WALL; cave[yval - 2][xval + 1].fval = TMP1_WALL; cave[yval + 2][xval - 1].fval = TMP1_WALL; cave[yval + 2][xval + 1].fval = TMP1_WALL; if (randint(3) == 1) { place_secret_door(yval, xval - 2); place_secret_door(yval, xval + 2); place_secret_door(yval - 2, xval); place_secret_door(yval + 2, xval); } } else if (randint(3) == 1) { cave[yval][xval].fval = TMP1_WALL; cave[yval - 1][xval].fval = TMP1_WALL; cave[yval + 1][xval].fval = TMP1_WALL; cave[yval][xval - 1].fval = TMP1_WALL; cave[yval][xval + 1].fval = TMP1_WALL; } else if (randint(3) == 1) cave[yval][xval].fval = TMP1_WALL; break; case 4: break; } } static void vault_nasty(j, i, type, rank, colour) int j, i, type, rank, colour; { switch (type) { case 1: vault_jelly(j, i); break; case 2: vault_orc(j, i, rank); break; case 3: vault_troll(j, i, rank); break; case 4: vault_undead(j, i); break; case 5: vault_dragon(j, i, rank, colour); break; case 6: vault_demon(j, i, rank); break; case 7: vault_giant(j, i, rank); break; } } static void special_pit(yval, xval, type) int yval, xval, type; { register int i, j, y_height, x_left; int y_depth, x_right, colour; int8u floor; register cave_type *c_ptr, *d_ptr; floor = DARK_FLOOR; y_height = yval - 4; y_depth = yval + 4; x_left = xval - 11; x_right = xval + 11; /* for paranoia's sake: bounds-check! Memory errors caused by * accessing cave[][] out-of-bounds are nearly impossible to * spot! -CFT */ if ((y_height < 1) || (y_depth >= (cur_height-1)) || (x_left < 1) || (x_right >= (cur_width-1))) { build_type1(yval,xval); /* type1 is heavily bounds-checked, and considered * safe to use as a fall-back room type -CFT */ return; } else if ((randint(dun_level*dun_level + 1) < 300) && (dun_level <= 40)) good_item_flag = TRUE; /* the x dim of rooms tends to be much larger than the y dim, so don't bother * rewriting the y loop */ for (i = y_height; i <= y_depth; i++) { c_ptr = &cave[i][x_left]; for (j = x_left; j <= x_right; j++) { c_ptr->fval = floor; c_ptr->lr = TRUE; c_ptr++; } } for (i = (y_height - 1); i <= (y_depth + 1); i++) { c_ptr = &cave[i][x_left - 1]; c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; c_ptr = &cave[i][x_right + 1]; c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; } c_ptr = &cave[y_height - 1][x_left]; d_ptr = &cave[y_depth + 1][x_left]; for (i = x_left; i <= x_right; i++) { c_ptr->fval = GRANITE_WALL; c_ptr->lr = TRUE; c_ptr++; d_ptr->fval = GRANITE_WALL; d_ptr->lr = TRUE; d_ptr++; } /* The inner room */ y_height = y_height + 2; y_depth = y_depth - 2; x_left = x_left + 2; x_right = x_right - 2; for (i = (y_height - 1); i <= (y_depth + 1); i++) { cave[i][x_left - 1].fval = TMP1_WALL; cave[i][x_right + 1].fval = TMP1_WALL; } c_ptr = &cave[y_height - 1][x_left]; d_ptr = &cave[y_depth + 1][x_left]; for (i = x_left; i <= x_right; i++) { c_ptr->fval = TMP1_WALL; c_ptr++; d_ptr->fval = TMP1_WALL; d_ptr++; } switch (randint(4)) { case 1: place_secret_door(y_height - 1, xval); break; case 2: place_secret_door(y_depth + 1, xval); break; case 3: place_secret_door(yval, x_left - 1); break; case 4: place_secret_door(yval, x_right + 1); break; } colour = randint(6); if (wizard || peek) { switch (type) { case 1: msg_print("A Slime Pit"); break; case 2: msg_print("An Orc Pit"); break; case 3: msg_print("A Troll Pit"); break; case 4: msg_print("A Graveyard"); break; case 5: switch (colour) { case 1: msg_print("A Blue Dragon Pit"); break; case 2: msg_print("A White Dragon Pit"); break; case 3: msg_print("A Green Dragon Pit"); break; case 4: msg_print("A Black Dragon Pit"); break; case 5: msg_print("A Red Dragon Pit"); break; case 6: msg_print("A Multi-Hued Dragon Pit"); break; } break; case 6: msg_print("A Demon Pit"); break; case 7: msg_print("A Giant Pit"); break; } } j = y_height; for (i = x_left; i <= x_right; i++) vault_nasty(j, i, type, 1, colour); j = y_depth; for (i = x_left; i <= x_right; i++) vault_nasty(j, i, type, 1, colour); i = x_left; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 1, colour); i = x_right; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 1, colour); i = x_left + 1; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 2, colour); i = x_left + 2; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 2, colour); i = x_right - 1; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 2, colour); i = x_right - 2; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 2, colour); i = x_left + 3; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 3, colour); i = x_left + 4; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 3, colour); i = x_right - 3; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 3, colour); i = x_right - 4; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 3, colour); i = x_left + 5; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 4, colour); i = x_left + 6; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 4, colour); i = x_right - 5; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 4, colour); i = x_right - 6; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 4, colour); i = x_left + 7; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 5, colour); i = x_left + 8; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 5, colour); i = x_right - 7; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 5, colour); i = x_right - 8; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 5, colour); i = x_right - 9; for (j = (y_height + 1); j <= (y_depth - 1); j++) vault_nasty(j, i, type, 6, colour); } /* Constructs a tunnel between two points */ static void build_tunnel(row1, col1, row2, col2) int row1, col1, row2, col2; { register int tmp_row, tmp_col, i, j; register cave_type *c_ptr; cave_type *d_ptr; coords tunstk[1000], wallstk[1000]; coords *tun_ptr; int row_dir, col_dir, tunindex, wallindex; int stop_flag, door_flag, main_loop_count; int start_row, start_col; /* Main procedure for Tunnel */ /* Note: 9 is a temporary value */ stop_flag = FALSE; door_flag = FALSE; tunindex = 0; wallindex = 0; main_loop_count = 0; start_row = row1; start_col = col1; correct_dir(&row_dir, &col_dir, row1, col1, row2, col2); do { /* prevent infinite loops, just in case */ main_loop_count++; if (main_loop_count > 2000) stop_flag = TRUE; if (randint(100) > DUN_TUN_CHG) { if (randint(DUN_TUN_RND) == 1) rand_dir(&row_dir, &col_dir); else correct_dir(&row_dir, &col_dir, row1, col1, row2, col2); } tmp_row = row1 + row_dir; tmp_col = col1 + col_dir; while (!in_bounds(tmp_row, tmp_col)) { if (randint(DUN_TUN_RND) == 1) rand_dir(&row_dir, &col_dir); else correct_dir(&row_dir, &col_dir, row1, col1, row2, col2); tmp_row = row1 + row_dir; tmp_col = col1 + col_dir; } c_ptr = &cave[tmp_row][tmp_col]; if (c_ptr->fval == NULL_WALL) { row1 = tmp_row; col1 = tmp_col; if (tunindex < 1000) { tunstk[tunindex].y = row1; tunstk[tunindex].x = col1; tunindex++; } door_flag = FALSE; } else if (c_ptr->fval == TMP2_WALL) /* do nothing */ ; else if (c_ptr->fval == GRANITE_WALL) { d_ptr = &cave[tmp_row + row_dir][tmp_col + col_dir]; if ((d_ptr->fval == GRANITE_WALL) || (d_ptr->fval == TMP2_WALL)) c_ptr->fval = TMP2_WALL; /* if can not pass completely through wall don't try... And mark as * impassible for future -KOC */ else { row1 = tmp_row; col1 = tmp_col; if (wallindex < 1000) { wallstk[wallindex].y = row1; wallstk[wallindex].x = col1; wallindex++; } for (i = row1 - 1; i <= row1 + 1; i++) for (j = col1 - 1; j <= col1 + 1; j++) if (in_bounds(i, j)) { d_ptr = &cave[i][j]; /* * values 11 and 12 are impossible here, * place_streamer is never run before build_tunnel */ if (d_ptr->fval == GRANITE_WALL) d_ptr->fval = TMP2_WALL; } } } else if (c_ptr->fval == CORR_FLOOR || c_ptr->fval == BLOCKED_FLOOR) { row1 = tmp_row; col1 = tmp_col; if (!door_flag) { if (doorindex < 100) { doorstk[doorindex].y = row1; doorstk[doorindex].x = col1; doorindex++; } door_flag = TRUE; } /* make sure that tunnel has gone a reasonable distance before * stopping it, this helps prevent isolated rooms */ if (randint(100) > DUN_TUN_CON) { tmp_row = row1 - start_row; if (tmp_row < 0) tmp_row = (-tmp_row); tmp_col = col1 - start_col; if (tmp_col < 0) tmp_col = (-tmp_col); if (tmp_row > 10 || tmp_col > 10) stop_flag = TRUE; } } else { /* c_ptr->fval != NULL, TMP2, GRANITE, * CORR */ row1 = tmp_row; col1 = tmp_col; } } while (((row1 != row2) || (col1 != col2)) && (!stop_flag)); tun_ptr = &tunstk[0]; for (i = 0; i < tunindex; i++) { d_ptr = &cave[tun_ptr->y][tun_ptr->x]; d_ptr->fval = CORR_FLOOR; tun_ptr++; } for (i = 0; i < wallindex; i++) { c_ptr = &cave[wallstk[i].y][wallstk[i].x]; if (c_ptr->fval == TMP2_WALL) { if (randint(100) < DUN_TUN_PEN) place_door(wallstk[i].y, wallstk[i].x); else { /* these have to be doorways to rooms */ c_ptr->fval = CORR_FLOOR; } } } } static int next_to(y, x) register int y, x; { register int next; if (!in_bounds(y, x)) return 0; /* abort! -CFT */ if (next_to_corr(y, x) > 2) if ((cave[y - 1][x].fval >= MIN_CAVE_WALL) && (cave[y + 1][x].fval >= MIN_CAVE_WALL)) next = TRUE; else if ((cave[y][x - 1].fval >= MIN_CAVE_WALL) && (cave[y][x + 1].fval >= MIN_CAVE_WALL)) next = TRUE; else next = FALSE; else next = FALSE; return (next); } /* Places door at y, x position if at least 2 walls found */ static void try_door(y, x) register int y, x; { if (!in_bounds(y, x)) return; /* abort! -CFT */ if ((cave[y][x].fval == CORR_FLOOR) && (randint(100) > DUN_TUN_JCT) && next_to(y, x)) place_door(y, x); } /* Returns random co-ordinates -RAK- */ static void new_spot(y, x) int16 *y, *x; { register int i, j; register cave_type *c_ptr; do { i = randint(cur_height - 2); j = randint(cur_width - 2); c_ptr = &cave[i][j]; } while (c_ptr->fval >= MIN_CLOSED_SPACE || (c_ptr->cptr != 0) || (c_ptr->tptr != 0) || (c_ptr->fval == NT_LIGHT_FLOOR) || (c_ptr->fval == NT_DARK_FLOOR)); *y = i; *x = j; } static void build_pit(yval, xval) int yval, xval; { int tmp; tmp = randint(dun_level > 80 ? 80 : dun_level); rating += 10; if (tmp < 10) special_pit(yval, xval, 1); else if (tmp < 20) special_pit(yval, xval, 2); else if (tmp < 43) ((randint(3) == 1) ? special_pit(yval, xval, 7) : special_pit(yval, xval, 3)); else if (tmp < 57) special_pit(yval, xval, 4); else if (tmp < 73) special_pit(yval, xval, 5); else special_pit(yval, xval, 6); } /* Cave logic flow for generation of new dungeon */ static void cave_gen() { struct spot_type { int endx; int endy; }; int room_map[20][20]; register int i, j, k; int y1, x1, y2, x2, pick1, pick2, tmp; int row_rooms, col_rooms, alloc_level; int16 yloc[400], xloc[400]; int pit_ok, spec_level; rating = 0; spec_level = 0; pit_ok = FALSE; if ((randint(DUN_DEST) == 1) && (dun_level > 10) && (!is_quest(dun_level))) { if (wizard) msg_print("Destroyed Level"); spec_level = SPEC_DEST; } else pit_ok = TRUE; row_rooms = 2 * (cur_height / SCREEN_HEIGHT); col_rooms = 2 * (cur_width / SCREEN_WIDTH); for (i = 0; i < row_rooms; i++) for (j = 0; j < col_rooms; j++) room_map[i][j] = FALSE; k = randnor(DUN_ROO_MEA, 2); for (i = 0; i < k; i++) room_map[randint(row_rooms) - 1][randint(col_rooms) - 1] = TRUE; k = 0; for (i = 0; i < row_rooms; i++) for (j = 0; j < col_rooms; j++) if (room_map[i][j] == TRUE) { yloc[k] = i * (SCREEN_HEIGHT >> 1) + QUART_HEIGHT; xloc[k] = j * (SCREEN_WIDTH >> 1) + QUART_WIDTH; if (dun_level > randint(DUN_UNUSUAL)) { tmp = randint(5); if ((tmp == 1) || (spec_level)) build_type1(yloc[k], xloc[k]); else if (tmp == 2) build_type2(yloc[k], xloc[k]); else if (tmp == 3) build_type3(yloc[k], xloc[k]); else if ((tmp == 4) && dun_level > randint(DUN_UNUSUAL)) { build_type5(yloc[k], xloc[k]); if (j + 1 < col_rooms) room_map[i][j + 1] = FALSE; if (j + 1 < col_rooms && i + 1 < row_rooms) room_map[i + 1][j + 1] = FALSE; if (j > 0 && i + 1 < row_rooms) room_map[i + 1][j - 1] = FALSE; if (i + 1 < row_rooms) room_map[i + 1][j] = FALSE; } else if (dun_level > randint(DUN_UNUSUAL) && pit_ok) { build_pit(yloc[k], xloc[k]); pit_ok = FALSE; } else { build_room(yloc[k], xloc[k]); } } else build_room(yloc[k], xloc[k]); k++; } for (i = 0; i < k; i++) { pick1 = randint(k) - 1; pick2 = randint(k) - 1; y1 = yloc[pick1]; x1 = xloc[pick1]; yloc[pick1] = yloc[pick2]; xloc[pick1] = xloc[pick2]; yloc[pick2] = y1; xloc[pick2] = x1; } doorindex = 0; /* move zero entry to k, so that can call build_tunnel all k times */ yloc[k] = yloc[0]; xloc[k] = xloc[0]; for (i = 0; i < k; i++) { y1 = yloc[i]; x1 = xloc[i]; y2 = yloc[i + 1]; x2 = xloc[i + 1]; build_tunnel(y2, x2, y1, x1); } fill_cave(GRANITE_WALL); for (i = 0; i < DUN_STR_MAG; i++) place_streamer(MAGMA_WALL, DUN_STR_MC); for (i = 0; i < DUN_STR_QUA; i++) place_streamer(QUARTZ_WALL, DUN_STR_QC); place_boundary(); /* Place intersection doors */ for (i = 0; i < doorindex; i++) { try_door(doorstk[i].y, doorstk[i].x - 1); try_door(doorstk[i].y, doorstk[i].x + 1); try_door(doorstk[i].y - 1, doorstk[i].x); try_door(doorstk[i].y + 1, doorstk[i].x); } if (spec_level == SPEC_DEST) place_destroyed(); alloc_level = (dun_level / 3); if (alloc_level < 2) alloc_level = 2; else if (alloc_level > 10) alloc_level = 10; place_stairs(2, randint(2) + 2, 3); place_stairs(1, randint(2), 3); /* Set up the character co-ords, used by alloc_monster, place_win_monster */ new_spot(&char_row, &char_col); alloc_monster((randint(8) + MIN_MALLOC_LEVEL + alloc_level), 0, TRUE); alloc_object(set_corr, 3, randint(alloc_level)); alloc_object(set_room, 5, randnor(TREAS_ROOM_ALLOC, 3)); alloc_object(set_floor, 5, randnor(TREAS_ANY_ALLOC, 3)); alloc_object(set_floor, 4, randnor(TREAS_GOLD_ALLOC, 3)); alloc_object(set_floor, 1, randint(alloc_level)); if (place_ghost()) good_item_flag = TRUE; else if (spec_level == SPEC_DEST) { int flag, counter = 0; do { flag = place_ghost(); counter++; } while (!flag && counter < 10); if (flag) good_item_flag = TRUE; } if (randint(5) < 4 && dun_level >= WIN_MON_APPEAR) place_win_monster(); } /* Builds a store at a row, column coordinate */ static void build_store(store_num, y, x) int store_num, y, x; { int yval, y_height, y_depth; int xval, x_left, x_right; register int i, j; int cur_pos, tmp; register cave_type *c_ptr; yval = y * 10 + 5; xval = x * 14 + 12; y_height = yval - randint(3); y_depth = yval + randint(4); x_left = xval - randint(4); x_right = xval + randint(4); for (i = y_height; i <= y_depth; i++) for (j = x_left; j <= x_right; j++) cave[i][j].fval = BOUNDARY_WALL; tmp = randint(4); if (tmp < 3) { i = randint(y_depth - y_height) + y_height - 1; if (tmp == 1) j = x_left; else j = x_right; } else { j = randint(x_right - x_left) + x_left - 1; if (tmp == 3) i = y_depth; else i = y_height; } c_ptr = &cave[i][j]; c_ptr->fval = CORR_FLOOR; cur_pos = popt(); c_ptr->tptr = cur_pos; invcopy(&t_list[cur_pos], OBJ_STORE_DOOR + store_num); } /* Link all free space in treasure list together */ static void tlink() { register int i; for (i = 0; i < MAX_TALLOC; i++) invcopy(&t_list[i], OBJ_NOTHING); tcptr = MIN_TRIX; } /* Link all free space in monster list together */ static void mlink() { register int i; for (i = 0; i < MAX_MALLOC; i++) if (m_list[i].mptr) delete_monster(i); for (i = 0; i < MAX_MALLOC; i++) m_list[i] = blank_monster; delete_unique(); /* Kludgey Fix ~Ludwig */ mfptr = MIN_MONIX; } /* Town logic flow for generation of new town */ static void town_gen() { register int i, j, l, m; register cave_type *c_ptr; int rooms[MAX_STORES], k; set_seed(town_seed); for (i = 0; i < MAX_STORES; i++) rooms[i] = i; l = MAX_STORES; for (i = 0; i < 2; i++) for (j = 0; j < 4; j++) { k = randint(l) - 1; build_store(rooms[k], i, j); for (m = k; m < l - 1; m++) rooms[m] = rooms[m + 1]; l--; } fill_cave(DARK_FLOOR); /* make stairs before reset_seed, so that they don't move around */ place_boundary(); place_stairs(2, 1, 0); reset_seed(); /* Set up the character co-ords, used by alloc_monster below */ new_spot(&char_row, &char_col); if (0x1 & (turn / 5000)) { /* Night */ for (i = 0; i < cur_height; i++) { c_ptr = &cave[i][0]; for (j = 0; j < cur_width; j++) { if (c_ptr->fval != DARK_FLOOR) c_ptr->pl = TRUE; c_ptr++; } } alloc_monster(MIN_MALLOC_TN, 3, TRUE); } else { /* Day */ for (i = 0; i < cur_height; i++) { c_ptr = &cave[i][0]; for (j = 0; j < cur_width; j++) { c_ptr->pl = TRUE; c_ptr++; } } alloc_monster(MIN_MALLOC_TD, 3, TRUE); } store_maint(); place_ghost(); } /* Generates a random dungeon level -RAK- */ void generate_cave() { panel_row_min = 0; panel_row_max = 0; panel_col_min = 0; panel_col_max = 0; char_row = (-1); char_col = (-1); tlink(); mlink(); blank_cave(); object_level = dun_level; /* prevent great 50' levels with chars who * have gone much deeper -CWS */ if (dun_level == 0) { cur_height = SCREEN_HEIGHT; cur_width = SCREEN_WIDTH; max_panel_rows = (cur_height / SCREEN_HEIGHT) * 2 - 2; max_panel_cols = (cur_width / SCREEN_WIDTH) * 2 - 2; panel_row = max_panel_rows; panel_col = max_panel_cols; town_gen(); } else { cur_height = MAX_HEIGHT; cur_width = MAX_WIDTH; max_panel_rows = (cur_height / SCREEN_HEIGHT) * 2 - 2; max_panel_cols = (cur_width / SCREEN_WIDTH) * 2 - 2; panel_row = max_panel_rows; panel_col = max_panel_cols; cave_gen(); } unfelt = TRUE; feeling = 0; if (rating > 100) feeling = 2; else if (rating > 80) feeling = 3; else if (rating > 60) feeling = 4; else if (rating > 40) feeling = 5; else if (rating > 30) feeling = 6; else if (rating > 20) feeling = 7; else if (rating > 10) feeling = 8; else if (rating > 0) feeling = 9; else feeling = 10; if (good_item_flag) /* do this last to explicitly set value -CWS */ feeling = 1; }