/* * 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); } }
/* * 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); } }
struct monst * make_familiar(struct obj *otmp, xchar x, xchar y, boolean quietly) { const struct permonst *pm; struct monst *mtmp = 0; int chance, trycnt = 100; do { if (otmp) { /* figurine; otherwise spell */ int mndx = otmp->corpsenm; pm = &mons[mndx]; /* activating a figurine provides one way to exceed the maximum number of the target critter created--unless it has a special limit (erinys, Nazgul) */ if ((mvitals[mndx].mvflags & G_EXTINCT) && mbirth_limit(mndx) != MAXMONNO) { if (!quietly) /* have just been given "You <do something with> the figurine and it transforms." message */ pline("... into a pile of dust."); break; /* mtmp is null */ } } else if (!rn2(3)) { pm = &mons[pet_type(NULL)]; } else { pm = rndmonst(&u.uz, rng_t_create_monster); if (!pm) { if (!quietly) pline ("There seems to be nothing available for a familiar."); break; } } mtmp = makemon(pm, level, x, y, MM_EDOG | MM_IGNOREWATER | (otmp ? 0 : (MM_CREATEMONSTER | MM_CMONSTER_T))); if (otmp && !mtmp) { /* monster was genocided or square occupied */ if (!quietly) pline("The figurine writhes and then shatters into pieces!"); break; } } while (!mtmp && --trycnt > 0); if (!mtmp) return NULL; if (is_pool(level, mtmp->mx, mtmp->my) && minliquid(mtmp)) return NULL; initedog(mtmp); mtmp->msleeping = 0; if (otmp) { /* figurine; resulting monster might not become a pet */ chance = rn2_on_rng(10, rng_figurine_effect); /* 0: tame, 1: peaceful, 2: hostile, 3+: matching BCU; this gives an 80% chance of the desired effect, 10% of each other effect */ if (chance > 2) chance = otmp->blessed ? 0 : !otmp->cursed ? 1 : 2; if (chance > 0) { mtmp->mtame = 0; /* not tame after all */ if (chance == 2) { /* hostile (cursed figurine) */ if (!quietly) pline("You get a bad feeling about this."); msethostility(mtmp, TRUE, TRUE); } } /* if figurine has been named, give same name to the monster */ if (otmp->onamelth) mtmp = christen_monst(mtmp, ONAME(otmp)); } set_malign(mtmp); /* more alignment changes */ newsym(mtmp->mx, mtmp->my); /* must wield weapon immediately since pets will otherwise drop it */ if (mtmp->mtame && attacktype(mtmp->data, AT_WEAP)) { mtmp->weapon_check = NEED_HTH_WEAPON; mon_wield_item(mtmp); } return mtmp; }