/* * Open the drawbridge located at x,y */ void open_drawbridge(int x, int y) { struct rm *loc1, *loc2; struct trap *t; int x2, y2; loc1 = &level->locations[x][y]; if (loc1->typ != DRAWBRIDGE_UP) return; x2 = x; y2 = y; get_wall_for_db(&x2,&y2); if (cansee(x,y) || cansee(x2,y2)) pline("You see a drawbridge %s down!", (distu(x2,y2) < distu(x,y)) ? "going" : "coming"); loc1->typ = DRAWBRIDGE_DOWN; loc2 = &level->locations[x2][y2]; loc2->typ = DOOR; loc2->doormask = D_NODOOR; 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 tails */ do_entity(&(occupants[1])); revive_nasty(x,y,NULL); delallobj(x, y); 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); unblock_point(x2,y2); /* vision */ if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE; }
/* * 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 */ }
/* * Let's destroy the drawbridge located at x,y */ void destroy_drawbridge(int x, int y) { struct rm *loc1, *loc2; struct trap *t; int x2, y2; int db_u; boolean e_inview; struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]); loc1 = &level->locations[x][y]; if (!IS_DRAWBRIDGE(loc1->typ)) return; x2 = x; y2 = y; get_wall_for_db(&x2,&y2); loc2 = &level->locations[x2][y2]; db_u = (loc1->drawbridgemask & DB_UNDER); if (db_u == DB_MOAT || db_u == DB_LAVA || db_u == DB_BOG) { struct obj *otmp; int where = (db_u == DB_LAVA) ? 0 : (db_u == DB_MOAT) ? 1 : 2; static char *wstr[3] = { "lava", "moat", "swamp" }; if (loc1->typ == DRAWBRIDGE_UP) { if (cansee(x2,y2)) pline("The portcullis of the drawbridge falls into the %s!", wstr[where]); else if (flags.soundok) You_hear("a loud *SPLASH*!"); } else { if (cansee(x,y)) pline("The drawbridge collapses into the %s!", wstr[where]); else if (flags.soundok) You_hear("a loud *SPLASH*!"); } loc1->typ = (where == 0) ? LAVAPOOL : (where == 1) ? MOAT : BOG; loc1->drawbridgemask = 0; if ((otmp = sobj_at(BOULDER, level, x,y)) != 0) { obj_extract_self(otmp); flooreffects(otmp,x,y,"fall"); } } else { if (cansee(x,y)) pline("The drawbridge disintegrates!"); else You_hear("a loud *CRASH*!"); loc1->typ = ((loc1->drawbridgemask & DB_ICE) ? ICE : ROOM); loc1->icedpool = ((loc1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0); } wake_nearto(x, y, 500); loc2->typ = DOOR; loc2->doormask = D_NODOOR; 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); if (!does_block(level, x2, y2, NULL)) unblock_point(x2,y2); /* vision */ if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE; set_entity(x2, y2, etmp2); /* currently only automissers can be here */ if (etmp2->edata) { e_inview = e_canseemon(level, etmp2); if (!automiss(etmp2)) { if (e_inview) pline("%s blown apart by flying debris.", E_phrase(etmp2, "are")); killer_format = KILLED_BY_AN; killer = "exploding drawbridge"; e_died(etmp2, e_inview? 3 : 2, CRUSHING); /*no corpse*/ } /* nothing which is vulnerable can survive this */ } set_entity(x, y, etmp1); if (etmp1->edata) { e_inview = e_canseemon(level, etmp1); if (!e_missed(etmp1, TRUE)) { if (e_inview) { if (!is_u(etmp1) && Hallucination) pline("%s into some heavy metal!", E_phrase(etmp1, "get")); else pline("%s hit by a huge chunk of metal!", E_phrase(etmp1, "are")); } else { if (flags.soundok && !is_u(etmp1) && !is_pool(level, x,y)) You_hear("a crushing sound."); } killer_format = KILLED_BY_AN; killer = "collapsing drawbridge"; e_died(etmp1, e_inview? 3 : 2, CRUSHING); /*no corpse*/ if (loc1->typ == MOAT) do_entity(etmp1); } } }
/* * Let's destroy the drawbridge located at x,y */ void destroy_drawbridge(int x, int y) { struct rm *loc1, *loc2; struct trap *t; struct obj *chain; int x2, y2, i; boolean e_inview; struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]); loc1 = &level->locations[x][y]; if (!IS_DRAWBRIDGE(loc1->typ)) return; x2 = x; y2 = y; get_wall_for_db(&x2, &y2); loc2 = &level->locations[x2][y2]; if ((loc1->drawbridgemask & DB_UNDER) == DB_MOAT || (loc1->drawbridgemask & DB_UNDER) == DB_LAVA) { struct obj *otmp; boolean lava = (loc1->drawbridgemask & DB_UNDER) == DB_LAVA; if (loc1->typ == DRAWBRIDGE_UP) { if (cansee(x2, y2)) pline("The portcullis of the drawbridge falls into the %s!", lava ? "lava" : waterbody_name(x2, y2)); else You_hear("a loud *SPLASH*!"); } else { if (cansee(x, y)) pline("The drawbridge collapses into the %s!", lava ? "lava" : waterbody_name(x, y)); else You_hear("a loud *SPLASH*!"); } loc1->typ = lava ? LAVAPOOL : MOAT; loc1->drawbridgemask = 0; if ((otmp = sobj_at(BOULDER, level, x, y)) != 0) { obj_extract_self(otmp); flooreffects(otmp, x, y, "fall"); } } else { if (cansee(x, y)) pline("The drawbridge disintegrates!"); else You_hear("a loud *CRASH*!"); loc1->typ = ((loc1->drawbridgemask & DB_ICE) ? ICE : ROOM); loc1->icedpool = ((loc1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0); } wake_nearto(x, y, 500); loc2->typ = DOOR; loc2->doormask = D_NODOOR; 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); for (i = rn2(6); i > 0; --i) { /* scatter some debris */ /* doesn't matter if we happen to pick <x,y2> or <x2,y>; since drawbridges are never placed diagonally, those pairings will always match one of <x,y> or <x2,y2> */ chain = mksobj_at(IRON_CHAIN, level, rn2(2) ? x : x2, rn2(2) ? y : y2, TRUE, FALSE, rng_main); /* a force of 5 here would yield a radius of 2 for iron chain; anything less produces a radius of 1 */ (void) scatter(chain->ox, chain->oy, 1, MAY_HIT, chain); } newsym(x, y); newsym(x2, y2); if (!does_block(level, x2, y2)) unblock_point(x2, y2); /* vision */ if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE; set_entity(x2, y2, etmp2); /* currently only automissers can be here */ if (etmp2->edata) { e_inview = e_canseemon(etmp2); if (!automiss(etmp2)) { if (e_inview) pline("%s blown apart by flying debris.", E_phrase(etmp2, "are")); e_died(etmp2, e_inview ? 3 : 2, CRUSHING, killer_msg(CRUSHING, "an exploding drawbridge")); } /* nothing which is vulnerable can survive this */ } set_entity(x, y, etmp1); if (etmp1->edata) { e_inview = e_canseemon(etmp1); if (!e_missed(etmp1, TRUE)) { if (e_inview) { if (!is_u(etmp1) && Hallucination) pline("%s into some heavy metal!", E_phrase(etmp1, "get")); else pline("%s hit by a huge chunk of metal!", E_phrase(etmp1, "are")); } else { if (!is_u(etmp1) && !is_pool(level, x, y)) You_hear("a crushing sound."); } e_died(etmp1, e_inview ? 3 : 2, CRUSHING, killer_msg(CRUSHING, "a collapsing drawbridge")); /* if (loc1->typ == MOAT) do_entity(etmp1); */ } if (is_u(etmp1)) spoteffects(FALSE); else if (!DEADMONSTER(etmp1->emon)) minliquid(etmp1->emon); } }
/* * Let's destroy the drawbridge located at x,y */ void destroy_drawbridge(int x, int y) { struct rm *loc1, *loc2; struct trap *t; int x2, y2; boolean e_inview; struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]); loc1 = &level->locations[x][y]; if (!IS_DRAWBRIDGE(loc1->typ)) return; x2 = x; y2 = y; get_wall_for_db(&x2, &y2); loc2 = &level->locations[x2][y2]; if ((loc1->drawbridgemask & DB_UNDER) == DB_MOAT || (loc1->drawbridgemask & DB_UNDER) == DB_LAVA) { struct obj *otmp; boolean lava = (loc1->drawbridgemask & DB_UNDER) == DB_LAVA; if (loc1->typ == DRAWBRIDGE_UP) { if (cansee(x2, y2)) pline(msgc_consequence, "The portcullis of the drawbridge falls into the %s!", lava ? "lava" : waterbody_name(x2, y2)); else You_hear(msgc_levelsound, "a loud *SPLASH*!"); } else { if (cansee(x, y)) pline(msgc_consequence, "The drawbridge collapses into the %s!", lava ? "lava" : waterbody_name(x, y)); else You_hear(msgc_levelsound, "a loud *SPLASH*!"); } loc1->typ = lava ? LAVAPOOL : MOAT; loc1->drawbridgemask = 0; if ((otmp = sobj_at(BOULDER, level, x, y)) != 0) { obj_extract_self(otmp); flooreffects(otmp, x, y, "fall"); } } else { if (cansee(x, y)) pline(msgc_consequence, "The drawbridge disintegrates!"); else You_hear(msgc_levelsound, "a loud *CRASH*!"); loc1->typ = ((loc1->drawbridgemask & DB_ICE) ? ICE : ROOM); loc1->icedpool = ((loc1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0); } wake_nearto(x, y, 500); loc2->typ = DOOR; loc2->doormask = D_NODOOR; 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); if (!does_block(level, x2, y2)) unblock_point(x2, y2); /* vision */ if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE; set_entity(x2, y2, etmp2); /* currently only automissers can be here */ if (etmp2->edata) { enum msg_channel hit_msgc; if (is_u(etmp2)) hit_msgc = msgc_fatal_predone; else if (etmp2->emon->mtame && canspotmon(etmp2->emon)) hit_msgc = msgc_petfatal; else hit_msgc = msgc_monneutral; e_inview = e_canseemon(etmp2); if (!automiss(etmp2)) { if (e_inview) pline(hit_msgc, "%s blown apart by flying debris.", E_phrase(etmp2, "are")); e_died(etmp2, e_inview ? 3 : 2, CRUSHING, killer_msg(CRUSHING, "an exploding drawbridge")); } /* nothing which is vulnerable can survive this */ } set_entity(x, y, etmp1); if (etmp1->edata) { enum msg_channel hit_msgc; if (is_u(etmp1)) hit_msgc = msgc_fatal_predone; else if (etmp1->emon->mtame && canspotmon(etmp1->emon)) hit_msgc = msgc_petfatal; else hit_msgc = msgc_monneutral; e_inview = e_canseemon(etmp1); if (!e_missed(etmp1, TRUE)) { if (e_inview) { if (!is_u(etmp1) && Hallucination) pline(hit_msgc, "%s into some heavy metal!", E_phrase(etmp1, "get")); else pline(hit_msgc, "%s hit by a huge chunk of metal!", E_phrase(etmp1, "are")); } else { if (!is_u(etmp1) && !is_pool(level, x, y)) You_hear(msgc_levelsound, "a crushing sound."); } e_died(etmp1, e_inview ? 3 : 2, CRUSHING, killer_msg(CRUSHING, "a collapsing drawbridge")); /* if (loc1->typ == MOAT) do_entity(etmp1); */ } if (is_u(etmp1)) spoteffects(FALSE); else if (!DEADMONSTER(etmp1->emon)) minliquid(etmp1->emon); } }