Пример #1
0
static void
do_entity(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;

    /* TODO: Long worms? */
    e_inview = e_canseemon(etmp);
    oldx = etmp->ex;
    oldy = etmp->ey;
    at_portcullis = is_db_wall(oldx, oldy);
    crm = &level->locations[oldx][oldy];

    if (automiss(etmp) && e_survives_at(etmp, oldx, oldy)) {
        if (e_inview && (at_portcullis || IS_DRAWBRIDGE(crm->typ)))
            pline("The %s passes through %s!",
                  at_portcullis ? "portcullis" : "drawbridge", e_nam(etmp));
        if (is_u(etmp))
            spoteffects(FALSE);
        return;
    }
    if (e_missed(etmp, FALSE)) {
        if (at_portcullis)
            pline("The portcullis misses %s!", e_nam(etmp));
        if (e_survives_at(etmp, oldx, oldy))
            return;
        else {
            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,
                   killer_msg(CRUSHING, "a falling drawbridge"));  /* 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;
            } else {
                if (e_inview)
                    pline("%s crushed by the falling portcullis!",
                          E_phrase(etmp, "are"));
                else
                    You_hear("a crushing sound.");
                e_died(etmp, e_inview ? 3 : 2, CRUSHING,
                       killer_msg(CRUSHING, "a falling portcullis"));
                /* no corpse */
                return;
            }
        } else {        /* tries to jump off bridge to original square */
            relocates = !e_jumps(etmp);
        }
    }

/*
 * 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.
 */
    newx = oldx;
    newy = oldy;
    find_drawbridge(&newx, &newy);
    if ((newx == oldx) && (newy == oldy))
        get_wall_for_db(&newx, &newy);
    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);
        if (e_survives_at(other, newx, newy) && automiss(other)) {
            relocates = FALSE;  /* "other" won't budge */
        } else {

            while ((e_at(newx, newy) != 0) && (e_at(newx, newy) != etmp))
                do_entity(other);
            if (e_at(oldx, oldy) != etmp) {
                return;
            }
        }
    }
    if (relocates && !e_at(newx, newy)) {       /* if e_at() entity = worm tail 
                                                 */
        if (!is_u(etmp)) {
            remove_monster(level, etmp->ex, etmp->ey);
            place_monster(etmp->emon, newx, newy);
            update_monster_region(etmp->emon);
        } else {
            u.ux = newx;
            u.uy = newy;
        }
        etmp->ex = newx;
        etmp->ey = newy;
        e_inview = e_canseemon(etmp);
    }
    if (is_db_wall(etmp->ex, etmp->ey)) {
        if (e_inview) {
            if (is_u(etmp)) {
                pline("You tumble towards the closed portcullis!");
                if (automiss(etmp))
                    pline("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)) {
            e_died(etmp, 0, CRUSHING,
                   killer_msg(CRUSHING, "a closing drawbridge"));
            return;
        }
    } else {
        if (is_pool(level, etmp->ex, etmp->ey) && !e_inview)
            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;
        }
        if (is_pool(level, etmp->ex, etmp->ey) ||
            is_lava(level, etmp->ex, etmp->ey))
            if (e_inview && !is_u(etmp)) {
                /* drown() will supply msgs if nec. */
                boolean lava = is_lava(level, etmp->ex, etmp->ey);

                if (Hallucination)
                    pline("%s the %s and disappears.", E_phrase(etmp, "drink"),
                          lava ? "lava" : waterbody_name(etmp->ex, etmp->ey));
                else
                    pline("%s into the %s.", E_phrase(etmp, "fall"),
                          lava ? "lava" : waterbody_name(etmp->ex, etmp->ey));
            }
        e_died(etmp, e_inview ? 3 : 2,  /* CRUSHING is arbitrary */
               (is_pool(level, etmp->ex, etmp->ey)) ? DROWNING :
               (is_lava(level, etmp->ex, etmp->ey)) ? BURNING :
               CRUSHING, "fell from a drawbridge");    /* no corpse */
        return;
    }
}
Пример #2
0
/*
 * 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);
    }
}
Пример #3
0
/*
 * 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("The portcullis of the drawbridge falls into the %s!",
                      lava ? "lava" : waterbody_name(x2, y2));
            else if (flags.soundok)
                You_hear("a loud *SPLASH*!");
        } else {
            if (cansee(x, y))
                pline("The drawbridge collapses into the %s!",
                      lava ? "lava" : waterbody_name(x, y));
            else if (flags.soundok)
                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);
    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"));
            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)) {
            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); */
        }
        if (is_u(etmp1))
            spoteffects(FALSE);
        else if (!DEADMONSTER(etmp1->emon))
            minliquid(etmp1->emon);
    }
}