/* 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); }
/* 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); }
/* * 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; }
/* * 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 */ }
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); }
/* 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; }
/* 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; }
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!"); } }
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!"); } }
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; }