Beispiel #1
0
/* put the object at the given location */
void
place_object(register struct obj *otmp, int x, int y)
{
    register struct obj *otmp2 = level.objects[x][y];

    if (otmp->where != OBJ_FREE)
        panic("place_object: obj not free (%d,%d,%d)", otmp->where, otmp->otyp, otmp->invlet);

    obj_no_longer_held(otmp);
    if (otmp->otyp == BOULDER) block_point(x,y);	/* vision */

    /* obj goes under boulders */
    if (otmp2 && (otmp2->otyp == BOULDER)) {
        otmp->nexthere = otmp2->nexthere;
        otmp2->nexthere = otmp;
    } else {
        otmp->nexthere = otmp2;
        level.objects[x][y] = otmp;
    }

    /* set the new object's location */
    otmp->ox = x;
    otmp->oy = y;

    otmp->where = OBJ_FLOOR;

    /* add to floor chain */
    otmp->nobj = fobj;
    fobj = otmp;
    if (otmp->timed) obj_timer_checks(otmp, x, y, 0);
}
Beispiel #2
0
/* put the object at the given location */
void place_object(struct obj *otmp, struct level *lev, int x, int y)
{
    struct obj *otmp2 = lev->objects[x][y];

    if (otmp->where != OBJ_FREE)
	panic("place_object: obj not free");

    obj_no_longer_held(otmp);
    if (otmp->otyp == BOULDER) block_point(x,y);	/* vision */

    /* obj goes under boulders */
    if (otmp2 && (otmp2->otyp == BOULDER)) {
	otmp->nexthere = otmp2->nexthere;
	otmp2->nexthere = otmp;
    } else {
	otmp->nexthere = otmp2;
	lev->objects[x][y] = otmp;
    }

    /* set the new object's location */
    otmp->ox = x;
    otmp->oy = y;

    otmp->where = OBJ_FLOOR;
    set_obj_level(lev, otmp); /* set the level recursively for containers */

    /* add to floor chain */
    otmp->nobj = lev->objlist;
    lev->objlist = otmp;
    if (otmp->timed) obj_timer_checks(otmp, x, y, 0);
}
Beispiel #3
0
/*
 * Close the drawbridge located at x,y.
 * Returns TRUE if the drawbridge was closed, FALSE otherwise.
 */
boolean close_drawbridge(int x, int y)
{
	struct rm *loc1, *loc2;
	struct monst *m;
	struct trap *t;
	int x2, y2;

	loc1 = &level->locations[x][y];
	if (loc1->typ != DRAWBRIDGE_DOWN) return FALSE;
	/* A huge monster will block the drawbridge. */
	if ((m = m_at(level, x, y)) && hugemonst(m->data)) {
	    pline("%s blocks the drawbridge with %s weight!",
		  canseemon(level, m) ? Amonnam(m) : "Something",
		  canseemon(level, m) ? mhis(level, m) : "its");
	    return FALSE;
	}
	if (rn2(5) == 0) {
	    pline("The mechanism seems to have something stuck in it and won't close.");
	    return FALSE;
	}
	x2 = x; y2 = y;
	get_wall_for_db(&x2,&y2);
	if (cansee(x,y) || cansee(x2,y2))
		pline("You see a drawbridge %s up!",
		    (((u.ux == x || u.uy == y) && !Underwater) ||
		     distu(x2,y2) < distu(x,y)) ? "coming" : "going");
	loc1->typ = DRAWBRIDGE_UP;
	loc2 = &level->locations[x2][y2];
	loc2->typ = DBWALL;
	switch (loc1->drawbridgemask & DB_DIR) {
		case DB_NORTH:
		case DB_SOUTH:
			loc2->horizontal = TRUE;
			break;
		case DB_WEST:
		case DB_EAST:
			loc2->horizontal = FALSE;
			break;
	}
	loc2->wall_info = W_NONDIGGABLE;
	set_entity(x, y, &(occupants[0]));
	set_entity(x2, y2, &(occupants[1]));
	do_entity(&(occupants[0]));		/* Do set_entity after first */
	set_entity(x2, y2, &(occupants[1]));	/* do_entity for worm tail */
	do_entity(&(occupants[1]));
	if (OBJ_AT(x, y) && flags.soundok)
	    You_hear("smashing and crushing.");
	revive_nasty(x,y,NULL);
	revive_nasty(x2,y2,NULL);
	delallobj(x, y);
	delallobj(x2, y2);
	if ((t = t_at(level, x, y)) != 0) deltrap(level, t);
	if ((t = t_at(level, x2, y2)) != 0) deltrap(level, t);
	newsym(x, y);
	newsym(x2, y2);
	block_point(x2,y2);	/* vision */
	return TRUE;
}
Beispiel #4
0
/*
 * Close the drawbridge located at x,y
 */
void
close_drawbridge(int x, int y)
{
    struct rm *loc1, *loc2;
    struct trap *t;
    int x2, y2;

    loc1 = &level->locations[x][y];
    if (loc1->typ != DRAWBRIDGE_DOWN)
        return;
    x2 = x;
    y2 = y;
    get_wall_for_db(&x2, &y2);
    if (cansee(x, y) || cansee(x2, y2))
        pline("You see a drawbridge %s up!",
              (((u.ux == x || u.uy == y) && !Underwater) ||
               distu(x2, y2) < distu(x, y)) ? "coming" : "going");
    else if (canhear())
        pline("You hear chains rattling and gears turning.");
    loc1->typ = DRAWBRIDGE_UP;
    loc2 = &level->locations[x2][y2];
    loc2->typ = DBWALL;
    switch (loc1->drawbridgemask & DB_DIR) {
    case DB_NORTH:
    case DB_SOUTH:
        loc2->horizontal = TRUE;
        break;
    case DB_WEST:
    case DB_EAST:
        loc2->horizontal = FALSE;
        break;
    }
    loc2->wall_info = W_NONDIGGABLE;
    set_entity(x, y, &(occupants[0]));
    set_entity(x2, y2, &(occupants[1]));
    do_entity(&(occupants[0])); /* Do set_entity after first */
    set_entity(x2, y2, &(occupants[1]));        /* do_entity for worm tail */
    do_entity(&(occupants[1]));
    if (OBJ_AT(x, y))
        You_hear("smashing and crushing.");
    revive_nasty(x, y, NULL);
    revive_nasty(x2, y2, NULL);
    delallobj(x, y);
    delallobj(x2, y2);
    if ((t = t_at(level, x, y)) != 0)
        deltrap(level, t);
    if ((t = t_at(level, x2, y2)) != 0)
        deltrap(level, t);
    del_engr_at(level, x, y);
    del_engr_at(level, x2, y2);
    newsym(x, y);
    newsym(x2, y2);
    block_point(x2, y2);        /* vision */
}
Beispiel #5
0
static bool clear_fcorr(struct monst *grd, bool forceshow) {
    int fcx, fcy, fcbeg;
    struct monst *mtmp;

    if (!on_level(&(EGD(grd)->gdlevel), &u.uz))
        return true;

    while ((fcbeg = EGD(grd)->fcbeg) < EGD(grd)->fcend) {
        fcx = EGD(grd)->fakecorr[fcbeg].fx;
        fcy = EGD(grd)->fakecorr[fcbeg].fy;
        if ((grd->mhp <= 0 || !in_fcorridor(grd, u.ux, u.uy)) &&
        EGD(grd)->gddone)
            forceshow = true;
        if ((u.ux == fcx && u.uy == fcy && grd->mhp > 0) || (!forceshow && couldsee(fcx, fcy)) || (Punished && !carried(uball) && uball->ox == fcx && uball->oy == fcy))
            return false;

        if ((mtmp = m_at(fcx, fcy)) != 0) {
            if (mtmp->isgd)
                return (false);
            else if (!in_fcorridor(grd, u.ux, u.uy)) {
                if (mtmp->mtame)
                    yelp(mtmp);
                (void)rloc(mtmp, false);
            }
        }
        levl[fcx][fcy].typ = EGD(grd)->fakecorr[fcbeg].ftyp;
        map_location(fcx, fcy, 1); /* bypass vision */
        if (!ACCESSIBLE(levl[fcx][fcy].typ))
            block_point(fcx, fcy);
        EGD(grd)->fcbeg++;
    }
    if (grd->mhp <= 0) {
        pline_The("corridor disappears.");
        if (IS_ROCK(levl[u.ux][u.uy].typ))
            You("are encased in rock.");
    }
    return (true);
}
Beispiel #6
0
/* returns true if something happened */
boolean
doorlock(struct obj * otmp, int x, int y)
{
    struct rm *door = &level->locations[x][y];
    boolean res = TRUE;
    int loudness = 0;
    int wandlevel = 0;
    if (otmp->oclass == WAND_CLASS)
        wandlevel = getwandlevel(&youmonst, otmp); /* Not completely right, but works
                                                      since monsters wont use knock/wizlock */
    const char *msg = NULL;
    const char *dustcloud = "A cloud of dust";
    const char *quickly_dissipates = "quickly dissipates";

    if (door->typ == SDOOR) {
        switch (otmp->otyp) {
        case WAN_OPENING:
        case SPE_KNOCK:
        case WAN_STRIKING:
        case SPE_FORCE_BOLT:
            door->typ = DOOR;
            door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
            newsym(x, y);
            if (cansee(x, y))
                pline(msgc_youdiscover, "A door appears in the wall!");
            if (otmp->otyp == WAN_OPENING || otmp->otyp == SPE_KNOCK)
                return TRUE;
            break;      /* striking: continue door handling below */
        case WAN_LOCKING:
        case SPE_WIZARD_LOCK:
        default:
            return FALSE;
        }
    }

    switch (otmp->otyp) {
    case WAN_LOCKING:
    case SPE_WIZARD_LOCK:
        if (Is_rogue_level(&u.uz)) {
            boolean vis = cansee(x, y);

            /* Can't have real locking in Rogue, so just hide doorway */
            if (vis)
                pline(msgc_actionok,
                      "%s springs up in the older, more primitive doorway.",
                      dustcloud);
            else
                You_hear(msgc_actionok, "a swoosh.");
            if (obstructed(x, y, msgc_yafm)) {
                if (vis)
                    pline(msgc_yafm, "The cloud %s.", quickly_dissipates);
                return FALSE;
            }
            block_point(x, y);
            door->typ = SDOOR;
            if (vis)
                pline(msgc_actionok, "The doorway vanishes!");
            newsym(x, y);
            return TRUE;
        }
        if (obstructed(x, y, msgc_yafm))
            return FALSE;
        /* Don't allow doors to close over traps.  This is for pits */
        /* & trap doors, but is it ever OK for anything else? */
        if (t_at(level, x, y)) {
            /* maketrap() clears doormask, so it should be NODOOR */
            pline(msgc_yafm, "%s springs up in the doorway, but %s.",
                  dustcloud, quickly_dissipates);
            return FALSE;
        }
        if (wandlevel == P_MASTER) {
            pline(msgc_yafm,
                  "%s springs up in the doorway and conceals it!", dustcloud);
            door->typ = SDOOR;
            newsym(x, y);
            return TRUE;
        }

        switch (door->doormask & ~D_TRAPPED) {
        case D_CLOSED:
            msg = "The door locks!";
            break;
        case D_ISOPEN:
            msg = "The door swings shut, and locks!";
            break;
        case D_BROKEN:
            msg = "The broken door reassembles and locks!";
            break;
        case D_NODOOR:
            msg =
                "A cloud of dust springs up and assembles itself into a door!";
            break;
        default:
            res = FALSE;
            break;
        }
        block_point(x, y);
        door->doormask = D_LOCKED | (door->doormask & D_TRAPPED);
        newsym(x, y);
        break;
    case WAN_OPENING:
    case SPE_KNOCK:
        if (door->doormask & D_LOCKED) {
            msg = "The door unlocks!";
            door->doormask = D_CLOSED | (door->doormask & D_TRAPPED);
        } else
            res = FALSE;
        break;
    case WAN_STRIKING:
    case SPE_FORCE_BOLT:
        if (door->doormask & (D_LOCKED | D_CLOSED)) {
            if (door->doormask & D_TRAPPED) {
                if (MON_AT(level, x, y))
                    mb_trapped(m_at(level, x, y));
                else {
                    if (cansee(x, y))
                        pline(msgc_substitute,
                              "KABOOM!!  You see a door explode.");
                    else
                        You_hear(msgc_levelsound, "a distant explosion.");
                }
                door->doormask = D_NODOOR;
                unblock_point(x, y);
                newsym(x, y);
                loudness = 40;
                break;
            }
            door->doormask = D_BROKEN;
            if (cansee(x, y))
                pline(msgc_actionok, "The door crashes open!");
            else
                You_hear(msgc_levelsound, "a crashing sound.");
            unblock_point(x, y);
            newsym(x, y);
            /* force vision recalc before printing more messages */
            if (turnstate.vision_full_recalc)
                vision_recalc(0);
            loudness = 20;
        } else
            res = FALSE;
        break;
    default:
        impossible("magic (%d) attempted on door.", otmp->otyp);
        break;
    }
    if (msg && cansee(x, y)) {
        pline(msgc_actionok, "%s", msg);
        /* we know whether it's locked now */
        level->locations[x][y].mem_door_l = 1;
        map_background(x, y, TRUE);
    }
    if (loudness > 0) {
        /* door was destroyed */
        wake_nearto(x, y, loudness);
        if (*in_rooms(level, x, y, SHOPBASE))
            add_damage(x, y, 0L);
    }

    return res;
}
Beispiel #7
0
/* try to close a door */
int
doclose(const struct nh_cmd_arg *arg)
{
    struct rm *door;
    struct monst *mtmp;
    coord cc;
    schar dx, dy, dz;

    if (nohands(youmonst.data)) {
        pline(msgc_cancelled, "You can't close anything -- you have no hands!");
        return 0;
    }

    if (u.utrap && u.utraptype == TT_PIT) {
        pline(msgc_cancelled, "You can't reach over the edge of the pit.");
        return 0;
    }

    if (!getargdir(arg, NULL, &dx, &dy, &dz))
        return 0;

    cc.x = youmonst.mx + dx;
    cc.y = youmonst.my + dy;
    if (!isok(cc.x, cc.y))
        return 0;

    if ((cc.x == youmonst.mx) && (cc.y == youmonst.my)) {
        pline(msgc_cancelled1, "You are in the way!");
        return 1;
    }

    if ((mtmp = m_at(level, cc.x, cc.y)) && mtmp->m_ap_type == M_AP_FURNITURE &&
        (mtmp->mappearance == S_hcdoor || mtmp->mappearance == S_vcdoor) &&
        !Protection_from_shape_changers) {

        stumble_onto_mimic(mtmp, dx, dy);
        return 1;
    }

    door = &level->locations[cc.x][cc.y];

    if (!IS_DOOR(door->typ)) {
        if (door->typ == DRAWBRIDGE_DOWN)
            pline(msgc_cancelled,
                  "There is no obvious way to close the drawbridge.");
        else
            pline(msgc_mispaste, "You %s no door there.",
                  Blind ? "feel" : "see");
        return 0;
    }

    if (door->doormask == D_NODOOR) {
        pline(msgc_cancelled, "This doorway has no door.");
        return 0;
    }

    if (obstructed(cc.x, cc.y, msgc_cancelled))
        return 0;

    if (door->doormask == D_BROKEN) {
        pline(msgc_cancelled, "This door is broken.");
        return 0;
    }

    if (door->doormask & (D_CLOSED | D_LOCKED)) {
        pline(msgc_cancelled, "This door is already closed.");
        return 0;
    }

    if (door->doormask == D_ISOPEN) {
        if (verysmall(youmonst.data) && !u.usteed) {
            pline(msgc_cancelled, "You're too small to push the door closed.");
            return 0;
        }
        if (u.usteed ||
            rn2(25) < (ACURRSTR + ACURR(A_DEX) + ACURR(A_CON)) / 3) {
            pline(msgc_actionok, "The door closes.");
            door->doormask = D_CLOSED;
            door->mem_door_l = 1;
            /* map_background here sets the mem_door flags correctly; and it's
               redundant to both feel_location and newsym with a door.
               Exception: if we remember an invisible monster on the door
               square, but in this case, we want to set the memory of a door
               there anyway because we know there's a door there because we
               just closed it, and in Nitro this doesn't clash with keeping the 
               I there. */
            map_background(cc.x, cc.y, TRUE);
            if (Blind)
                feel_location(cc.x, cc.y);   /* the hero knows she closed it */
            else
                newsym(cc.x, cc.y);
            block_point(cc.x, cc.y);    /* vision: no longer see there */
        } else {
            exercise(A_STR, TRUE);
            pline(msgc_failrandom, "The door resists!");
        }
    }

    return 1;
}
Beispiel #8
0
static void wallify_vault(struct monst *grd) {
    int x, y, typ;
    int vlt = EGD(grd)->vroom;
    char tmp_viz;
    signed char lox = rooms[vlt].lx - 1, hix = rooms[vlt].hx + 1, loy = rooms[vlt].ly - 1, hiy = rooms[vlt].hy + 1;
    struct monst *mon;
    struct obj *gold;
    struct trap *trap;
    bool fixed = false;
    bool movedgold = false;

    for (x = lox; x <= hix; x++) {
        for (y = loy; y <= hiy; y++) {
            /* if not on the room boundary, skip ahead */
            if (x != lox && x != hix && y != loy && y != hiy)
                continue;

            if (!IS_WALL(levl[x][y].typ) && !in_fcorridor(grd, x, y)) {
                if ((mon = m_at(x, y)) != 0 && mon != grd) {
                    if (mon->mtame)
                        yelp(mon);
                    (void)rloc(mon, false);
                }
                if ((gold = g_at(x, y)) != 0) {
                    move_gold(gold, EGD(grd)->vroom);
                    movedgold = true;
                }
                if ((trap = t_at(x, y)) != 0)
                    deltrap(trap);
                if (x == lox)
                    typ = (y == loy) ? TLCORNER : (y == hiy) ? BLCORNER : VWALL;
                else if (x == hix)
                    typ = (y == loy) ? TRCORNER : (y == hiy) ? BRCORNER : VWALL;
                else
                    /* not left or right side, must be top or bottom */
                    typ = HWALL;
                levl[x][y].typ = typ;
                levl[x][y].flags = 0;
                /*
                 * hack: player knows walls are restored because of the
                 * message, below, so show this on the screen.
                 */
                tmp_viz = viz_array[y][x];
                viz_array[y][x] = IN_SIGHT | COULD_SEE;
                newsym(x, y);
                viz_array[y][x] = tmp_viz;
                block_point(x, y);
                fixed = true;
            }
        }
    }

    if (movedgold || fixed) {
        if (in_fcorridor(grd, grd->mx, grd->my) || cansee(grd->mx, grd->my)) {
            char name[BUFSZ];
            g_monnam(name, BUFSZ, grd);
            pline_The("%s whispers an incantation.", name);
        } else {
            You_hear("a distant chant.");
        }
        if (movedgold)
            pline("A mysterious force moves the gold into the vault.");
        if (fixed)
            pline_The("damaged vault's walls are magically restored!");
    }
}
Beispiel #9
0
static void
wallify_vault(struct monst *grd)
{
    int x, y, typ;
    int vlt = EGD(grd)->vroom;
    char tmp_viz;
    xchar lox = level->rooms[vlt].lx - 1, hix = level->rooms[vlt].hx + 1, loy =
        level->rooms[vlt].ly - 1, hiy = level->rooms[vlt].hy + 1;
    struct monst *mon;
    struct obj *gold;
    struct trap *trap;
    boolean fixed = FALSE;
    boolean movedgold = FALSE;

    for (x = lox; x <= hix; x++)
        for (y = loy; y <= hiy; y++) {
            /* if not on the room boundary, skip ahead */
            if (x != lox && x != hix && y != loy && y != hiy)
                continue;

            if (!IS_WALL(level->locations[x][y].typ) &&
                !in_fcorridor(grd, x, y)) {
                if ((mon = m_at(level, x, y)) != 0 && mon != grd) {
                    if (mon->mtame)
                        yelp(mon);
                    rloc(mon, FALSE);
                }
                if ((gold = gold_at(level, x, y)) != 0) {
                    move_gold(gold, EGD(grd)->vroom);
                    movedgold = TRUE;
                }
                if ((trap = t_at(level, x, y)) != 0)
                    deltrap(level, trap);
                if (x == lox)
                    typ = (y == loy) ? TLCORNER : (y == hiy) ? BLCORNER : VWALL;
                else if (x == hix)
                    typ = (y == loy) ? TRCORNER : (y == hiy) ? BRCORNER : VWALL;
                else    /* not left or right side, must be top or bottom */
                    typ = HWALL;
                level->locations[x][y].typ = typ;
                level->locations[x][y].doormask = 0;
                /* 
                 * hack: player knows walls are restored because of the
                 * message, below, so show this on the screen.
                 */
                tmp_viz = viz_array[y][x];
                viz_array[y][x] = IN_SIGHT | COULD_SEE;
                newsym(x, y);
                viz_array[y][x] = tmp_viz;
                block_point(x, y);
                fixed = TRUE;
            }
        }

    if (movedgold || fixed) {
        if (mon_visible(grd))
            pline("%s whispers an incantation.", Monnam(grd));
        else
            You_hear("a %s chant.", in_fcorridor(grd, grd->mx, grd->my)
                     ? "nearby" : "distant");
        if (movedgold)
            pline("A mysterious force moves the gold into the vault.");
        if (fixed)
            pline("The damaged vault's walls are magically restored!");
    }
}
Beispiel #10
0
static boolean
clear_fcorr(struct monst *grd, boolean forceshow)
{
    int fcx, fcy, fcbeg, oldtyp;
    struct monst *mtmp;
    boolean showmsg = FALSE;

    if (!on_level(&(EGD(grd)->gdlevel), &u.uz))
        return TRUE;

    while ((fcbeg = EGD(grd)->fcbeg) < EGD(grd)->fcend) {
        fcx = EGD(grd)->fakecorr[fcbeg].fx;
        fcy = EGD(grd)->fakecorr[fcbeg].fy;
        if ((grd->mhp <= 0 || !in_fcorridor(grd, u.ux, u.uy)) &&
            EGD(grd)->gddone)
            forceshow = TRUE;
        if ((u.ux == fcx && u.uy == fcy && grd->mhp > 0)
            || (!forceshow && couldsee(fcx, fcy)))
            return FALSE;

        if ((Punished && !carried(uball)
             && uball->ox == fcx && uball->oy == fcy)) {
            unplacebc();
            placebc();
        }

        if ((mtmp = m_at(level, fcx, fcy)) != 0) {
            if (mtmp->isgd)
                return FALSE;
            else if (!in_fcorridor(grd, u.ux, u.uy)) {
                if (mtmp->mtame)
                    yelp(mtmp);
                rloc(mtmp, FALSE);
            }
        }
        oldtyp = level->locations[fcx][fcy].typ;
        level->locations[fcx][fcy].typ = EGD(grd)->fakecorr[fcbeg].ftyp;
        if (!ACCESSIBLE(level->locations[fcx][fcy].typ) && ACCESSIBLE(oldtyp)) {
            struct trap *t = t_at(level, fcx, fcy);

            if (couldsee(fcx, fcy))
                showmsg = TRUE;
            if (t)
                deltrap(level, t);
            level->locations[fcx][fcy].lit = FALSE;
            block_point(fcx, fcy);
        }
        map_location(fcx, fcy, 1, FALSE);      /* bypass vision */
        EGD(grd)->fcbeg++;
    }
    if (grd->mhp <= 0) {
        if (showmsg) {
            if (!Blind)
                pline("The corridor disappears.");
            else
                pline("You feel claustrophobic.");
        }
        if (IS_ROCK(level->locations[u.ux][u.uy].typ))
            pline("You are encased in rock.");
    }
    return TRUE;
}