Esempio n. 1
0
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++;
        }
    }
}
Esempio n. 2
0
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);
}
Esempio n. 3
0
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);
}
Esempio n. 4
0
/* 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;
}
Esempio n. 5
0
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 */
    }
}
Esempio n. 6
0
/* 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);
        }
    }
}