int dospinweb(void) { struct trap *ttmp = t_at(level, u.ux, u.uy); if (Levitation || Is_airlevel(&u.uz) || Underwater || Is_waterlevel(&u.uz)) { pline("You must be on the ground to spin a web."); return 0; } if (u.uswallow) { pline("You release web fluid inside %s.", mon_nam(u.ustuck)); if (is_animal(u.ustuck->data)) { expels(u.ustuck, u.ustuck->data, TRUE); return 0; } if (is_whirly(u.ustuck->data)) { int i; for (i = 0; i < NATTK; i++) if (u.ustuck->data->mattk[i].aatyp == AT_ENGL) break; if (i == NATTK) impossible("Swallower has no engulfing attack?"); else { char sweep[30]; sweep[0] = '\0'; switch(u.ustuck->data->mattk[i].adtyp) { case AD_FIRE: strcpy(sweep, "ignites and "); break; case AD_ELEC: strcpy(sweep, "fries and "); break; case AD_COLD: strcpy(sweep, "freezes, shatters and "); break; } pline("The web %sis swept away!", sweep); } return 0; } /* default: a nasty jelly-like creature */ pline("The web dissolves into %s.", mon_nam(u.ustuck)); return 0; } if (u.utrap) { pline("You cannot spin webs while stuck in a trap."); return 0; } exercise(A_DEX, TRUE); if (ttmp) switch (ttmp->ttyp) { case PIT: case SPIKED_PIT: pline("You spin a web, covering up the pit."); deltrap(ttmp); bury_objs(u.ux, u.uy); newsym(u.ux, u.uy); return 1; case SQKY_BOARD: pline("The squeaky board is muffled."); deltrap(ttmp); newsym(u.ux, u.uy); return 1; case TELEP_TRAP: case LEVEL_TELEP: case MAGIC_PORTAL: case VIBRATING_SQUARE: pline("Your webbing vanishes!"); return 0; case WEB: pline("You make the web thicker."); return 1; case HOLE: case TRAPDOOR: pline("You web over the %s.", (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole"); deltrap(ttmp); newsym(u.ux, u.uy); return 1; case ROLLING_BOULDER_TRAP: pline("You spin a web, jamming the trigger."); deltrap(ttmp); newsym(u.ux, u.uy); return 1; case ARROW_TRAP: case DART_TRAP: case BEAR_TRAP: case ROCKTRAP: case FIRE_TRAP: case LANDMINE: case SLP_GAS_TRAP: case RUST_TRAP: case MAGIC_TRAP: case ANTI_MAGIC: case POLY_TRAP: pline("You have triggered a trap!"); dotrap(ttmp, 0); return 1; default: impossible("Webbing over trap type %d?", ttmp->ttyp); return 0; } else if (On_stairs(u.ux, u.uy)) { /* cop out: don't let them hide the stairs */ pline("Your web fails to impede access to the %s.", (level->locations[u.ux][u.uy].typ == STAIRS) ? "stairs" : "ladder"); return 1; } ttmp = maketrap(level, u.ux, u.uy, WEB); if (ttmp) { ttmp->tseen = 1; ttmp->madeby_u = 1; } newsym(u.ux, u.uy); return 1; }
struct monst * tamedog(struct monst *mtmp, struct obj *obj) { struct monst *mtmp2; /* The Wiz, Medusa and the quest nemeses aren't even made peaceful. */ if (mtmp->iswiz || mtmp->data == &mons[PM_MEDUSA] || (mtmp->data->mflags3 & M3_WANTSARTI)) return NULL; /* worst case, at least it'll be peaceful; this uses the main RNG because realtime effects means that this won't really sync anyway; this also calls set_malign (thus there's no need for the caller to call it after calling tamedog()) */ msethostility(mtmp, FALSE, TRUE); if (flags.moonphase == FULL_MOON && night() && rn2(6) && obj && mtmp->data->mlet == S_DOG) return NULL; /* If we cannot tame it, at least it's no longer afraid. */ mtmp->mflee = 0; mtmp->mfleetim = 0; /* make grabber let go now, whether it becomes tame or not */ if (mtmp == u.ustuck) { if (Engulfed) expels(mtmp, mtmp->data, TRUE); else if (!(Upolyd && sticks(youmonst.data))) unstuck(mtmp); } /* feeding it treats makes it tamer */ if (mtmp->mtame && obj) { int tasty; if (mtmp->mcanmove && !mtmp->mconf && !mtmp->meating && ((tasty = dogfood(mtmp, obj)) == DOGFOOD || (tasty <= ACCFOOD && CONST_EDOG(mtmp)->hungrytime <= moves))) { /* pet will "catch" and eat this thrown food */ if (canseemon(mtmp)) { boolean big_corpse = (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM && mons[obj->corpsenm].msize > mtmp->data->msize); pline("%s catches %s%s", Monnam(mtmp), the(xname(obj)), !big_corpse ? "." : ", or vice versa!"); } else if (cansee(mtmp->mx, mtmp->my)) pline("%s.", Tobjnam(obj, "stop")); /* dog_eat expects a floor object */ place_object(obj, level, mtmp->mx, mtmp->my); dog_eat(mtmp, obj, mtmp->mx, mtmp->my, FALSE); /* eating might have killed it, but that doesn't matter here; a non-null result suppresses "miss" message for thrown food and also implies that the object has been deleted */ return mtmp; } else return NULL; } if (mtmp->mtame || !mtmp->mcanmove || /* monsters with conflicting structures cannot be tamed */ mtmp->isshk || mtmp->isgd || mtmp->ispriest || mtmp->isminion || is_covetous(mtmp->data) || is_human(mtmp->data) || (is_demon(mtmp->data) && !is_demon(youmonst.data)) || (obj && dogfood(mtmp, obj) >= MANFOOD)) return NULL; if (mtmp->m_id == u.quest_status.leader_m_id) return NULL; /* make a new monster which has the pet extension */ mtmp2 = newmonst(MX_EDOG, mtmp->mnamelth); *mtmp2 = *mtmp; mtmp2->mxtyp = MX_EDOG; mtmp2->mxlth = sizeof (struct edog); if (mtmp->mnamelth) strcpy(NAME_MUTABLE(mtmp2), NAME(mtmp)); initedog(mtmp2); replmon(mtmp, mtmp2); /* `mtmp' is now obsolete */ if (obj) { /* thrown food */ /* defer eating until the edog extension has been set up */ place_object(obj, level, mtmp2->mx, mtmp2->my); /* put on floor */ /* devour the food (might grow into larger, genocided monster) */ if (dog_eat(mtmp2, obj, mtmp2->mx, mtmp2->my, TRUE) == 2) return mtmp2; /* oops, it died... */ /* `obj' is now obsolete */ } if (mtmp2->dlevel == level) newsym(mtmp2->mx, mtmp2->my); if (attacktype(mtmp2->data, AT_WEAP)) { mtmp2->weapon_check = NEED_HTH_WEAPON; mon_wield_item(mtmp2); } return mtmp2; }