static void init_fill(struct level *lev, schar bg_typ, schar fg_typ) { int i, j; long limit, count; limit = (WIDTH * HEIGHT * 2) / 5; count = 0; while (count < limit) { i = 1 + mklev_rn2(WIDTH - 1, lev); j = 1 + mklev_rn2(HEIGHT - 1, lev); if (lev->locations[i][j].typ == bg_typ) { lev->locations[i][j].typ = fg_typ; count++; } } }
static void mkshop(struct level *lev) { struct mkroom *sroom; int styp, j; char *ep = NULL; /* first determine shoptype */ styp = -1; for (sroom = &lev->rooms[0];; sroom++) { if (sroom->hx < 0) return; if (sroom - lev->rooms >= lev->nroom) { pline("lev->rooms not closed by -1?"); return; } if (sroom->rtype != OROOM) continue; if (has_dnstairs(lev, sroom) || has_upstairs(lev, sroom)) continue; if ((wizard && ep && sroom->doorct != 0) || sroom->doorct == 1) break; } if (!sroom->rlit) { int x, y; for (x = sroom->lx - 1; x <= sroom->hx + 1; x++) for (y = sroom->ly - 1; y <= sroom->hy + 1; y++) lev->locations[x][y].lit = 1; sroom->rlit = 1; } if (styp < 0) { /* pick a shop type at random */ j = 1 + mklev_rn2(100, lev); for (styp = 0; (j -= shtypes[styp].prob) > 0; styp++) continue; /* big rooms cannot be wand or book shops, so make them general stores */ if (isbig(sroom) && (shtypes[styp].symb == WAND_CLASS || shtypes[styp].symb == SPBOOK_CLASS)) styp = 0; } sroom->rtype = SHOPBASE + styp; /* set room bits before stocking the shop */ topologize(lev, sroom); /* stock the room with a shopkeeper and artifacts */ stock_room(styp, lev, sroom); }
void mkmap(struct level *lev, lev_init *init_lev) { schar bg_typ = init_lev->bg, fg_typ = init_lev->fg; boolean smooth = init_lev->smoothed, join = init_lev->joined; xchar lit = init_lev->lit, walled = init_lev->walled; int i; if (lit < 0) lit = (mklev_rn2(1 + abs(depth(&u.uz)), lev) < 10 && mklev_rn2(77, lev)) ? 1 : 0; new_locations = malloc((WIDTH + 1) * HEIGHT); init_map(lev, bg_typ); init_fill(lev, bg_typ, fg_typ); for (i = 0; i < N_P1_ITER; i++) pass_one(lev, bg_typ, fg_typ); for (i = 0; i < N_P2_ITER; i++) pass_two(lev, bg_typ, fg_typ); if (smooth) for (i = 0; i < N_P3_ITER; i++) pass_three(lev, bg_typ, fg_typ); if (join) join_map(lev, bg_typ, fg_typ); finish_map(lev, fg_typ, bg_typ, (boolean) lit, (boolean) walled); /* a walled, joined level is cavernous, not mazelike -dlc */ if (walled && join) { lev->flags.is_maze_lev = FALSE; lev->flags.is_cavernous_lev = TRUE; } free(new_locations); }
/* create a new shopkeeper in the given room; uses level creation RNG */ static int shkinit(const struct shclass *shp, struct level *lev, struct mkroom *sroom) { int sh, sx, sy; struct monst *shk; /* place the shopkeeper in the given room */ sh = sroom->fdoor; sx = lev->doors[sh].x; sy = lev->doors[sh].y; /* check that the shopkeeper placement is sane */ if (sroom->irregular) { int rmno = (sroom - lev->rooms) + ROOMOFFSET; if (isok(sx - 1, sy) && !lev->locations[sx - 1][sy].edge && (int)lev->locations[sx - 1][sy].roomno == rmno) sx--; else if (isok(sx + 1, sy) && !lev->locations[sx + 1][sy].edge && (int)lev->locations[sx + 1][sy].roomno == rmno) sx++; else if (isok(sx, sy - 1) && !lev->locations[sx][sy - 1].edge && (int)lev->locations[sx][sy - 1].roomno == rmno) sy--; else if (isok(sx, sy + 1) && !lev->locations[sx][sy + 1].edge && (int)lev->locations[sx][sy + 1].roomno == rmno) sx++; else goto shk_failed; } else if (sx == sroom->lx - 1) sx++; else if (sx == sroom->hx + 1) sx--; else if (sy == sroom->ly - 1) sy++; else if (sy == sroom->hy + 1) sy--; else { shk_failed: return -1; } if (MON_AT(lev, sx, sy)) rloc(m_at(lev, sx, sy), FALSE); /* insurance */ /* now initialize the shopkeeper monster structure */ if (!(shk = makemon(&mons[PM_SHOPKEEPER], lev, sx, sy, MM_ALLLEVRNG))) return -1; shk->isshk = 1; msethostility(shk, FALSE, TRUE); shk->msleeping = 0; shk->mtrapseen = ~0; /* we know all the traps already */ ESHK(shk)->shoproom = (sroom - lev->rooms) + ROOMOFFSET; sroom->resident = shk; ESHK(shk)->shoptype = sroom->rtype; assign_level(&(ESHK(shk)->shoplevel), &lev->z); ESHK(shk)->shd = lev->doors[sh]; ESHK(shk)->shk.x = sx; ESHK(shk)->shk.y = sy; ESHK(shk)->robbed = 0L; ESHK(shk)->credit = 0L; ESHK(shk)->debit = 0L; ESHK(shk)->loan = 0L; ESHK(shk)->visitct = 0; ESHK(shk)->following = 0; ESHK(shk)->billct = 0; ESHK(shk)->bill_inactive = FALSE; /* initial capital */ mkmonmoney(shk, 1030L + 30L * mklev_rn2(100, lev), rng_for_level(&lev->z)); if (shp->shknms == shkrings) mongets(shk, TOUCHSTONE, rng_for_level(&lev->z)); nameshk(shk, shp->shknms, lev); return sh; }
static void join_map(struct level *lev, schar bg_typ, schar fg_typ) { struct mkroom *croom, *croom2; int i, j; int sx, sy; coord sm, em; enum rng rng = rng_for_level(&lev->z); /* first, use flood filling to find all of the regions that need joining */ for (i = 1; i <= WIDTH; i++) for (j = 1; j < HEIGHT; j++) { if (lev->locations[i][j].typ == fg_typ && lev->locations[i][j].roomno == NO_ROOM) { min_rx = max_rx = i; min_ry = max_ry = j; n_loc_filled = 0; flood_fill_rm(lev, i, j, lev->nroom + ROOMOFFSET, FALSE, FALSE); if (n_loc_filled > 3) { add_room(lev, min_rx, min_ry, max_rx, max_ry, FALSE, OROOM, TRUE); lev->rooms[lev->nroom - 1].irregular = TRUE; if (lev->nroom >= (MAXNROFROOMS * 2)) goto joinm; } else { /* * it's a tiny hole; erase it from the map to avoid * having the player end up here with no way out. */ for (sx = min_rx; sx <= max_rx; sx++) for (sy = min_ry; sy <= max_ry; sy++) if ((int)lev->locations[sx][sy].roomno == lev->nroom + ROOMOFFSET) { lev->locations[sx][sy].typ = bg_typ; lev->locations[sx][sy].roomno = NO_ROOM; } } } } joinm: /* * Ok, now we can actually join the regions with fg_typ's. * The rooms are already sorted due to the previous loop, * so don't call sort_rooms(), which can screw up the roomno's * validity in the level->locations structure. */ for (croom = &lev->rooms[0], croom2 = croom + 1; croom2 < &lev->rooms[lev->nroom];) { /* pick random starting and end locations for "corridor" */ if (!somexy(lev, croom, &sm, rng) || !somexy(lev, croom2, &em, rng)) { /* ack! -- the level is going to be busted */ /* arbitrarily pick centers of both rooms and hope for the best */ impossible("No start/end room loc in join_map."); sm.x = croom->lx + ((croom->hx - croom->lx) / 2); sm.y = croom->ly + ((croom->hy - croom->ly) / 2); em.x = croom2->lx + ((croom2->hx - croom2->lx) / 2); em.y = croom2->ly + ((croom2->hy - croom2->ly) / 2); } dig_corridor(lev, &sm, &em, FALSE, fg_typ, bg_typ); /* choose next region to join */ /* only increment croom if croom and croom2 are non-overlapping */ if (croom2->lx > croom->hx || ((croom2->ly > croom->hy || croom2->hy < croom->ly) && mklev_rn2(3, lev))) { croom = croom2; } croom2++; /* always increment the next room */ } }
/* exclusively for mktemple(); uses level creation RNG */ void priestini(struct level *lev, struct mkroom *sroom, int sx, int sy, boolean sanctum) { /* is it the seat of the high priest? */ struct monst *priest = NULL; struct obj *otmp; int cnt; coord *priest_pos, pos_array[] = { { sx + 1, sy }, { sx - 1, sy }, { sx, sy + 1 }, { sx, sy - 1 }, { sx, sy }, { COLNO, ROWNO }, }; /* Search for a good position for the priest. The -1 in the array bound is * to ensure that we stop on the { COLNO, ROWNO } entry which is not ok. Do * not pass a monster to goodpos(), because we will move any monster later. */ for (priest_pos = pos_array; !goodpos(lev, priest_pos->x, priest_pos->y, NULL, 0) && (priest_pos < pos_array + ARRAY_SIZE(pos_array) - 1); ++priest_pos) {} if (!isok(priest_pos->x, priest_pos->y)) { impossible("Unable to find location for priest in shrine"); } else { if (MON_AT(lev, priest_pos->x, priest_pos->y)) rloc(m_at(lev, priest_pos->x, priest_pos->y), FALSE); priest = makemon(&mons[sanctum ? PM_HIGH_PRIEST : PM_ALIGNED_PRIEST], lev, priest_pos->x, priest_pos->y, MM_ALLLEVRNG); } if (priest) { EPRI(priest)->shroom = (sroom - lev->rooms) + ROOMOFFSET; EPRI(priest)->shralign = Amask2align(lev->locations[sx][sy].altarmask); EPRI(priest)->shrpos.x = sx; EPRI(priest)->shrpos.y = sy; assign_level(&(EPRI(priest)->shrlevel), &lev->z); priest->mtrapseen = ~0; /* traps are known */ priest->mpeaceful = 1; priest->ispriest = 1; priest->msleeping = 0; set_malign(priest); /* mpeaceful may have changed */ /* now his/her goodies... */ if (sanctum && CONST_EPRI(priest)->shralign == A_NONE && on_level(&sanctum_level, &lev->z)) { mongets(priest, AMULET_OF_YENDOR, rng_for_level(&lev->z)); } /* 2 to 4 spellbooks */ for (cnt = rn1(3, 2); cnt > 0; --cnt) { mpickobj(priest, mkobj(level, SPBOOK_CLASS, FALSE, rng_for_level(&lev->z))); } /* robe [via makemon()] */ if (mklev_rn2(2, lev) && (otmp = which_armor(priest, os_armc)) != 0) { if (p_coaligned(priest)) uncurse(otmp); else curse(otmp); } } }