home *** CD-ROM | disk | FTP | other *** search
- /* SCCS Id: @(#)dbridge.c 3.1 92/10/24 */
- /* Copyright (c) 1989 by Jean-Christophe Collet */
- /* NetHack may be freely redistributed. See license for details. */
-
- /*
- * This file contains the drawbridge manipulation (create, open, close,
- * destroy).
- *
- * Added comprehensive monster-handling, and the "entity" structure to
- * deal with players as well. - 11/89
- */
-
- #include "hack.h"
-
- #ifdef OVLB
- static void FDECL(get_wall_for_db, (int *, int *));
- static struct entity *FDECL(e_at, (int, int));
- static void FDECL(m_to_e, (struct monst *, XCHAR_P, XCHAR_P, struct entity *));
- static void FDECL(u_to_e, (struct entity *));
- static void FDECL(set_entity, (int, int, struct entity *));
- static char *FDECL(e_nam, (struct entity *));
- #ifdef D_DEBUG
- static char *FDECL(Enam, (struct entity *)); /* unused */
- #endif
- static char *FDECL(E_phrase, (struct entity *, const char *));
- static boolean FDECL(e_survives_at, (struct entity *, int, int));
- static void FDECL(e_died, (struct entity *, int, int));
- static boolean FDECL(automiss, (struct entity *));
- static boolean FDECL(e_missed, (struct entity *, BOOLEAN_P));
- static boolean FDECL(e_jumps, (struct entity *));
- static void FDECL(do_entity, (struct entity *));
- #endif /* OVLB */
-
- #ifdef OVL0
-
- boolean
- is_pool(x,y)
- int x,y;
- {
- register schar ltyp = levl[x][y].typ;
- if(ltyp == POOL || ltyp == MOAT || ltyp == WATER) return TRUE;
- if(ltyp == DRAWBRIDGE_UP &&
- (levl[x][y].drawbridgemask & DB_UNDER) == DB_MOAT) return TRUE;
- return FALSE;
- }
-
- boolean
- is_lava(x,y)
- int x,y;
- {
- register schar ltyp = levl[x][y].typ;
- if(ltyp == LAVAPOOL ||
- (ltyp == DRAWBRIDGE_UP &&
- (levl[x][y].drawbridgemask & DB_UNDER) == DB_LAVA)) return TRUE;
- return FALSE;
- }
-
- boolean
- is_ice(x,y)
- int x,y;
- {
- register schar ltyp = levl[x][y].typ;
- if (ltyp == ICE ||
- (ltyp == DRAWBRIDGE_UP &&
- (levl[x][y].drawbridgemask & DB_UNDER) == DB_ICE)) return TRUE;
- return FALSE;
- }
-
- #endif /* OVL0 */
-
- #ifdef OVL1
-
- /*
- * We want to know whether a wall (or a door) is the portcullis (passageway)
- * of an eventual drawbridge.
- *
- * Return value: the direction of the drawbridge.
- */
-
- int
- is_drawbridge_wall(x,y)
- int x,y;
- {
- struct rm *lev;
-
- lev = &levl[x][y];
- if (lev->typ != DOOR && lev->typ != DBWALL)
- return (-1);
-
- if (IS_DRAWBRIDGE(levl[x+1][y].typ) &&
- (levl[x+1][y].drawbridgemask & DB_DIR) == DB_WEST)
- return (DB_WEST);
- if (IS_DRAWBRIDGE(levl[x-1][y].typ) &&
- (levl[x-1][y].drawbridgemask & DB_DIR) == DB_EAST)
- return (DB_EAST);
- if (IS_DRAWBRIDGE(levl[x][y-1].typ) &&
- (levl[x][y-1].drawbridgemask & DB_DIR) == DB_SOUTH)
- return (DB_SOUTH);
- if (IS_DRAWBRIDGE(levl[x][y+1].typ) &&
- (levl[x][y+1].drawbridgemask & DB_DIR) == DB_NORTH)
- return (DB_NORTH);
-
- return (-1);
- }
-
- /*
- * Use is_db_wall where you want to verify that a
- * drawbridge "wall" is UP in the location x, y
- * (instead of UP or DOWN, as with is_drawbridge_wall).
- */
- boolean
- is_db_wall(x,y)
- int x,y;
- {
- return( levl[x][y].typ == DBWALL );
- }
-
-
- /*
- * Return true with x,y pointing to the drawbridge if x,y initially indicate
- * a drawbridge or drawbridge wall.
- */
- boolean
- find_drawbridge(x,y)
- int *x,*y;
- {
- int dir;
-
- if (IS_DRAWBRIDGE(levl[*x][*y].typ))
- return TRUE;
- dir = is_drawbridge_wall(*x,*y);
- if (dir >= 0) {
- switch(dir) {
- case DB_NORTH: (*y)++; break;
- case DB_SOUTH: (*y)--; break;
- case DB_EAST: (*x)--; break;
- case DB_WEST: (*x)++; break;
- }
- return TRUE;
- }
- return FALSE;
- }
-
- #endif /* OVL1 */
- #ifdef OVLB
-
- /*
- * Find the drawbridge wall associated with a drawbridge.
- */
- static void
- get_wall_for_db(x,y)
- int *x,*y;
- {
- switch (levl[*x][*y].drawbridgemask & DB_DIR) {
- case DB_NORTH: (*y)--; break;
- case DB_SOUTH: (*y)++; break;
- case DB_EAST: (*x)++; break;
- case DB_WEST: (*x)--; break;
- }
- }
-
- /*
- * Creation of a drawbridge at pos x,y.
- * dir is the direction.
- * flag must be put to TRUE if we want the drawbridge to be opened.
- */
-
- boolean
- create_drawbridge(x,y,dir,flag)
- int x,y,dir;
- boolean flag;
- {
- int x2,y2;
- boolean horiz;
- boolean lava = levl[x][y].typ == LAVAPOOL; /* assume initialized map */
-
- x2 = x; y2 = y;
- switch(dir) {
- case DB_NORTH:
- horiz = TRUE;
- y2--;
- break;
- case DB_SOUTH:
- horiz = TRUE;
- y2++;
- break;
- case DB_EAST:
- horiz = FALSE;
- x2++;
- break;
- default:
- impossible("bad direction in create_drawbridge");
- /* fall through */
- case DB_WEST:
- horiz = FALSE;
- x2--;
- break;
- }
- if (!IS_WALL(levl[x2][y2].typ))
- return(FALSE);
- if (flag) { /* We want the bridge open */
- levl[x][y].typ = DRAWBRIDGE_DOWN;
- levl[x2][y2].typ = DOOR;
- levl[x2][y2].doormask = D_NODOOR;
- } else {
- levl[x][y].typ = DRAWBRIDGE_UP;
- levl[x2][y2].typ = DBWALL;
- /* Drawbridges are non-diggable. */
- levl[x2][y2].diggable = W_NONDIGGABLE;
- }
- levl[x][y].horizontal = !horiz;
- levl[x2][y2].horizontal = horiz;
- levl[x][y].drawbridgemask = dir;
- if(lava) levl[x][y].drawbridgemask |= DB_LAVA;
- return(TRUE);
- }
-
- struct entity {
- struct monst *emon; /* youmonst for the player */
- struct permonst *edata; /* must be non-zero for record to be valid */
- int ex, ey;
- };
-
- #define ENTITIES 2
-
- static struct entity NEARDATA occupants[ENTITIES];
-
- static
- struct entity *
- e_at(x, y)
- int x, y;
- {
- int entitycnt;
-
- for (entitycnt = 0; entitycnt < ENTITIES; entitycnt++)
- if ((occupants[entitycnt].edata) &&
- (occupants[entitycnt].ex == x) &&
- (occupants[entitycnt].ey == y))
- break;
- #ifdef D_DEBUG
- pline("entitycnt = %d", entitycnt);
- wait_synch();
- #endif
- return((entitycnt == ENTITIES)?
- (struct entity *)0 : &(occupants[entitycnt]));
- }
-
- static void
- m_to_e(mtmp, x, y, etmp)
- struct monst *mtmp;
- xchar x, y;
- struct entity *etmp;
- {
- etmp->emon = mtmp;
- if (mtmp) {
- etmp->ex = x;
- etmp->ey = y;
- if (mtmp->wormno && (x != mtmp->mx || y != mtmp->my))
- etmp->edata = &mons[PM_LONG_WORM_TAIL];
- else
- etmp->edata = mtmp->data;
- } else
- etmp->edata = (struct permonst *)0;
- }
-
- static void
- u_to_e(etmp)
- struct entity *etmp;
- {
- etmp->emon = &youmonst;
- etmp->ex = u.ux;
- etmp->ey = u.uy;
- etmp->edata = uasmon;
- }
-
- static void
- set_entity(x, y, etmp)
- int x, y;
- struct entity *etmp;
- {
- if ((x == u.ux) && (y == u.uy))
- u_to_e(etmp);
- else
- if (MON_AT(x, y))
- m_to_e(m_at(x, y), x, y, etmp);
- else
- etmp->edata = (struct permonst *)0;
- }
-
- #define is_u(etmp) (etmp->emon == &youmonst)
- #define e_canseemon(etmp) (is_u(etmp) ? (boolean)TRUE : canseemon(etmp->emon))
-
- /*
- * e_strg is a utility routine which is not actually in use anywhere, since
- * the specialized routines below suffice for all current purposes.
- */
-
- /* #define e_strg(etmp, func) (is_u(etmp)? (char *)0 : func(etmp->emon)) */
-
- static char *
- e_nam(etmp)
- struct entity *etmp;
- {
- return(is_u(etmp)? "you" : mon_nam(etmp->emon));
- }
-
- #ifdef D_DEBUG
- /*
- * Enam is another unused utility routine: E_phrase is preferable.
- */
-
- static char *
- Enam(etmp)
- struct entity *etmp;
- {
- return(is_u(etmp)? "You" : Monnam(etmp->emon));
- }
- #endif /* D_DEBUG */
-
- /*
- * Generates capitalized entity name, makes 2nd -> 3rd person conversion on
- * verb, where necessary.
- */
-
- static char *
- E_phrase(etmp, verb)
- struct entity *etmp;
- const char *verb;
- {
- static char wholebuf[80];
- char verbbuf[30];
-
- if (is_u(etmp))
- Strcpy(wholebuf, "You");
- else
- Strcpy(wholebuf, Monnam(etmp->emon));
- if (!*verb)
- return(wholebuf);
- Strcat(wholebuf, " ");
- verbbuf[0] = '\0';
- if (is_u(etmp))
- Strcpy(verbbuf, verb);
- else {
- if (!strcmp(verb, "are"))
- Strcpy(verbbuf, "is");
- if (!strcmp(verb, "have"))
- Strcpy(verbbuf, "has");
- if (!verbbuf[0]) {
- Strcpy(verbbuf, verb);
- switch (verbbuf[strlen(verbbuf) - 1]) {
- case 'y':
- verbbuf[strlen(verbbuf) - 1] = '\0';
- Strcat(verbbuf, "ies");
- break;
- case 'h':
- case 'o':
- case 's':
- Strcat(verbbuf, "es");
- break;
- default:
- Strcat(verbbuf, "s");
- break;
- }
- }
- }
- Strcat(wholebuf, verbbuf);
- return(wholebuf);
- }
-
- /*
- * Simple-minded "can it be here?" routine
- */
-
- static boolean
- e_survives_at(etmp, x, y)
- struct entity *etmp;
- int x, y;
- {
- if (noncorporeal(etmp->edata))
- return(TRUE);
- if (is_pool(x, y))
- return((is_u(etmp) && (Wwalking || Magical_breathing || Levitation)) ||
- is_swimmer(etmp->edata) || is_flyer(etmp->edata) ||
- is_floater(etmp->edata));
- /* must force call to lava_effects in e_died if is_u */
- if (is_lava(x, y))
- return(is_u(etmp) ? !!Levitation : resists_fire(etmp->edata));
- if (is_db_wall(x, y))
- return(passes_walls(etmp->edata));
- return(TRUE);
- }
-
- static void
- e_died(etmp, dest, how)
- struct entity *etmp;
- int dest, how;
- {
- if (is_u(etmp)) {
- if (how == DROWNING)
- (void) drown();
- if (how == BURNING)
- (void) lava_effects();
- else {
- coord xy;
-
- killer_format = KILLED_BY_AN;
- killer = "falling drawbridge";
- done(how);
- /* So, you didn't die */
- if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
- if (enexto(&xy, etmp->ex, etmp->ey,
- etmp->edata)) {
- pline("A %s force teleports you away...",
- Hallucination ? "normal" : "strange");
- teleds(xy.x, xy.y);
- }
- /* otherwise on top of the drawbridge is the
- * only viable spot in the dungeon, so stay there
- */
- }
- }
- } else {
- xkilled(etmp->emon, dest);
- etmp->edata = (struct permonst *)0;
- }
- }
-
-
- /*
- * These are never directly affected by a bridge or portcullis.
- */
-
- static boolean
- automiss(etmp)
- struct entity *etmp;
- {
- return(passes_walls(etmp->edata) || noncorporeal(etmp->edata));
- }
-
- /*
- * Does falling drawbridge or portcullis miss etmp?
- */
-
- static boolean
- e_missed(etmp, chunks)
- struct entity *etmp;
- boolean chunks;
- {
- int misses;
-
- #ifdef D_DEBUG
- if (chunks)
- pline("Do chunks miss?");
- #endif
- if (automiss(etmp))
- return(TRUE);
-
- if (is_flyer(etmp->edata) &&
- (is_u(etmp)? !Sleeping :
- (etmp->emon->mcanmove && !etmp->emon->msleep)))
- /* flying requires mobility */
- misses = 5; /* out of 8 */
- else
- if (is_floater(etmp->edata) ||
- (is_u(etmp) && Levitation)) /* doesn't require mobility */
- misses = 3;
- else
- if (chunks && is_pool(etmp->ex, etmp->ey))
- misses = 2; /* sitting ducks */
- else
- misses = 0;
-
- if (is_db_wall(etmp->ex, etmp->ey))
- misses -= 3; /* less airspace */
-
- #ifdef D_DEBUG
- pline("Miss chance = %d (out of 8)", misses);
- #endif
-
- return((misses >= rnd(8))? TRUE : FALSE);
- }
-
- /*
- * Can etmp jump from death?
- */
-
- static boolean
- e_jumps(etmp)
- struct entity *etmp;
- {
- int tmp = 4; /* out of 10 */
-
- if (is_u(etmp)? (Sleeping || Fumbling) :
- (!etmp->emon->mcanmove || etmp->emon->msleep ||
- !etmp->edata->mmove || etmp->emon->wormno))
- return(FALSE);
-
- if (is_u(etmp)? Confusion : etmp->emon->mconf)
- tmp -= 2;
-
- if (is_u(etmp)? Stunned : etmp->emon->mstun)
- tmp -= 3;
-
- if (is_db_wall(etmp->ex, etmp->ey))
- tmp -= 2; /* less room to maneuver */
-
- #ifdef D_DEBUG
- pline("%s to jump (%d chances in 10)", E_phrase(etmp, "try"), tmp);
- #endif
- return((tmp >= rnd(10))? TRUE : FALSE);
- }
-
- static void
- do_entity(etmp)
- struct entity *etmp;
- {
- int newx, newy, at_portcullis, oldx, oldy;
- boolean must_jump = FALSE, relocates = FALSE, e_inview;
- struct rm *crm;
-
- if (!etmp->edata)
- return;
-
- e_inview = e_canseemon(etmp);
-
- oldx = etmp->ex;
- oldy = etmp->ey;
-
- at_portcullis = is_db_wall(oldx, oldy);
-
- crm = &levl[oldx][oldy];
-
- if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) {
- char edifice[20];
-
- if (e_inview) {
- *edifice = '\0';
- if ((crm->typ == DRAWBRIDGE_DOWN) ||
- (crm->typ == DRAWBRIDGE_UP))
- Strcpy(edifice, "drawbridge");
- else
- if (at_portcullis)
- Strcpy(edifice, "portcullis");
- if (*edifice)
- pline("The %s passes through %s!", edifice,
- e_nam(etmp));
- }
- return;
- }
- if (e_missed(etmp, FALSE)) {
- if (at_portcullis)
- pline("The portcullis misses %s!",
- e_nam(etmp));
- #ifdef D_DEBUG
- else
- pline("The drawbridge misses %s!",
- e_nam(etmp));
- #endif
- if (e_survives_at(etmp, oldx, oldy))
- return;
- else {
- #ifdef D_DEBUG
- pline("Mon can't survive here");
- #endif
- if (at_portcullis)
- must_jump = TRUE;
- else
- relocates = TRUE; /* just ride drawbridge in */
- }
- } else {
- if (crm->typ == DRAWBRIDGE_DOWN) {
- pline("%s crushed underneath the drawbridge.",
- E_phrase(etmp, "are")); /* no jump */
- e_died(etmp, e_inview? 3 : 2, CRUSHING);/* no corpse */
- return; /* Note: Beyond this point, we know we're */
- } /* not at an opened drawbridge, since all */
- must_jump = TRUE; /* *missable* creatures survive on the */
- } /* square, and all the unmissed ones die. */
- if (must_jump) {
- if (at_portcullis) {
- if (e_jumps(etmp)) {
- relocates = TRUE;
- #ifdef D_DEBUG
- pline("Jump succeeds!");
- #endif
- } else {
- if (e_inview)
- pline("%s crushed by the falling portcullis!",
- E_phrase(etmp, "are"));
- else if (flags.soundok)
- You("hear a crushing sound.");
- e_died(etmp, e_inview? 3 : 2, CRUSHING);
- /* no corpse */
- return;
- }
- } else { /* tries to jump off bridge to original square */
- relocates = !e_jumps(etmp);
- #ifdef D_DEBUG
- pline("Jump %s!", (relocates)? "fails" : "succeeds");
- #endif
- }
- }
-
- /*
- * Here's where we try to do relocation. Assumes that etmp is not arriving
- * at the portcullis square while the drawbridge is falling, since this square
- * would be inaccessible (i.e. etmp started on drawbridge square) or
- * unnecessary (i.e. etmp started here) in such a situation.
- */
- #ifdef D_DEBUG
- pline("Doing relocation.");
- #endif
- newx = oldx;
- newy = oldy;
- (void)find_drawbridge(&newx, &newy);
- if ((newx == oldx) && (newy == oldy))
- get_wall_for_db(&newx, &newy);
- #ifdef D_DEBUG
- pline("Checking new square for occupancy.");
- #endif
- if (relocates && (e_at(newx, newy))) {
-
- /*
- * Standoff problem: one or both entities must die, and/or both switch
- * places. Avoid infinite recursion by checking first whether the other
- * entity is staying put. Clean up if we happen to move/die in recursion.
- */
- struct entity *other;
-
- other = e_at(newx, newy);
- #ifdef D_DEBUG
- pline("New square is occupied by %s", e_nam(other));
- #endif
- if (e_survives_at(other, newx, newy) && automiss(other)) {
- relocates = FALSE; /* "other" won't budge */
- #ifdef D_DEBUG
- pline("%s suicide.", E_phrase(etmp, "commit"));
- #endif
- } else {
-
- #ifdef D_DEBUG
- pline("Handling %s", e_nam(other));
- #endif
- while ((e_at(newx, newy)) &&
- (e_at(newx, newy) != etmp))
- do_entity(other);
- #ifdef D_DEBUG
- pline("Checking existence of %s", e_nam(etmp));
- wait_synch();
- #endif
- if (e_at(oldx, oldy) != etmp) {
- #ifdef D_DEBUG
- pline("%s moved or died in recursion somewhere",
- E_phrase(etmp, "have"));
- wait_synch();
- #endif
- return;
- }
- }
- }
- if (relocates && !e_at(newx, newy)) {/* if e_at() entity = worm tail */
- #ifdef D_DEBUG
- pline("Moving %s", e_nam(etmp));
- #endif
- if (!is_u(etmp)) {
- remove_monster(etmp->ex, etmp->ey);
- place_monster(etmp->emon, newx, newy);
- } else {
- u.ux = newx;
- u.uy = newy;
- }
- etmp->ex = newx;
- etmp->ey = newy;
- e_inview = e_canseemon(etmp);
- }
- #ifdef D_DEBUG
- pline("Final disposition of %s", e_nam(etmp));
- wait_synch();
- #endif
- if (is_db_wall(etmp->ex, etmp->ey)) {
- #ifdef D_DEBUG
- pline("%s in portcullis chamber", E_phrase(etmp, "are"));
- wait_synch();
- #endif
- if (e_inview) {
- if (is_u(etmp)) {
- You("tumble towards the closed portcullis!");
- if (automiss(etmp))
- You("pass through it!");
- else
- pline("The drawbridge closes in...");
- } else
- pline("%s behind the drawbridge.",
- E_phrase(etmp, "disappear"));
- }
- if (!e_survives_at(etmp, etmp->ex, etmp->ey)) {
- killer_format = KILLED_BY_AN;
- killer = "closing drawbridge";
- e_died(etmp, 0, CRUSHING); /* no message */
- return;
- }
- #ifdef D_DEBUG
- pline("%s in here", E_phrase(etmp, "survive"));
- #endif
- } else {
- #ifdef D_DEBUG
- pline("%s on drawbridge square", E_phrase(etmp, "are"));
- #endif
- if (is_pool(etmp->ex, etmp->ey) && !e_inview)
- if (flags.soundok)
- You("hear a splash.");
- if (e_survives_at(etmp, etmp->ex, etmp->ey)) {
- if (e_inview && !is_flyer(etmp->edata) &&
- !is_floater(etmp->edata))
- pline("%s from the bridge.",
- E_phrase(etmp, "fall"));
- return;
- }
- #ifdef D_DEBUG
- pline("%s cannot survive on the drawbridge square",Enam(etmp));
- #endif
- if (is_pool(etmp->ex, etmp->ey) || is_lava(etmp->ex, etmp->ey))
- if (e_inview && !is_u(etmp)) {
- /* drown() will supply msgs if nec. */
- boolean lava = is_lava(etmp->ex, etmp->ey);
-
- if (Hallucination)
- pline("%s the %s and disappears.",
- E_phrase(etmp, "drink"),
- lava ? "lava" : "moat");
- else
- pline("%s into the %s.",
- E_phrase(etmp, "fall"),
- lava ? "lava" : "moat");
- }
- killer_format = NO_KILLER_PREFIX;
- killer = "fell from a drawbridge";
- e_died(etmp, e_inview ? 3 : 2, /* CRUSHING is arbitrary */
- (is_pool(etmp->ex, etmp->ey)) ? DROWNING :
- (is_lava(etmp->ex, etmp->ey)) ? BURNING :
- CRUSHING); /*no corpse*/
- return;
- }
- }
-
- /*
- * Close the drawbridge located at x,y
- */
-
- void
- close_drawbridge(x,y)
- int x,y;
- {
- register struct rm *lev1, *lev2;
- int x2, y2;
-
- lev1 = &levl[x][y];
- if (lev1->typ != DRAWBRIDGE_DOWN) return;
- x2 = x; y2 = y;
- get_wall_for_db(&x2,&y2);
- if (cansee(x,y)) /* change msgs if you are a w-walker at portcullis */
- You("see a drawbridge %s up!",
- ((u.ux == x2) && (u.uy == y2))? "coming" : "going");
- lev1->typ = DRAWBRIDGE_UP;
- lev2 = &levl[x2][y2];
- lev2->typ = DBWALL;
- switch (lev1->drawbridgemask & DB_DIR) {
- case DB_NORTH:
- case DB_SOUTH:
- lev2->horizontal = TRUE;
- break;
- case DB_WEST:
- case DB_EAST:
- lev2->horizontal = FALSE;
- break;
- }
- lev2->diggable = 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.");
- (void) revive_nasty(x,y,NULL);
- (void) revive_nasty(x2,y2,NULL);
- delallobj(x, y);
- newsym(x, y);
- delallobj(x2, y2);
- newsym(x2, y2);
- block_point(x2,y2); /* vision */
- }
-
- /*
- * Open the drawbridge located at x,y
- */
-
- void
- open_drawbridge(x,y)
- int x,y;
- {
- register struct rm *lev1, *lev2;
- int x2, y2;
-
- lev1 = &levl[x][y];
- if (lev1->typ != DRAWBRIDGE_UP) return;
- x2 = x; y2 = y;
- get_wall_for_db(&x2,&y2);
- if (cansee(x,y)) /* change msgs if you are a w-walker at portcullis */
- You("see a drawbridge %s down!",
- ((x2 == u.ux) && (y2 == u.uy))? "going" : "coming");
- lev1->typ = DRAWBRIDGE_DOWN;
- lev2 = &levl[x2][y2];
- lev2->typ = DOOR;
- lev2->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]));
- spoteffects(); /* if underwater, hero is now on solid ground */
- (void) revive_nasty(x,y,NULL);
- delallobj(x, y);
- newsym(x, y);
- newsym(x2, y2);
- unblock_point(x2,y2); /* vision */
- if (Is_stronghold(&u.uz)) u.uevent.uopened_dbridge = TRUE;
- }
-
- /*
- * Let's destroy the drawbridge located at x,y
- */
-
- void
- destroy_drawbridge(x,y)
- int x,y;
- {
- register struct rm *lev1, *lev2;
- int x2, y2;
- boolean e_inview;
- struct entity *etmp1 = &(occupants[0]), *etmp2 = &(occupants[1]);
-
- lev1 = &levl[x][y];
- if (!IS_DRAWBRIDGE(lev1->typ))
- return;
- x2 = x; y2 = y;
- get_wall_for_db(&x2,&y2);
- lev2 = &levl[x2][y2];
- if ((lev1->drawbridgemask & DB_UNDER) == DB_MOAT ||
- (lev1->drawbridgemask & DB_UNDER) == DB_LAVA) {
- struct obj *otmp;
- boolean lava = (lev1->drawbridgemask & DB_UNDER) == DB_LAVA;
- if (lev1->typ == DRAWBRIDGE_UP) {
- if (cansee(x2,y2))
- pline("The portcullis of the drawbridge falls into the %s!",
- lava ? "lava" : "moat");
- else if (flags.soundok)
- You("hear a loud *SPLASH*!");
- } else {
- if (cansee(x,y))
- pline("The drawbridge collapses into the %s!",
- lava ? "lava" : "moat");
- else if (flags.soundok)
- You("hear a loud *SPLASH*!");
- }
- lev1->typ = lava ? LAVAPOOL : MOAT;
- lev1->drawbridgemask = 0;
- if(otmp = sobj_at(BOULDER,x,y)) {
- freeobj(otmp);
- (void) flooreffects(otmp,x,y,"fall");
- }
- } else {
- if (cansee(x,y))
- pline("The drawbridge disintegrates!");
- else
- You("hear a loud *CRASH*!");
- lev1->typ =
- ((lev1->drawbridgemask & DB_ICE) ? ICE : ROOM);
- lev1->icedpool =
- ((lev1->drawbridgemask & DB_ICE) ? ICED_MOAT : 0);
- }
- wake_nearby();
- lev2->typ = DOOR;
- lev2->doormask = D_NODOOR;
- newsym(x,y);
- newsym(x2,y2);
- if (!does_block(x2,y2,lev2)) 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"));
- 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(etmp1);
- if (e_missed(etmp1, TRUE)) {
- #ifdef D_DEBUG
- pline("%s spared!", E_phrase(etmp1, "are"));
- #endif
- } else {
- 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(x,y))
- You("hear a crushing sound");
- #ifdef D_DEBUG
- else
- pline("%s from shrapnel",
- E_phrase(etmp1, "die"));
- #endif
- }
- killer_format = KILLED_BY_AN;
- killer = "collapsing drawbridge";
- e_died(etmp1, e_inview? 3 : 2, CRUSHING); /*no corpse*/
- if(lev1->typ == MOAT) do_entity(etmp1);
- }
- }
- }
-
-
- #endif /* OVLB */
-
- /*dbridge.c*/
-