Exemplo n.º 1
0
/* make and stock a room of a given type

   Note: must not use the level creation RNG if this is of a room type that's
   affected by genocide/extinction (LEPREHALL, BEEHIVE, BARRACKS, ANTHOLE,
   COCKNEST), or genocide/extinction would change the layout of the rest of the
   level. */
void
mkroom(struct level *lev, int roomtype)
{
    if (roomtype >= SHOPBASE)
        mkshop(lev);    /* someday, we should be able to specify shop type */
    else
        switch (roomtype) {
        case COURT:
            mkzoo(lev, COURT, rng_for_level(&lev->z));
            break;
        case ZOO:
            mkzoo(lev, ZOO, rng_for_level(&lev->z));
            break;
        case BEEHIVE:
            mkzoo(lev, BEEHIVE, rng_main);
            break;
        case MORGUE:
            mkzoo(lev, MORGUE, rng_for_level(&lev->z));
            break;
        case BARRACKS:
            mkzoo(lev, BARRACKS, rng_main);
            break;
        case SWAMP:
            mkswamp(lev);
            break;
        case TEMPLE:
            mktemple(lev);
            break;
        case LEPREHALL:
            mkzoo(lev, LEPREHALL, rng_main);
            break;
        case COCKNEST:
            mkzoo(lev, COCKNEST, rng_main);
            break;
        case ANTHOLE:
            mkzoo(lev, ANTHOLE, rng_main);
            break;
        default:
            impossible("Tried to make a room of type %d.", roomtype);
        }
}
Exemplo n.º 2
0
static const struct permonst *
squadmon(const d_level *dlev)
{       /* return soldier types. */
    int sel_prob, i, cpro, mndx;

    sel_prob = 1 + rn2_on_rng(80 + level_difficulty(dlev), rng_for_level(dlev));

    cpro = 0;
    for (i = 0; i < NSTYPES; i++) {
        cpro += squadprob[i].prob;
        if (cpro > sel_prob) {
            mndx = squadprob[i].pm;
            goto gotone;
        }
    }
    mndx = squadprob[rn2_on_rng(NSTYPES, rng_for_level(dlev))].pm;
gotone:
    if (!(mvitals[mndx].mvflags & G_GONE))
        return &mons[mndx];
    else
        return NULL;
}
Exemplo n.º 3
0
static void
mktemple(struct level *lev)
{
    struct mkroom *sroom;
    coord *shrine_spot;
    struct rm *loc;

    if (!(sroom = pick_room(lev, TRUE, rng_for_level(&lev->z))))
        return;

    /* set up Priest and shrine */
    sroom->rtype = TEMPLE;
    /* 
     * In temples, shrines are blessed altars
     * located in the center of the room
     */
    shrine_spot = shrine_pos(lev, (sroom - lev->rooms) + ROOMOFFSET);
    loc = &lev->locations[shrine_spot->x][shrine_spot->y];
    loc->typ = ALTAR;
    loc->altarmask = induced_align(&lev->z, 80, rng_for_level(&lev->z));
    priestini(lev, sroom, shrine_spot->x, shrine_spot->y, FALSE);
    loc->altarmask |= AM_SHRINE;
}
Exemplo n.º 4
0
/* Make an object of the appropriate type for a shop square.

   Uses the level generation RNG. */
static void
mkshobj_at(const struct shclass *shp, struct level *lev, int sx, int sy)
{
    struct monst *mtmp;
    int atype;
    const struct permonst *ptr;
    enum rng rng = rng_for_level(&lev->z);

    if (rn2_on_rng(100, rng) < depth(&lev->z) && !MON_AT(lev, sx, sy) &&
        (ptr = mkclass(&lev->z, S_MIMIC, 0, rng)) &&
        (mtmp = makemon(ptr, lev, sx, sy, MM_ALLLEVRNG)) != 0) {
        /* note: makemon will set the mimic symbol to a shop item */
        if (rn2_on_rng(10, rng) >= depth(&lev->z)) {
            mtmp->m_ap_type = M_AP_OBJECT;
            mtmp->mappearance = STRANGE_OBJECT;
        }
    } else {
        atype = get_shop_item(shp - shtypes, rng);
        if (atype < 0)
            mksobj_at(-atype, lev, sx, sy, TRUE, TRUE, rng);
        else
            mkobj_at(atype, lev, sx, sy, TRUE, rng);
    }
}
Exemplo n.º 5
0
static void
mkswamp(struct level *lev)
{
    struct mkroom *sroom;
    int sx, sy, i, eelct = 0;

    enum rng rng = rng_for_level(&lev->z);

    for (i = 0; i < 5; i++) {   /* turn up to 5 rooms swampy */
        sroom = &lev->rooms[rn2_on_rng(lev->nroom, rng)];
        if (sroom->hx < 0 || sroom->rtype != OROOM || has_upstairs(lev, sroom)
            || has_dnstairs(lev, sroom))
            continue;

        /* satisfied; make a swamp */
        sroom->rtype = SWAMP;
        for (sx = sroom->lx; sx <= sroom->hx; sx++)
            for (sy = sroom->ly; sy <= sroom->hy; sy++)
                if (!OBJ_AT_LEV(lev, sx, sy) && !MON_AT(lev, sx, sy) &&
                    !t_at(lev, sx, sy) && !nexttodoor(lev, sx, sy)) {
                    if ((sx + sy) % 2) {
                        lev->locations[sx][sy].typ = POOL;
                        if (!eelct || !rn2_on_rng(4, rng)) {
                            /* mkclass() won't do, as we might get kraken */
                            makemon(rn2_on_rng(5, rng) ? &mons[PM_GIANT_EEL]
                                    : rn2_on_rng(2, rng) ? &mons[PM_PIRANHA]
                                    : &mons[PM_ELECTRIC_EEL], lev, sx, sy,
                                    MM_ALLLEVRNG);
                            eelct++;
                        }
                    } else if (!rn2_on_rng(4, rng)) /* swamps tend to be moldy */
                        makemon(mkclass(&lev->z, S_FUNGUS, 0, rng),
                                lev, sx, sy, MM_ALLLEVRNG);
                }
    }
}
Exemplo n.º 6
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;
}
Exemplo n.º 7
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 */
    }
}
Exemplo n.º 8
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);
        }
    }
}