E long FDECL(peek_at_iced_corpse_age, (struct obj *));
E int FDECL(hornoplenty, (struct obj *,BOOLEAN_P));
E void NDECL(obj_sanity_check);
+E struct obj* FDECL(obj_nexto, (struct obj*));
+E struct obj* FDECL(obj_nexto_xy, (int, int, int, int));
+E struct obj* FDECL(obj_meld, (struct obj**, struct obj**));
/* ### mkroom.c ### */
Bitfield(recharged,3); /* number of times it's been recharged */
#define on_ice recharged /* corpse on ice */
Bitfield(lamplit,1); /* a light-source -- can be lit */
- Bitfield(oglobby,1); /* globby; will combine with like types on adjacent squares */
+ Bitfield(globby,1); /* globby; will combine with like types on adjacent squares */
Bitfield(greased,1); /* covered with grease */
Bitfield(nomerge,1); /* set temporarily to prevent merging */
Bitfield(was_thrown,1); /* thrown by hero since last picked up */
extern int n_dgns; /* number of dungeons, from dungeon.c */
static NEARDATA const char drop_types[] =
- { ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, 0 };
+ { ALLOW_COUNT, COIN_CLASS, ALL_CLASSES, 0 };
/* 'd' command: drop one inventory item */
int
dodrop()
{
- int result, i = (invent) ? 0 : (SIZE(drop_types) - 1);
+ int result, i = (invent) ? 0 : (SIZE(drop_types) - 1);
- if (*u.ushops) sellobj_state(SELL_DELIBERATE);
- result = drop(getobj(&drop_types[i], "drop"));
- if (*u.ushops) sellobj_state(SELL_NORMAL);
- reset_occupations();
+ if (*u.ushops) sellobj_state(SELL_DELIBERATE);
+ result = drop(getobj(&drop_types[i], "drop"));
+ if (*u.ushops) sellobj_state(SELL_NORMAL);
+ reset_occupations();
- return result;
+ return result;
}
/* Called when a boulder is dropped, thrown, or pushed. If it ends up
register int rx, ry;
boolean pushing;
{
- if (!otmp || otmp->otyp != BOULDER)
- impossible("Not a boulder?");
- else if (!Is_waterlevel(&u.uz) && is_pool_or_lava(rx,ry)) {
- boolean lava = is_lava(rx,ry), fills_up;
- const char *what = waterbody_name(rx,ry);
- schar ltyp = levl[rx][ry].typ;
- int chance = rn2(10); /* water: 90%; lava: 10% */
- fills_up = lava ? chance == 0 : chance != 0;
-
- if (fills_up) {
- struct trap *ttmp = t_at(rx, ry);
-
- if (ltyp == DRAWBRIDGE_UP) {
- levl[rx][ry].drawbridgemask &= ~DB_UNDER; /* clear lava */
- levl[rx][ry].drawbridgemask |= DB_FLOOR;
- } else
- levl[rx][ry].typ = ROOM;
-
- if (ttmp) (void) delfloortrap(ttmp);
- bury_objs(rx, ry);
-
- newsym(rx,ry);
- if (pushing) {
- char whobuf[BUFSZ];
-
- Strcpy(whobuf, "you");
- if (u.usteed) Strcpy(whobuf, y_monnam(u.usteed));
- pline("%s %s %s into the %s.", upstart(whobuf),
- vtense(whobuf, "push"), the(xname(otmp)), what);
- if (flags.verbose && !Blind)
- pline("Now you can cross it!");
- /* no splashing in this case */
- }
- }
- if (!fills_up || !pushing) { /* splashing occurs */
- if (!u.uinwater) {
- if (pushing ? !Blind : cansee(rx,ry)) {
- There("is a large splash as %s %s the %s.",
- the(xname(otmp)), fills_up? "fills":"falls into",
- what);
- } else if (!Deaf)
- You_hear("a%s splash.", lava ? " sizzling" : "");
- wake_nearto(rx, ry, 40);
- }
-
- if (fills_up && u.uinwater && distu(rx,ry) == 0) {
- u.uinwater = 0;
- docrt();
- vision_full_recalc = 1;
- You("find yourself on dry land again!");
- } else if (lava && distu(rx,ry) <= 2) {
- int dmg;
- You("are hit by molten lava%c",
- Fire_resistance ? '.' : '!');
- burn_away_slime();
- dmg = d((Fire_resistance ? 1 : 3), 6);
- losehp(Maybe_Half_Phys(dmg), /* lava damage */
- "molten lava", KILLED_BY);
- } else if (!fills_up && flags.verbose &&
- (pushing ? !Blind : cansee(rx,ry)))
- pline("It sinks without a trace!");
- }
-
- /* boulder is now gone */
- if (pushing) delobj(otmp);
- else obfree(otmp, (struct obj *)0);
- return TRUE;
- }
- return FALSE;
+ if (!otmp || otmp->otyp != BOULDER)
+ impossible("Not a boulder?");
+ else if (!Is_waterlevel(&u.uz) && is_pool_or_lava(rx,ry)) {
+ boolean lava = is_lava(rx,ry), fills_up;
+ const char *what = waterbody_name(rx,ry);
+ schar ltyp = levl[rx][ry].typ;
+ int chance = rn2(10); /* water: 90%; lava: 10% */
+ fills_up = lava ? chance == 0 : chance != 0;
+
+ if (fills_up) {
+ struct trap *ttmp = t_at(rx, ry);
+
+ if (ltyp == DRAWBRIDGE_UP) {
+ levl[rx][ry].drawbridgemask &= ~DB_UNDER; /* clear lava */
+ levl[rx][ry].drawbridgemask |= DB_FLOOR;
+ } else
+ levl[rx][ry].typ = ROOM;
+
+ if (ttmp) (void) delfloortrap(ttmp);
+ bury_objs(rx, ry);
+
+ newsym(rx,ry);
+ if (pushing) {
+ char whobuf[BUFSZ];
+
+ Strcpy(whobuf, "you");
+ if (u.usteed) Strcpy(whobuf, y_monnam(u.usteed));
+ pline("%s %s %s into the %s.", upstart(whobuf),
+ vtense(whobuf, "push"), the(xname(otmp)), what);
+ if (flags.verbose && !Blind)
+ pline("Now you can cross it!");
+ /* no splashing in this case */
+ }
+ }
+ if (!fills_up || !pushing) { /* splashing occurs */
+ if (!u.uinwater) {
+ if (pushing ? !Blind : cansee(rx,ry)) {
+ There("is a large splash as %s %s the %s.",
+ the(xname(otmp)), fills_up? "fills":"falls into",
+ what);
+ } else if (!Deaf)
+ You_hear("a%s splash.", lava ? " sizzling" : "");
+ wake_nearto(rx, ry, 40);
+ }
+
+ if (fills_up && u.uinwater && distu(rx,ry) == 0) {
+ u.uinwater = 0;
+ docrt();
+ vision_full_recalc = 1;
+ You("find yourself on dry land again!");
+ } else if (lava && distu(rx,ry) <= 2) {
+ int dmg;
+ You("are hit by molten lava%c",
+ Fire_resistance ? '.' : '!');
+ burn_away_slime();
+ dmg = d((Fire_resistance ? 1 : 3), 6);
+ losehp(Maybe_Half_Phys(dmg), /* lava damage */
+ "molten lava", KILLED_BY);
+ } else if (!fills_up && flags.verbose &&
+ (pushing ? !Blind : cansee(rx,ry)))
+ pline("It sinks without a trace!");
+ }
+
+ /* boulder is now gone */
+ if (pushing) delobj(otmp);
+ else obfree(otmp, (struct obj *)0);
+ return TRUE;
+ }
+ return FALSE;
}
/* Used for objects which sometimes do special things when dropped; must be
int x, y;
const char *verb;
{
- struct trap *t;
- struct monst *mtmp;
-
- if (obj->where != OBJ_FREE)
- panic("flooreffects: obj not free");
-
- /* make sure things like water_damage() have no pointers to follow */
- obj->nobj = obj->nexthere = (struct obj *)0;
-
- if (obj->otyp == BOULDER && boulder_hits_pool(obj, x, y, FALSE))
- return TRUE;
- else if (obj->otyp == BOULDER && (t = t_at(x,y)) != 0 &&
- (t->ttyp==PIT || t->ttyp==SPIKED_PIT
- || t->ttyp==TRAPDOOR || t->ttyp==HOLE)) {
- if (((mtmp = m_at(x, y)) && mtmp->mtrapped) ||
- (u.utrap && u.ux == x && u.uy == y)) {
- if (*verb)
- pline_The("boulder %s into the pit%s.",
- vtense((const char *)0, verb),
- (mtmp) ? "" : " with you");
- if (mtmp) {
- if (!passes_walls(mtmp->data) &&
- !throws_rocks(mtmp->data)) {
- if (hmon(mtmp, obj, TRUE) && !is_whirly(mtmp->data))
- return FALSE; /* still alive */
- }
- mtmp->mtrapped = 0;
- } else {
- if (!Passes_walls && !throws_rocks(youmonst.data)) {
- losehp(Maybe_Half_Phys(rnd(15)),
- "squished under a boulder",
- NO_KILLER_PREFIX);
- return FALSE; /* player remains trapped */
- } else u.utrap = 0;
- }
- }
- if (*verb) {
- if (Blind && (x == u.ux) && (y == u.uy)) {
- You_hear("a CRASH! beneath you.");
- } else if (!Blind && cansee(x, y)) {
- pline_The("boulder %s%s.",
- t->tseen ? "" : "triggers and ",
- t->ttyp == TRAPDOOR ? "plugs a trap door" :
- t->ttyp == HOLE ? "plugs a hole" :
- "fills a pit");
- } else {
- You_hear("a boulder %s.", verb);
- }
- }
- deltrap(t);
- useupf(obj, 1L);
- bury_objs(x, y);
- newsym(x,y);
- return TRUE;
- } else if (is_lava(x, y)) {
- return fire_damage(obj, FALSE, x, y);
- } else if (is_pool(x, y)) {
- /* Reasonably bulky objects (arbitrary) splash when dropped.
- * If you're floating above the water even small things make
- * noise. Stuff dropped near fountains always misses */
- if ((Blind || (Levitation || Flying)) && !Deaf &&
- ((x == u.ux) && (y == u.uy))) {
- if (!Underwater) {
- if (weight(obj) > 9) {
- pline("Splash!");
- } else if (Levitation || Flying) {
- pline("Plop!");
- }
- }
- map_background(x, y, 0);
- newsym(x, y);
- }
- return water_damage(obj, NULL, FALSE) == ER_DESTROYED;
- } else if (u.ux == x && u.uy == y &&
- (t = t_at(x,y)) != 0 && uteetering_at_seen_pit(t)) {
- if (Blind && !Deaf)
- You_hear("%s tumble downwards.",
- the(xname(obj)));
- else
- pline("%s %s into %s pit.",
- The(xname(obj)), otense(obj, "tumble"),
- the_your[t->madeby_u]);
- }
- return FALSE;
+ struct trap *t;
+ struct monst *mtmp;
+ struct obj* otmp;
+
+ if (obj->where != OBJ_FREE)
+ panic("flooreffects: obj not free");
+
+ /* make sure things like water_damage() have no pointers to follow */
+ obj->nobj = obj->nexthere = (struct obj *)0;
+
+ if (obj->otyp == BOULDER && boulder_hits_pool(obj, x, y, FALSE))
+ return TRUE;
+ else if (obj->otyp == BOULDER && (t = t_at(x,y)) != 0 &&
+ (t->ttyp==PIT || t->ttyp==SPIKED_PIT
+ || t->ttyp==TRAPDOOR || t->ttyp==HOLE)) {
+ if (((mtmp = m_at(x, y)) && mtmp->mtrapped) ||
+ (u.utrap && u.ux == x && u.uy == y)) {
+ if (*verb)
+ pline_The("boulder %s into the pit%s.",
+ vtense((const char *)0, verb),
+ (mtmp) ? "" : " with you");
+ if (mtmp) {
+ if (!passes_walls(mtmp->data) &&
+ !throws_rocks(mtmp->data)) {
+ if (hmon(mtmp, obj, TRUE) && !is_whirly(mtmp->data))
+ return FALSE; /* still alive */
+ }
+ mtmp->mtrapped = 0;
+ } else {
+ if (!Passes_walls && !throws_rocks(youmonst.data)) {
+ losehp(Maybe_Half_Phys(rnd(15)),
+ "squished under a boulder",
+ NO_KILLER_PREFIX);
+ return FALSE; /* player remains trapped */
+ } else u.utrap = 0;
+ }
+ }
+ if (*verb) {
+ if (Blind && (x == u.ux) && (y == u.uy)) {
+ You_hear("a CRASH! beneath you.");
+ } else if (!Blind && cansee(x, y)) {
+ pline_The("boulder %s%s.",
+ t->tseen ? "" : "triggers and ",
+ t->ttyp == TRAPDOOR ? "plugs a trap door" :
+ t->ttyp == HOLE ? "plugs a hole" :
+ "fills a pit");
+ } else {
+ You_hear("a boulder %s.", verb);
+ }
+ }
+ deltrap(t);
+ useupf(obj, 1L);
+ bury_objs(x, y);
+ newsym(x,y);
+ return TRUE;
+ } else if (is_lava(x, y)) {
+ return fire_damage(obj, FALSE, x, y);
+ } else if (is_pool(x, y)) {
+ /* Reasonably bulky objects (arbitrary) splash when dropped.
+ * If you're floating above the water even small things make
+ * noise. Stuff dropped near fountains always misses */
+ if ((Blind || (Levitation || Flying)) && !Deaf &&
+ ((x == u.ux) && (y == u.uy))) {
+ if (!Underwater) {
+ if (weight(obj) > 9) {
+ pline("Splash!");
+ } else if (Levitation || Flying) {
+ pline("Plop!");
+ }
+ }
+ map_background(x, y, 0);
+ newsym(x, y);
+ }
+ return water_damage(obj, NULL, FALSE) == ER_DESTROYED;
+ } else if (u.ux == x && u.uy == y &&
+ (t = t_at(x,y)) != 0 && uteetering_at_seen_pit(t)) {
+ if (Blind && !Deaf)
+ You_hear("%s tumble downwards.",
+ the(xname(obj)));
+ else
+ pline("%s %s into %s pit.",
+ The(xname(obj)), otense(obj, "tumble"),
+ the_your[t->madeby_u]);
+ } else if (obj->globby) {
+ /* Globby things like puddings might stick together */
+ while (obj && (otmp = obj_nexto_xy(obj->otyp, x, y, obj->o_id)) != (struct obj*)0) {
+ pline("The %s coalesce.", makeplural(obj_typename(obj->otyp)));
+ obj_meld(&obj, &otmp);
+ return (obj == NULL);
+ }
+ }
+ return FALSE;
}
void
doaltarobj(obj) /* obj is an object dropped on an altar */
- register struct obj *obj;
+ register struct obj *obj;
{
- if (Blind)
- return;
-
- /* KMH, conduct */
- u.uconduct.gnostic++;
-
- if ((obj->blessed || obj->cursed) && obj->oclass != COIN_CLASS) {
- There("is %s flash as %s %s the altar.",
- an(hcolor(obj->blessed ? NH_AMBER : NH_BLACK)),
- doname(obj), otense(obj, "hit"));
- if (!Hallucination) obj->bknown = 1;
- } else {
- pline("%s %s on the altar.", Doname2(obj),
- otense(obj, "land"));
- obj->bknown = 1;
- }
+ if (Blind)
+ return;
+
+ /* KMH, conduct */
+ u.uconduct.gnostic++;
+
+ if ((obj->blessed || obj->cursed) && obj->oclass != COIN_CLASS) {
+ There("is %s flash as %s %s the altar.",
+ an(hcolor(obj->blessed ? NH_AMBER : NH_BLACK)),
+ doname(obj), otense(obj, "hit"));
+ if (!Hallucination) obj->bknown = 1;
+ } else {
+ pline("%s %s on the altar.", Doname2(obj),
+ otense(obj, "land"));
+ obj->bknown = 1;
+ }
}
STATIC_OVL
trycall(obj)
register struct obj *obj;
{
- if(!objects[obj->otyp].oc_name_known &&
- !objects[obj->otyp].oc_uname)
- docall(obj);
+ if(!objects[obj->otyp].oc_name_known &&
+ !objects[obj->otyp].oc_uname)
+ docall(obj);
}
STATIC_OVL
dosinkring(obj) /* obj is a ring being dropped over a kitchen sink */
register struct obj *obj;
{
- register struct obj *otmp,*otmp2;
- register boolean ideed = TRUE;
-
- You("drop %s down the drain.", doname(obj));
- obj->in_use = TRUE; /* block free identification via interrupt */
- switch(obj->otyp) { /* effects that can be noticed without eyes */
- case RIN_SEARCHING:
- You("thought %s got lost in the sink, but there it is!",
- yname(obj));
- goto giveback;
- case RIN_SLOW_DIGESTION:
- pline_The("ring is regurgitated!");
+ register struct obj *otmp,*otmp2;
+ register boolean ideed = TRUE;
+
+ You("drop %s down the drain.", doname(obj));
+ obj->in_use = TRUE; /* block free identification via interrupt */
+ switch(obj->otyp) { /* effects that can be noticed without eyes */
+ case RIN_SEARCHING:
+ You("thought %s got lost in the sink, but there it is!",
+ yname(obj));
+ goto giveback;
+ case RIN_SLOW_DIGESTION:
+ pline_The("ring is regurgitated!");
giveback:
- obj->in_use = FALSE;
- dropx(obj);
- trycall(obj);
- return;
- case RIN_LEVITATION:
- pline_The("sink quivers upward for a moment.");
- break;
- case RIN_POISON_RESISTANCE:
- You("smell rotten %s.", makeplural(fruitname(FALSE)));
- break;
- case RIN_AGGRAVATE_MONSTER:
- pline("Several flies buzz angrily around the sink.");
- break;
- case RIN_SHOCK_RESISTANCE:
- pline("Static electricity surrounds the sink.");
- break;
- case RIN_CONFLICT:
- You_hear("loud noises coming from the drain.");
- break;
- case RIN_SUSTAIN_ABILITY: /* KMH */
- pline_The("water flow seems fixed.");
- break;
- case RIN_GAIN_STRENGTH:
- pline_The("water flow seems %ser now.",
- (obj->spe<0) ? "weak" : "strong");
- break;
- case RIN_GAIN_CONSTITUTION:
- pline_The("water flow seems %ser now.",
- (obj->spe<0) ? "less" : "great");
- break;
- case RIN_INCREASE_ACCURACY: /* KMH */
- pline_The("water flow %s the drain.",
- (obj->spe<0) ? "misses" : "hits");
- break;
- case RIN_INCREASE_DAMAGE:
- pline_The("water's force seems %ser now.",
- (obj->spe<0) ? "small" : "great");
- break;
- case RIN_HUNGER:
- ideed = FALSE;
- for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
- otmp2 = otmp->nexthere;
- if (otmp != uball && otmp != uchain &&
- !obj_resists(otmp, 1, 99)) {
- if (!Blind) {
- pline("Suddenly, %s %s from the sink!",
- doname(otmp), otense(otmp, "vanish"));
- ideed = TRUE;
- }
- delobj(otmp);
- }
- }
- break;
- case MEAT_RING:
- /* Not the same as aggravate monster; besides, it's obvious. */
- pline("Several flies buzz around the sink.");
- break;
- default:
- ideed = FALSE;
- break;
- }
- if(!Blind && !ideed && obj->otyp != RIN_HUNGER) {
- ideed = TRUE;
- switch(obj->otyp) { /* effects that need eyes */
- case RIN_ADORNMENT:
- pline_The("faucets flash brightly for a moment.");
- break;
- case RIN_REGENERATION:
- pline_The("sink looks as good as new.");
- break;
- case RIN_INVISIBILITY:
- You("don't see anything happen to the sink.");
- break;
- case RIN_FREE_ACTION:
- You_see("the ring slide right down the drain!");
- break;
- case RIN_SEE_INVISIBLE:
- You_see("some air in the sink.");
- break;
- case RIN_STEALTH:
- pline_The("sink seems to blend into the floor for a moment.");
- break;
- case RIN_FIRE_RESISTANCE:
- pline_The("hot water faucet flashes brightly for a moment.");
- break;
- case RIN_COLD_RESISTANCE:
- pline_The("cold water faucet flashes brightly for a moment.");
- break;
- case RIN_PROTECTION_FROM_SHAPE_CHAN:
- pline_The("sink looks nothing like a fountain.");
- break;
- case RIN_PROTECTION:
- pline_The("sink glows %s for a moment.",
- hcolor((obj->spe<0) ? NH_BLACK : NH_SILVER));
- break;
- case RIN_WARNING:
- pline_The("sink glows %s for a moment.", hcolor(NH_WHITE));
- break;
- case RIN_TELEPORTATION:
- pline_The("sink momentarily vanishes.");
- break;
- case RIN_TELEPORT_CONTROL:
- pline_The("sink looks like it is being beamed aboard somewhere.");
- break;
- case RIN_POLYMORPH:
- pline_The("sink momentarily looks like a fountain.");
- break;
- case RIN_POLYMORPH_CONTROL:
- pline_The("sink momentarily looks like a regularly erupting geyser.");
- break;
- }
- }
- if(ideed)
- trycall(obj);
- else
- You_hear("the ring bouncing down the drainpipe.");
- if (!rn2(20)) {
- pline_The("sink backs up, leaving %s.", doname(obj));
- obj->in_use = FALSE;
- dropx(obj);
- } else
- useup(obj);
+ obj->in_use = FALSE;
+ dropx(obj);
+ trycall(obj);
+ return;
+ case RIN_LEVITATION:
+ pline_The("sink quivers upward for a moment.");
+ break;
+ case RIN_POISON_RESISTANCE:
+ You("smell rotten %s.", makeplural(fruitname(FALSE)));
+ break;
+ case RIN_AGGRAVATE_MONSTER:
+ pline("Several flies buzz angrily around the sink.");
+ break;
+ case RIN_SHOCK_RESISTANCE:
+ pline("Static electricity surrounds the sink.");
+ break;
+ case RIN_CONFLICT:
+ You_hear("loud noises coming from the drain.");
+ break;
+ case RIN_SUSTAIN_ABILITY: /* KMH */
+ pline_The("water flow seems fixed.");
+ break;
+ case RIN_GAIN_STRENGTH:
+ pline_The("water flow seems %ser now.",
+ (obj->spe<0) ? "weak" : "strong");
+ break;
+ case RIN_GAIN_CONSTITUTION:
+ pline_The("water flow seems %ser now.",
+ (obj->spe<0) ? "less" : "great");
+ break;
+ case RIN_INCREASE_ACCURACY: /* KMH */
+ pline_The("water flow %s the drain.",
+ (obj->spe<0) ? "misses" : "hits");
+ break;
+ case RIN_INCREASE_DAMAGE:
+ pline_The("water's force seems %ser now.",
+ (obj->spe<0) ? "small" : "great");
+ break;
+ case RIN_HUNGER:
+ ideed = FALSE;
+ for(otmp = level.objects[u.ux][u.uy]; otmp; otmp = otmp2) {
+ otmp2 = otmp->nexthere;
+ if (otmp != uball && otmp != uchain &&
+ !obj_resists(otmp, 1, 99)) {
+ if (!Blind) {
+ pline("Suddenly, %s %s from the sink!",
+ doname(otmp), otense(otmp, "vanish"));
+ ideed = TRUE;
+ }
+ delobj(otmp);
+ }
+ }
+ break;
+ case MEAT_RING:
+ /* Not the same as aggravate monster; besides, it's obvious. */
+ pline("Several flies buzz around the sink.");
+ break;
+ default:
+ ideed = FALSE;
+ break;
+ }
+ if(!Blind && !ideed && obj->otyp != RIN_HUNGER) {
+ ideed = TRUE;
+ switch(obj->otyp) { /* effects that need eyes */
+ case RIN_ADORNMENT:
+ pline_The("faucets flash brightly for a moment.");
+ break;
+ case RIN_REGENERATION:
+ pline_The("sink looks as good as new.");
+ break;
+ case RIN_INVISIBILITY:
+ You("don't see anything happen to the sink.");
+ break;
+ case RIN_FREE_ACTION:
+ You_see("the ring slide right down the drain!");
+ break;
+ case RIN_SEE_INVISIBLE:
+ You_see("some air in the sink.");
+ break;
+ case RIN_STEALTH:
+ pline_The("sink seems to blend into the floor for a moment.");
+ break;
+ case RIN_FIRE_RESISTANCE:
+ pline_The("hot water faucet flashes brightly for a moment.");
+ break;
+ case RIN_COLD_RESISTANCE:
+ pline_The("cold water faucet flashes brightly for a moment.");
+ break;
+ case RIN_PROTECTION_FROM_SHAPE_CHAN:
+ pline_The("sink looks nothing like a fountain.");
+ break;
+ case RIN_PROTECTION:
+ pline_The("sink glows %s for a moment.",
+ hcolor((obj->spe<0) ? NH_BLACK : NH_SILVER));
+ break;
+ case RIN_WARNING:
+ pline_The("sink glows %s for a moment.", hcolor(NH_WHITE));
+ break;
+ case RIN_TELEPORTATION:
+ pline_The("sink momentarily vanishes.");
+ break;
+ case RIN_TELEPORT_CONTROL:
+ pline_The("sink looks like it is being beamed aboard somewhere.");
+ break;
+ case RIN_POLYMORPH:
+ pline_The("sink momentarily looks like a fountain.");
+ break;
+ case RIN_POLYMORPH_CONTROL:
+ pline_The("sink momentarily looks like a regularly erupting geyser.");
+ break;
+ }
+ }
+ if(ideed)
+ trycall(obj);
+ else
+ You_hear("the ring bouncing down the drainpipe.");
+ if (!rn2(20)) {
+ pline_The("sink backs up, leaving %s.", doname(obj));
+ obj->in_use = FALSE;
+ dropx(obj);
+ } else
+ useup(obj);
}
/* some common tests when trying to drop or throw items */
register struct obj *obj;
register const char *word;
{
- if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)){
- if (*word)
- Norep("You cannot %s %s you are wearing.",word,
- something);
- return(FALSE);
- }
- if (obj->otyp == LOADSTONE && obj->cursed) {
- /* getobj() kludge sets corpsenm to user's specified count
- when refusing to split a stack of cursed loadstones */
- if (*word) {
- /* getobj() ignores a count for throwing since that is
- implicitly forced to be 1; replicate its kludge... */
- if (!strcmp(word, "throw") && obj->quan > 1L)
- obj->corpsenm = 1;
- pline("For some reason, you cannot %s%s the stone%s!",
- word, obj->corpsenm ? " any of" : "",
- plur(obj->quan));
- }
- obj->corpsenm = 0; /* reset */
- obj->bknown = 1;
- return(FALSE);
- }
- if (obj->otyp == LEASH && obj->leashmon != 0) {
- if (*word)
- pline_The("leash is tied around your %s.",
- body_part(HAND));
- return(FALSE);
- }
- if (obj->owornmask & W_SADDLE) {
- if (*word)
- You("cannot %s %s you are sitting on.", word,
- something);
- return (FALSE);
- }
- return(TRUE);
+ if(obj->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)){
+ if (*word)
+ Norep("You cannot %s %s you are wearing.",word,
+ something);
+ return(FALSE);
+ }
+ if (obj->otyp == LOADSTONE && obj->cursed) {
+ /* getobj() kludge sets corpsenm to user's specified count
+ when refusing to split a stack of cursed loadstones */
+ if (*word) {
+ /* getobj() ignores a count for throwing since that is
+ implicitly forced to be 1; replicate its kludge... */
+ if (!strcmp(word, "throw") && obj->quan > 1L)
+ obj->corpsenm = 1;
+ pline("For some reason, you cannot %s%s the stone%s!",
+ word, obj->corpsenm ? " any of" : "",
+ plur(obj->quan));
+ }
+ obj->corpsenm = 0; /* reset */
+ obj->bknown = 1;
+ return(FALSE);
+ }
+ if (obj->otyp == LEASH && obj->leashmon != 0) {
+ if (*word)
+ pline_The("leash is tied around your %s.",
+ body_part(HAND));
+ return(FALSE);
+ }
+ if (obj->owornmask & W_SADDLE) {
+ if (*word)
+ You("cannot %s %s you are sitting on.", word,
+ something);
+ return (FALSE);
+ }
+ return(TRUE);
}
STATIC_PTR
drop(obj)
register struct obj *obj;
{
- if(!obj) return(0);
- if(!canletgo(obj,"drop"))
- return(0);
- if(obj == uwep) {
- if(welded(uwep)) {
- weldmsg(obj);
- return(0);
- }
- setuwep((struct obj *)0);
- }
- if(obj == uquiver) {
- setuqwep((struct obj *)0);
- }
- if (obj == uswapwep) {
- setuswapwep((struct obj *)0);
- }
-
- if (u.uswallow) {
- /* barrier between you and the floor */
- if(flags.verbose)
- {
- char buf[BUFSZ];
-
- /* doname can call s_suffix, reusing its buffer */
- Strcpy(buf, s_suffix(mon_nam(u.ustuck)));
- You("drop %s into %s %s.", doname(obj), buf,
- mbodypart(u.ustuck, STOMACH));
- }
- } else {
- if((obj->oclass == RING_CLASS || obj->otyp == MEAT_RING) &&
- IS_SINK(levl[u.ux][u.uy].typ)) {
- dosinkring(obj);
- return(1);
- }
- if (!can_reach_floor(TRUE)) {
- /* we might be levitating due to #invoke Heart of Ahriman;
- if so, levitation would end during call to freeinv()
- and we want hitfloor() to happen before float_down() */
- boolean levhack = finesse_ahriman(obj);
-
- if (levhack) ELevitation = W_ART; /* other than W_ARTI */
- if(flags.verbose) You("drop %s.", doname(obj));
- /* Ensure update when we drop gold objects */
- if (obj->oclass == COIN_CLASS) context.botl = 1;
- freeinv(obj);
- hitfloor(obj);
- if (levhack) float_down(I_SPECIAL|TIMEOUT, W_ARTI|W_ART);
- return(1);
- }
- if (!IS_ALTAR(levl[u.ux][u.uy].typ) && flags.verbose)
- You("drop %s.", doname(obj));
- }
- dropx(obj);
- return(1);
+ if(!obj) return(0);
+ if(!canletgo(obj,"drop"))
+ return(0);
+ if(obj == uwep) {
+ if(welded(uwep)) {
+ weldmsg(obj);
+ return(0);
+ }
+ setuwep((struct obj *)0);
+ }
+ if(obj == uquiver) {
+ setuqwep((struct obj *)0);
+ }
+ if (obj == uswapwep) {
+ setuswapwep((struct obj *)0);
+ }
+
+ if (u.uswallow) {
+ /* barrier between you and the floor */
+ if(flags.verbose)
+ {
+ char buf[BUFSZ];
+
+ /* doname can call s_suffix, reusing its buffer */
+ Strcpy(buf, s_suffix(mon_nam(u.ustuck)));
+ You("drop %s into %s %s.", doname(obj), buf,
+ mbodypart(u.ustuck, STOMACH));
+ }
+ } else {
+ if((obj->oclass == RING_CLASS || obj->otyp == MEAT_RING) &&
+ IS_SINK(levl[u.ux][u.uy].typ)) {
+ dosinkring(obj);
+ return(1);
+ }
+ if (!can_reach_floor(TRUE)) {
+ /* we might be levitating due to #invoke Heart of Ahriman;
+ if so, levitation would end during call to freeinv()
+ and we want hitfloor() to happen before float_down() */
+ boolean levhack = finesse_ahriman(obj);
+
+ if (levhack) ELevitation = W_ART; /* other than W_ARTI */
+ if(flags.verbose) You("drop %s.", doname(obj));
+ /* Ensure update when we drop gold objects */
+ if (obj->oclass == COIN_CLASS) context.botl = 1;
+ freeinv(obj);
+ hitfloor(obj);
+ if (levhack) float_down(I_SPECIAL|TIMEOUT, W_ARTI|W_ART);
+ return(1);
+ }
+ if (!IS_ALTAR(levl[u.ux][u.uy].typ) && flags.verbose)
+ You("drop %s.", doname(obj));
+ }
+ dropx(obj);
+ return(1);
}
/* dropx - take dropped item out of inventory;
/* Ensure update when we drop gold objects */
if (obj->oclass == COIN_CLASS) context.botl = 1;
freeinv(obj);
- if (!u.uswallow) {
- if (ship_object(obj, u.ux, u.uy, FALSE)) return;
- if (IS_ALTAR(levl[u.ux][u.uy].typ))
- doaltarobj(obj); /* set bknown */
- }
- dropy(obj);
+ if (!u.uswallow) {
+ if (ship_object(obj, u.ux, u.uy, FALSE)) return;
+ if (IS_ALTAR(levl[u.ux][u.uy].typ))
+ doaltarobj(obj); /* set bknown */
+ }
+ dropy(obj);
}
/* dropy - put dropped object at its destination; called from lots of places */
dropy(obj)
struct obj *obj;
{
- dropz(obj, FALSE);
+ dropz(obj, FALSE);
}
/* dropz - really put dropped object at its destination... */
struct obj *obj;
boolean with_impact;
{
- if (obj == uwep) setuwep((struct obj *)0);
- if (obj == uquiver) setuqwep((struct obj *)0);
- if (obj == uswapwep) setuswapwep((struct obj *)0);
-
- if (!u.uswallow && flooreffects(obj,u.ux,u.uy,"drop")) return;
- /* uswallow check done by GAN 01/29/87 */
- if(u.uswallow) {
- boolean could_petrify = FALSE;
- boolean could_poly = FALSE;
- boolean could_slime = FALSE;
- boolean could_grow = FALSE;
- boolean could_heal = FALSE;
-
- if (obj != uball) { /* mon doesn't pick up ball */
- if (obj->otyp == CORPSE) {
- could_petrify = touch_petrifies(&mons[obj->corpsenm]);
- could_poly = polyfodder(obj);
- could_slime = (obj->corpsenm == PM_GREEN_SLIME);
- could_grow = (obj->corpsenm == PM_WRAITH);
- could_heal = (obj->corpsenm == PM_NURSE);
- }
- (void) mpickobj(u.ustuck,obj);
- if (is_animal(u.ustuck->data)) {
- if (could_poly || could_slime) {
- (void) newcham(u.ustuck,
- could_poly ? (struct permonst *)0 :
- &mons[PM_GREEN_SLIME],
- FALSE, could_slime);
- delobj(obj); /* corpse is digested */
- } else if (could_petrify) {
- minstapetrify(u.ustuck, TRUE);
- /* Don't leave a cockatrice corpse in a statue */
- if (!u.uswallow) delobj(obj);
- } else if (could_grow) {
- (void) grow_up(u.ustuck, (struct monst *)0);
- delobj(obj); /* corpse is digested */
- } else if (could_heal) {
- u.ustuck->mhp = u.ustuck->mhpmax;
- delobj(obj); /* corpse is digested */
- }
- }
- }
- } else {
- place_object(obj, u.ux, u.uy);
- if (with_impact)
- container_impact_dmg(obj, u.ux, u.uy);
- if (obj == uball)
- drop_ball(u.ux,u.uy);
- else if (level.flags.has_shop)
- sellobj(obj, u.ux, u.uy);
- stackobj(obj);
- if(Blind && Levitation)
- map_object(obj, 0);
- newsym(u.ux,u.uy); /* remap location under self */
- }
+ if (obj == uwep) setuwep((struct obj *)0);
+ if (obj == uquiver) setuqwep((struct obj *)0);
+ if (obj == uswapwep) setuswapwep((struct obj *)0);
+
+ if (!u.uswallow && flooreffects(obj,u.ux,u.uy,"drop")) return;
+ /* uswallow check done by GAN 01/29/87 */
+ if(u.uswallow) {
+ boolean could_petrify = FALSE;
+ boolean could_poly = FALSE;
+ boolean could_slime = FALSE;
+ boolean could_grow = FALSE;
+ boolean could_heal = FALSE;
+
+ if (obj != uball) { /* mon doesn't pick up ball */
+ if (obj->otyp == CORPSE) {
+ could_petrify = touch_petrifies(&mons[obj->corpsenm]);
+ could_poly = polyfodder(obj);
+ could_slime = (obj->corpsenm == PM_GREEN_SLIME);
+ could_grow = (obj->corpsenm == PM_WRAITH);
+ could_heal = (obj->corpsenm == PM_NURSE);
+ }
+ (void) mpickobj(u.ustuck,obj);
+ if (is_animal(u.ustuck->data)) {
+ if (could_poly || could_slime) {
+ (void) newcham(u.ustuck,
+ could_poly ? (struct permonst *)0 :
+ &mons[PM_GREEN_SLIME],
+ FALSE, could_slime);
+ delobj(obj); /* corpse is digested */
+ } else if (could_petrify) {
+ minstapetrify(u.ustuck, TRUE);
+ /* Don't leave a cockatrice corpse in a statue */
+ if (!u.uswallow) delobj(obj);
+ } else if (could_grow) {
+ (void) grow_up(u.ustuck, (struct monst *)0);
+ delobj(obj); /* corpse is digested */
+ } else if (could_heal) {
+ u.ustuck->mhp = u.ustuck->mhpmax;
+ delobj(obj); /* corpse is digested */
+ }
+ }
+ }
+ } else {
+ place_object(obj, u.ux, u.uy);
+ if (with_impact)
+ container_impact_dmg(obj, u.ux, u.uy);
+ if (obj == uball)
+ drop_ball(u.ux,u.uy);
+ else if (level.flags.has_shop)
+ sellobj(obj, u.ux, u.uy);
+ stackobj(obj);
+ if(Blind && Levitation)
+ map_object(obj, 0);
+ newsym(u.ux,u.uy); /* remap location under self */
+ }
}
/* things that must change when not held; recurse into containers.
obj_no_longer_held(obj)
struct obj *obj;
{
- if (!obj) {
- return;
- } else if (Has_contents(obj)) {
- struct obj *contents;
-
- for (contents = obj->cobj; contents; contents = contents->nobj)
- obj_no_longer_held(contents);
- }
- switch (obj->otyp) {
- case CRYSKNIFE:
- /* Normal crysknife reverts to worm tooth when not held by hero
- * or monster; fixed crysknife has only 10% chance of reverting.
- * When a stack of the latter is involved, it could be worthwhile
- * to give each individual crysknife its own separate 10% chance,
- * but we aren't in any position to handle stack splitting here.
- */
- if (!obj->oerodeproof || !rn2(10)) {
- /* if monsters aren't moving, assume player is responsible */
- if (!context.mon_moving && !program_state.gameover)
- costly_alteration(obj, COST_DEGRD);
- obj->otyp = WORM_TOOTH;
- obj->oerodeproof = 0;
- }
- break;
- }
+ if (!obj) {
+ return;
+ } else if (Has_contents(obj)) {
+ struct obj *contents;
+
+ for (contents = obj->cobj; contents; contents = contents->nobj)
+ obj_no_longer_held(contents);
+ }
+ switch (obj->otyp) {
+ case CRYSKNIFE:
+ /* Normal crysknife reverts to worm tooth when not held by hero
+ * or monster; fixed crysknife has only 10% chance of reverting.
+ * When a stack of the latter is involved, it could be worthwhile
+ * to give each individual crysknife its own separate 10% chance,
+ * but we aren't in any position to handle stack splitting here.
+ */
+ if (!obj->oerodeproof || !rn2(10)) {
+ /* if monsters aren't moving, assume player is responsible */
+ if (!context.mon_moving && !program_state.gameover)
+ costly_alteration(obj, COST_DEGRD);
+ obj->otyp = WORM_TOOTH;
+ obj->oerodeproof = 0;
+ }
+ break;
+ }
}
/* 'D' command: drop several things */
int
doddrop()
{
- int result = 0;
+ int result = 0;
- add_valid_menu_class(0); /* clear any classes already there */
- if (*u.ushops) sellobj_state(SELL_DELIBERATE);
- if (flags.menu_style != MENU_TRADITIONAL ||
- (result = ggetobj("drop", drop, 0, FALSE, (unsigned *)0)) < -1)
- result = menu_drop(result);
- if (*u.ushops) sellobj_state(SELL_NORMAL);
- reset_occupations();
+ add_valid_menu_class(0); /* clear any classes already there */
+ if (*u.ushops) sellobj_state(SELL_DELIBERATE);
+ if (flags.menu_style != MENU_TRADITIONAL ||
+ (result = ggetobj("drop", drop, 0, FALSE, (unsigned *)0)) < -1)
+ result = menu_drop(result);
+ if (*u.ushops) sellobj_state(SELL_NORMAL);
+ reset_occupations();
- return result;
+ return result;
}
/* Drop things from the hero's inventory, using a menu. */
boolean drop_everything = FALSE;
if (retry) {
- all_categories = (retry == -2);
+ all_categories = (retry == -2);
} else if (flags.menu_style == MENU_FULL) {
- all_categories = FALSE;
- n = query_category("Drop what type of items?",
- invent,
- UNPAID_TYPES | ALL_TYPES | CHOOSE_ALL |
- BUC_BLESSED | BUC_CURSED | BUC_UNCURSED | BUC_UNKNOWN,
- &pick_list, PICK_ANY);
- if (!n) goto drop_done;
- for (i = 0; i < n; i++) {
- if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
- all_categories = TRUE;
- else if (pick_list[i].item.a_int == 'A')
- drop_everything = TRUE;
- else
- add_valid_menu_class(pick_list[i].item.a_int);
- }
- free((genericptr_t) pick_list);
+ all_categories = FALSE;
+ n = query_category("Drop what type of items?",
+ invent,
+ UNPAID_TYPES | ALL_TYPES | CHOOSE_ALL |
+ BUC_BLESSED | BUC_CURSED | BUC_UNCURSED | BUC_UNKNOWN,
+ &pick_list, PICK_ANY);
+ if (!n) goto drop_done;
+ for (i = 0; i < n; i++) {
+ if (pick_list[i].item.a_int == ALL_TYPES_SELECTED)
+ all_categories = TRUE;
+ else if (pick_list[i].item.a_int == 'A')
+ drop_everything = TRUE;
+ else
+ add_valid_menu_class(pick_list[i].item.a_int);
+ }
+ free((genericptr_t) pick_list);
} else if (flags.menu_style == MENU_COMBINATION) {
- unsigned ggoresults = 0;
- all_categories = FALSE;
- /* Gather valid classes via traditional NetHack method */
- i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
- if (i == -2) all_categories = TRUE;
- if (ggoresults & ALL_FINISHED) {
- n_dropped = i;
- goto drop_done;
- }
+ unsigned ggoresults = 0;
+ all_categories = FALSE;
+ /* Gather valid classes via traditional NetHack method */
+ i = ggetobj("drop", drop, 0, TRUE, &ggoresults);
+ if (i == -2) all_categories = TRUE;
+ if (ggoresults & ALL_FINISHED) {
+ n_dropped = i;
+ goto drop_done;
+ }
}
if (drop_everything) {
- /*
- * Dropping a burning potion of oil while levitating can cause
- * an explosion which might destroy some of hero's inventory,
- * so the old code
- * for (otmp = invent; otmp; otmp = otmp2) {
- * otmp2 = otmp->nobj;
- * n_dropped += drop(otmp);
- * }
- * was unreliable and could lead to an "object lost" panic.
- *
- * Use the bypass bit to mark items already processed (hence
- * not droppable) and rescan inventory until no unbypassed
- * items remain.
- */
- bypass_objlist(invent, FALSE); /* clear bypass bit for invent */
- while ((otmp = nxt_unbypassed_obj(invent)) != 0)
- n_dropped += drop(otmp);
- /* we might not have dropped everything (worn armor, welded weapon,
- cursed loadstones), so reset any remaining inventory to normal */
- bypass_objlist(invent, FALSE);
+ /*
+ * Dropping a burning potion of oil while levitating can cause
+ * an explosion which might destroy some of hero's inventory,
+ * so the old code
+ * for (otmp = invent; otmp; otmp = otmp2) {
+ * otmp2 = otmp->nobj;
+ * n_dropped += drop(otmp);
+ * }
+ * was unreliable and could lead to an "object lost" panic.
+ *
+ * Use the bypass bit to mark items already processed (hence
+ * not droppable) and rescan inventory until no unbypassed
+ * items remain.
+ */
+ bypass_objlist(invent, FALSE); /* clear bypass bit for invent */
+ while ((otmp = nxt_unbypassed_obj(invent)) != 0)
+ n_dropped += drop(otmp);
+ /* we might not have dropped everything (worn armor, welded weapon,
+ cursed loadstones), so reset any remaining inventory to normal */
+ bypass_objlist(invent, FALSE);
} else {
- /* should coordinate with perm invent, maybe not show worn items */
- n = query_objlist("What would you like to drop?", invent,
- USE_INVLET|INVORDER_SORT, &pick_list,
- PICK_ANY, all_categories ? allow_all : allow_category);
- if (n > 0) {
- /*
- * picklist[] contains a set of pointers into inventory, but
- * as soon as something gets dropped, they might become stale
- * (see the drop_everything code above for an explanation).
- * Just checking to see whether one is still in the invent
- * chain is not sufficient validation since destroyed items
- * will be freed and items we've split here might have already
- * reused that memory and put the same pointer value back into
- * invent. Ditto for using invlet to validate. So we start
- * by setting bypass on all of invent, then check each pointer
- * to verify that it is in invent and has that bit set.
- */
- bypass_objlist(invent, TRUE);
- for (i = 0; i < n; i++) {
- otmp = pick_list[i].item.a_obj;
- for (otmp2 = invent; otmp2; otmp2 = otmp2->nobj)
- if (otmp2 == otmp) break;
- if (!otmp2 || !otmp2->bypass) continue;
- /* found next selected invent item */
- cnt = pick_list[i].count;
- if (cnt < otmp->quan) {
- if (welded(otmp)) {
- ; /* don't split */
- } else if (otmp->otyp == LOADSTONE && otmp->cursed) {
- /* same kludge as getobj(), for canletgo()'s use */
- otmp->corpsenm = (int) cnt; /* don't split */
- } else {
- otmp = splitobj(otmp, cnt);
- }
- }
- n_dropped += drop(otmp);
- }
- bypass_objlist(invent, FALSE); /* reset invent to normal */
- free((genericptr_t) pick_list);
- }
+ /* should coordinate with perm invent, maybe not show worn items */
+ n = query_objlist("What would you like to drop?", invent,
+ USE_INVLET|INVORDER_SORT, &pick_list,
+ PICK_ANY, all_categories ? allow_all : allow_category);
+ if (n > 0) {
+ /*
+ * picklist[] contains a set of pointers into inventory, but
+ * as soon as something gets dropped, they might become stale
+ * (see the drop_everything code above for an explanation).
+ * Just checking to see whether one is still in the invent
+ * chain is not sufficient validation since destroyed items
+ * will be freed and items we've split here might have already
+ * reused that memory and put the same pointer value back into
+ * invent. Ditto for using invlet to validate. So we start
+ * by setting bypass on all of invent, then check each pointer
+ * to verify that it is in invent and has that bit set.
+ */
+ bypass_objlist(invent, TRUE);
+ for (i = 0; i < n; i++) {
+ otmp = pick_list[i].item.a_obj;
+ for (otmp2 = invent; otmp2; otmp2 = otmp2->nobj)
+ if (otmp2 == otmp) break;
+ if (!otmp2 || !otmp2->bypass) continue;
+ /* found next selected invent item */
+ cnt = pick_list[i].count;
+ if (cnt < otmp->quan) {
+ if (welded(otmp)) {
+ ; /* don't split */
+ } else if (otmp->otyp == LOADSTONE && otmp->cursed) {
+ /* same kludge as getobj(), for canletgo()'s use */
+ otmp->corpsenm = (int) cnt; /* don't split */
+ } else {
+ otmp = splitobj(otmp, cnt);
+ }
+ }
+ n_dropped += drop(otmp);
+ }
+ bypass_objlist(invent, FALSE); /* reset invent to normal */
+ free((genericptr_t) pick_list);
+ }
}
drop_done:
int
dodown()
{
- struct trap *trap = 0;
- boolean stairs_down = ((u.ux == xdnstair && u.uy == ydnstair) ||
- (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)),
- ladder_down = (u.ux == xdnladder && u.uy == ydnladder);
-
- if(!youmonst.data->mmove) {
- You("are rooted %s.",
- Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
- "in place" : "to the ground");
- nomul(0);
- return 1;
- }
-
- if (stucksteed(TRUE)) {
- return 0;
- }
- /* Levitation might be blocked, but player can still use '>' to
- turn off controlled levitaiton */
- if (HLevitation || ELevitation) {
- if ((HLevitation & I_SPECIAL) || (ELevitation & W_ARTI)) {
- /* end controlled levitation */
- if (ELevitation & W_ARTI) {
- struct obj *obj;
-
- for(obj = invent; obj; obj = obj->nobj) {
- if (obj->oartifact &&
- artifact_has_invprop(obj, LEVITATION)) {
- if (obj->age < monstermoves)
- obj->age = monstermoves;
- obj->age += rnz(100);
- }
- }
- }
- if (float_down(I_SPECIAL|TIMEOUT, W_ARTI)) {
- return 1; /* came down, so moved */
- } else if (!HLevitation && !ELevitation) {
- Your("latent levitation ceases.");
- return 1; /* did something, effectively moved */
- }
- }
- if (BLevitation) {
- ; /* weren't actually floating after all */
- } else if (Blind) {
- /* Avoid alerting player to an unknown stair or ladder.
- * Changes the message for a covered, known staircase
- * too; staircase knowledge is not stored anywhere.
- */
- if (stairs_down)
- stairs_down =
- (glyph_to_cmap(levl[u.ux][u.uy].glyph) == S_dnstair);
- else if (ladder_down)
- ladder_down =
- (glyph_to_cmap(levl[u.ux][u.uy].glyph) == S_dnladder);
- }
- floating_above(stairs_down ? "stairs" : ladder_down ?
- "ladder" : surface(u.ux, u.uy));
- return (0); /* didn't move */
- }
- if (!stairs_down && !ladder_down) {
- trap = t_at(u.ux,u.uy);
- if (trap && uteetering_at_seen_pit(trap)) {
- dotrap(trap, TOOKPLUNGE);
- return(1);
- } else if (!trap ||
- (trap->ttyp != TRAPDOOR && trap->ttyp != HOLE) ||
- !Can_fall_thru(&u.uz) || !trap->tseen) {
- if (flags.autodig && !context.nopick &&
- uwep && is_pick(uwep)) {
- return use_pick_axe2(uwep);
- } else {
- You_cant("go down here.");
- return(0);
- }
- }
- }
- if(u.ustuck) {
- You("are %s, and cannot go down.",
- !u.uswallow ? "being held" : is_animal(u.ustuck->data) ?
- "swallowed" : "engulfed");
- return(1);
- }
- if (on_level(&valley_level, &u.uz) && !u.uevent.gehennom_entered) {
- You("are standing at the gate to Gehennom.");
- pline("Unspeakable cruelty and harm lurk down there.");
- if (yn("Are you sure you want to enter?") != 'y')
- return(0);
- else pline("So be it.");
- u.uevent.gehennom_entered = 1; /* don't ask again */
- }
-
- if(!next_to_u()) {
- You("are held back by your pet!");
- return(0);
- }
-
- if (trap)
- You("%s %s.", Flying ? "fly" : locomotion(youmonst.data, "jump"),
- trap->ttyp == HOLE ? "down the hole" : "through the trap door");
-
- if (trap && Is_stronghold(&u.uz)) {
- goto_hell(FALSE, TRUE);
- } else {
- at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
- next_level(!trap);
- at_ladder = FALSE;
- }
- return(1);
+ struct trap *trap = 0;
+ boolean stairs_down = ((u.ux == xdnstair && u.uy == ydnstair) ||
+ (u.ux == sstairs.sx && u.uy == sstairs.sy && !sstairs.up)),
+ ladder_down = (u.ux == xdnladder && u.uy == ydnladder);
+
+ if(!youmonst.data->mmove) {
+ You("are rooted %s.",
+ Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
+ "in place" : "to the ground");
+ nomul(0);
+ return 1;
+ }
+
+ if (stucksteed(TRUE)) {
+ return 0;
+ }
+ /* Levitation might be blocked, but player can still use '>' to
+ turn off controlled levitaiton */
+ if (HLevitation || ELevitation) {
+ if ((HLevitation & I_SPECIAL) || (ELevitation & W_ARTI)) {
+ /* end controlled levitation */
+ if (ELevitation & W_ARTI) {
+ struct obj *obj;
+
+ for(obj = invent; obj; obj = obj->nobj) {
+ if (obj->oartifact &&
+ artifact_has_invprop(obj, LEVITATION)) {
+ if (obj->age < monstermoves)
+ obj->age = monstermoves;
+ obj->age += rnz(100);
+ }
+ }
+ }
+ if (float_down(I_SPECIAL|TIMEOUT, W_ARTI)) {
+ return 1; /* came down, so moved */
+ } else if (!HLevitation && !ELevitation) {
+ Your("latent levitation ceases.");
+ return 1; /* did something, effectively moved */
+ }
+ }
+ if (BLevitation) {
+ ; /* weren't actually floating after all */
+ } else if (Blind) {
+ /* Avoid alerting player to an unknown stair or ladder.
+ * Changes the message for a covered, known staircase
+ * too; staircase knowledge is not stored anywhere.
+ */
+ if (stairs_down)
+ stairs_down =
+ (glyph_to_cmap(levl[u.ux][u.uy].glyph) == S_dnstair);
+ else if (ladder_down)
+ ladder_down =
+ (glyph_to_cmap(levl[u.ux][u.uy].glyph) == S_dnladder);
+ }
+ floating_above(stairs_down ? "stairs" : ladder_down ?
+ "ladder" : surface(u.ux, u.uy));
+ return (0); /* didn't move */
+ }
+ if (!stairs_down && !ladder_down) {
+ trap = t_at(u.ux,u.uy);
+ if (trap && uteetering_at_seen_pit(trap)) {
+ dotrap(trap, TOOKPLUNGE);
+ return(1);
+ } else if (!trap ||
+ (trap->ttyp != TRAPDOOR && trap->ttyp != HOLE) ||
+ !Can_fall_thru(&u.uz) || !trap->tseen) {
+ if (flags.autodig && !context.nopick &&
+ uwep && is_pick(uwep)) {
+ return use_pick_axe2(uwep);
+ } else {
+ You_cant("go down here.");
+ return(0);
+ }
+ }
+ }
+ if(u.ustuck) {
+ You("are %s, and cannot go down.",
+ !u.uswallow ? "being held" : is_animal(u.ustuck->data) ?
+ "swallowed" : "engulfed");
+ return(1);
+ }
+ if (on_level(&valley_level, &u.uz) && !u.uevent.gehennom_entered) {
+ You("are standing at the gate to Gehennom.");
+ pline("Unspeakable cruelty and harm lurk down there.");
+ if (yn("Are you sure you want to enter?") != 'y')
+ return(0);
+ else pline("So be it.");
+ u.uevent.gehennom_entered = 1; /* don't ask again */
+ }
+
+ if(!next_to_u()) {
+ You("are held back by your pet!");
+ return(0);
+ }
+
+ if (trap)
+ You("%s %s.", Flying ? "fly" : locomotion(youmonst.data, "jump"),
+ trap->ttyp == HOLE ? "down the hole" : "through the trap door");
+
+ if (trap && Is_stronghold(&u.uz)) {
+ goto_hell(FALSE, TRUE);
+ } else {
+ at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
+ next_level(!trap);
+ at_ladder = FALSE;
+ }
+ return(1);
}
int
doup()
{
- if(!youmonst.data->mmove) {
- You("are rooted %s.",
- Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
- "in place" : "to the ground");
- nomul(0);
- return 1;
- }
-
- /* "up" to get out of a pit... */
- if (u.utrap && u.utraptype == TT_PIT) {
- climb_pit();
- return 1;
- }
-
- if( (u.ux != xupstair || u.uy != yupstair)
- && (!xupladder || u.ux != xupladder || u.uy != yupladder)
- && (!sstairs.sx || u.ux != sstairs.sx || u.uy != sstairs.sy
- || !sstairs.up)
- ) {
- You_cant("go up here.");
- return(0);
- }
- if (stucksteed(TRUE)) {
- return(0);
- }
- if(u.ustuck) {
- You("are %s, and cannot go up.",
- !u.uswallow ? "being held" : is_animal(u.ustuck->data) ?
- "swallowed" : "engulfed");
- return(1);
- }
- if(near_capacity() > SLT_ENCUMBER) {
- /* No levitation check; inv_weight() already allows for it */
- Your("load is too heavy to climb the %s.",
- levl[u.ux][u.uy].typ == STAIRS ? "stairs" : "ladder");
- return(1);
- }
- if(ledger_no(&u.uz) == 1) {
- if (yn("Beware, there will be no return! Still climb?") != 'y')
- return(0);
- }
- if(!next_to_u()) {
- You("are held back by your pet!");
- return(0);
- }
- at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
- prev_level(TRUE);
- at_ladder = FALSE;
- return(1);
+ if(!youmonst.data->mmove) {
+ You("are rooted %s.",
+ Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
+ "in place" : "to the ground");
+ nomul(0);
+ return 1;
+ }
+
+ /* "up" to get out of a pit... */
+ if (u.utrap && u.utraptype == TT_PIT) {
+ climb_pit();
+ return 1;
+ }
+
+ if( (u.ux != xupstair || u.uy != yupstair)
+ && (!xupladder || u.ux != xupladder || u.uy != yupladder)
+ && (!sstairs.sx || u.ux != sstairs.sx || u.uy != sstairs.sy
+ || !sstairs.up)
+ ) {
+ You_cant("go up here.");
+ return(0);
+ }
+ if (stucksteed(TRUE)) {
+ return(0);
+ }
+ if(u.ustuck) {
+ You("are %s, and cannot go up.",
+ !u.uswallow ? "being held" : is_animal(u.ustuck->data) ?
+ "swallowed" : "engulfed");
+ return(1);
+ }
+ if(near_capacity() > SLT_ENCUMBER) {
+ /* No levitation check; inv_weight() already allows for it */
+ Your("load is too heavy to climb the %s.",
+ levl[u.ux][u.uy].typ == STAIRS ? "stairs" : "ladder");
+ return(1);
+ }
+ if(ledger_no(&u.uz) == 1) {
+ if (yn("Beware, there will be no return! Still climb?") != 'y')
+ return(0);
+ }
+ if(!next_to_u()) {
+ You("are held back by your pet!");
+ return(0);
+ }
+ at_ladder = (boolean) (levl[u.ux][u.uy].typ == LADDER);
+ prev_level(TRUE);
+ at_ladder = FALSE;
+ return(1);
}
d_level save_dlevel = {0, 0};
STATIC_OVL int
currentlevel_rewrite()
{
- register int fd;
- char whynot[BUFSZ];
-
- /* since level change might be a bit slow, flush any buffered screen
- * output (like "you fall through a trap door") */
- mark_synch();
-
- fd = create_levelfile(ledger_no(&u.uz), whynot);
- if (fd < 0) {
- /*
- * This is not quite impossible: e.g., we may have
- * exceeded our quota. If that is the case then we
- * cannot leave this level, and cannot save either.
- * Another possibility is that the directory was not
- * writable.
- */
- pline1(whynot);
- return -1;
- }
+ register int fd;
+ char whynot[BUFSZ];
+
+ /* since level change might be a bit slow, flush any buffered screen
+ * output (like "you fall through a trap door") */
+ mark_synch();
+
+ fd = create_levelfile(ledger_no(&u.uz), whynot);
+ if (fd < 0) {
+ /*
+ * This is not quite impossible: e.g., we may have
+ * exceeded our quota. If that is the case then we
+ * cannot leave this level, and cannot save either.
+ * Another possibility is that the directory was not
+ * writable.
+ */
+ pline1(whynot);
+ return -1;
+ }
#ifdef MFLOPPY
- if (!savelev(fd, ledger_no(&u.uz), COUNT_SAVE)) {
- (void) close(fd);
- delete_levelfile(ledger_no(&u.uz));
- pline("NetHack is out of disk space for making levels!");
- You("can save, quit, or continue playing.");
- return -1;
- }
+ if (!savelev(fd, ledger_no(&u.uz), COUNT_SAVE)) {
+ (void) close(fd);
+ delete_levelfile(ledger_no(&u.uz));
+ pline("NetHack is out of disk space for making levels!");
+ You("can save, quit, or continue playing.");
+ return -1;
+ }
#endif
- return fd;
+ return fd;
}
#ifdef INSURANCE
void
save_currentstate()
{
- int fd;
-
- if (flags.ins_chkpt) {
- /* write out just-attained level, with pets and everything */
- fd = currentlevel_rewrite();
- if(fd < 0) return;
- bufon(fd);
- savelev(fd,ledger_no(&u.uz), WRITE_SAVE);
- bclose(fd);
- }
-
- /* write out non-level state */
- savestateinlock();
+ int fd;
+
+ if (flags.ins_chkpt) {
+ /* write out just-attained level, with pets and everything */
+ fd = currentlevel_rewrite();
+ if(fd < 0) return;
+ bufon(fd);
+ savelev(fd,ledger_no(&u.uz), WRITE_SAVE);
+ bclose(fd);
+ }
+
+ /* write out non-level state */
+ savestateinlock();
}
#endif
badspot(x, y)
register xchar x, y;
{
- return((levl[x][y].typ != ROOM && levl[x][y].typ != AIR &&
- levl[x][y].typ != CORR) || MON_AT(x, y));
+ return((levl[x][y].typ != ROOM && levl[x][y].typ != AIR &&
+ levl[x][y].typ != CORR) || MON_AT(x, y));
}
*/
d_level *newlevel;
boolean at_stairs, falling, portal;
{
- int fd, l_idx;
- xchar new_ledger;
- boolean cant_go_back,
- up = (depth(newlevel) < depth(&u.uz)),
- newdungeon = (u.uz.dnum != newlevel->dnum),
- was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz),
- familiar = FALSE;
- boolean new = FALSE; /* made a new level? */
- struct monst *mtmp;
- char whynot[BUFSZ];
-
- if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
- newlevel->dlevel = dunlevs_in_dungeon(newlevel);
- if (newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
- if (!u.uhave.amulet) return; /* must have the Amulet */
- if (!wizard) /* wizard ^V can bypass Earth level */
- assign_level(newlevel, &earth_level); /* (redundant) */
- }
- new_ledger = ledger_no(newlevel);
- if (new_ledger <= 0)
- done(ESCAPED); /* in fact < 0 is impossible */
-
- /* If you have the amulet and are trying to get out of Gehennom, going
- * up a set of stairs sometimes does some very strange things!
- * Biased against law and towards chaos, but not nearly as strongly
- * as it used to be (prior to 3.2.0).
- * Odds: old new
- * "up" L N C "up" L N C
- * +1 75.0 75.0 75.0 +1 75.0 75.0 75.0
- * 0 0.0 12.5 25.0 0 6.25 8.33 12.5
- * -1 8.33 4.17 0.0 -1 6.25 8.33 12.5
- * -2 8.33 4.17 0.0 -2 6.25 8.33 0.0
- * -3 8.33 4.17 0.0 -3 6.25 0.0 0.0
- */
- if (Inhell && up && u.uhave.amulet && !newdungeon && !portal &&
- (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)-3)) {
- if (!rn2(4)) {
- int odds = 3 + (int)u.ualign.type, /* 2..4 */
- diff = odds <= 1 ? 0 : rn2(odds); /* paranoia */
-
- if (diff != 0) {
- assign_rnd_level(newlevel, &u.uz, diff);
- /* if inside the tower, stay inside */
- if (was_in_W_tower &&
- !On_W_tower_level(newlevel)) diff = 0;
- }
- if (diff == 0)
- assign_level(newlevel, &u.uz);
-
- new_ledger = ledger_no(newlevel);
-
- pline("A mysterious force momentarily surrounds you...");
- if (on_level(newlevel, &u.uz)) {
- (void) safe_teleds(FALSE);
- (void) next_to_u();
- return;
- } else
- at_stairs = at_ladder = FALSE;
- }
- }
-
- /* Prevent the player from going past the first quest level unless
- * (s)he has been given the go-ahead by the leader.
- */
- if (on_level(&u.uz, &qstart_level) && !newdungeon && !ok_to_quest()) {
- pline("A mysterious force prevents you from descending.");
- return;
- }
-
- if (on_level(newlevel, &u.uz)) return; /* this can happen */
-
- /* tethered movement makes level change while trapped feasible */
- if (u.utrap && u.utraptype == TT_BURIEDBALL)
- buried_ball_to_punishment(); /* (before we save/leave old level) */
-
- fd = currentlevel_rewrite();
- if (fd < 0) return;
-
- if (falling) /* assuming this is only trap door or hole */
- impact_drop((struct obj *)0, u.ux, u.uy, newlevel->dlevel);
-
- check_special_room(TRUE); /* probably was a trap door */
- if (Punished) unplacebc();
- u.utrap = 0; /* needed in level_tele */
- fill_pit(u.ux, u.uy);
- u.ustuck = 0; /* idem */
- u.uinwater = 0;
- u.uundetected = 0; /* not hidden, even if means are available */
- keepdogs(FALSE);
- if (u.uswallow) /* idem */
- u.uswldtim = u.uswallow = 0;
- recalc_mapseen(); /* recalculate map overview before we leave the level */
- /*
- * We no longer see anything on the level. Make sure that this
- * follows u.uswallow set to null since uswallow overrides all
- * normal vision.
- */
- vision_recalc(2);
-
- /*
- * Save the level we're leaving. If we're entering the endgame,
- * we can get rid of all existing levels because they cannot be
- * reached any more. We still need to use savelev()'s cleanup
- * for the level being left, to recover dynamic memory in use and
- * to avoid dangling timers and light sources.
- */
- cant_go_back = (newdungeon && In_endgame(newlevel));
- if (!cant_go_back) {
- update_mlstmv(); /* current monsters are becoming inactive */
- bufon(fd); /* use buffered output */
- }
- savelev(fd, ledger_no(&u.uz),
- cant_go_back ? FREE_SAVE : (WRITE_SAVE | FREE_SAVE));
- bclose(fd);
- if (cant_go_back) {
- /* discard unreachable levels; keep #0 */
- for (l_idx = maxledgerno(); l_idx > 0; --l_idx)
- delete_levelfile(l_idx);
- /* mark #overview data for all dungeon branches as uninteresting */
- for (l_idx = 0; l_idx < n_dgns; ++l_idx)
- remdun_mapseen(l_idx);
- }
-
- if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
- assign_graphics(Is_rogue_level(newlevel) ? ROGUESET : PRIMARY);
+ int fd, l_idx;
+ xchar new_ledger;
+ boolean cant_go_back,
+ up = (depth(newlevel) < depth(&u.uz)),
+ newdungeon = (u.uz.dnum != newlevel->dnum),
+ was_in_W_tower = In_W_tower(u.ux, u.uy, &u.uz),
+ familiar = FALSE;
+ boolean new = FALSE; /* made a new level? */
+ struct monst *mtmp;
+ char whynot[BUFSZ];
+
+ if (dunlev(newlevel) > dunlevs_in_dungeon(newlevel))
+ newlevel->dlevel = dunlevs_in_dungeon(newlevel);
+ if (newdungeon && In_endgame(newlevel)) { /* 1st Endgame Level !!! */
+ if (!u.uhave.amulet) return; /* must have the Amulet */
+ if (!wizard) /* wizard ^V can bypass Earth level */
+ assign_level(newlevel, &earth_level); /* (redundant) */
+ }
+ new_ledger = ledger_no(newlevel);
+ if (new_ledger <= 0)
+ done(ESCAPED); /* in fact < 0 is impossible */
+
+ /* If you have the amulet and are trying to get out of Gehennom, going
+ * up a set of stairs sometimes does some very strange things!
+ * Biased against law and towards chaos, but not nearly as strongly
+ * as it used to be (prior to 3.2.0).
+ * Odds: old new
+ * "up" L N C "up" L N C
+ * +1 75.0 75.0 75.0 +1 75.0 75.0 75.0
+ * 0 0.0 12.5 25.0 0 6.25 8.33 12.5
+ * -1 8.33 4.17 0.0 -1 6.25 8.33 12.5
+ * -2 8.33 4.17 0.0 -2 6.25 8.33 0.0
+ * -3 8.33 4.17 0.0 -3 6.25 0.0 0.0
+ */
+ if (Inhell && up && u.uhave.amulet && !newdungeon && !portal &&
+ (dunlev(&u.uz) < dunlevs_in_dungeon(&u.uz)-3)) {
+ if (!rn2(4)) {
+ int odds = 3 + (int)u.ualign.type, /* 2..4 */
+ diff = odds <= 1 ? 0 : rn2(odds); /* paranoia */
+
+ if (diff != 0) {
+ assign_rnd_level(newlevel, &u.uz, diff);
+ /* if inside the tower, stay inside */
+ if (was_in_W_tower &&
+ !On_W_tower_level(newlevel)) diff = 0;
+ }
+ if (diff == 0)
+ assign_level(newlevel, &u.uz);
+
+ new_ledger = ledger_no(newlevel);
+
+ pline("A mysterious force momentarily surrounds you...");
+ if (on_level(newlevel, &u.uz)) {
+ (void) safe_teleds(FALSE);
+ (void) next_to_u();
+ return;
+ } else
+ at_stairs = at_ladder = FALSE;
+ }
+ }
+
+ /* Prevent the player from going past the first quest level unless
+ * (s)he has been given the go-ahead by the leader.
+ */
+ if (on_level(&u.uz, &qstart_level) && !newdungeon && !ok_to_quest()) {
+ pline("A mysterious force prevents you from descending.");
+ return;
+ }
+
+ if (on_level(newlevel, &u.uz)) return; /* this can happen */
+
+ /* tethered movement makes level change while trapped feasible */
+ if (u.utrap && u.utraptype == TT_BURIEDBALL)
+ buried_ball_to_punishment(); /* (before we save/leave old level) */
+
+ fd = currentlevel_rewrite();
+ if (fd < 0) return;
+
+ if (falling) /* assuming this is only trap door or hole */
+ impact_drop((struct obj *)0, u.ux, u.uy, newlevel->dlevel);
+
+ check_special_room(TRUE); /* probably was a trap door */
+ if (Punished) unplacebc();
+ u.utrap = 0; /* needed in level_tele */
+ fill_pit(u.ux, u.uy);
+ u.ustuck = 0; /* idem */
+ u.uinwater = 0;
+ u.uundetected = 0; /* not hidden, even if means are available */
+ keepdogs(FALSE);
+ if (u.uswallow) /* idem */
+ u.uswldtim = u.uswallow = 0;
+ recalc_mapseen(); /* recalculate map overview before we leave the level */
+ /*
+ * We no longer see anything on the level. Make sure that this
+ * follows u.uswallow set to null since uswallow overrides all
+ * normal vision.
+ */
+ vision_recalc(2);
+
+ /*
+ * Save the level we're leaving. If we're entering the endgame,
+ * we can get rid of all existing levels because they cannot be
+ * reached any more. We still need to use savelev()'s cleanup
+ * for the level being left, to recover dynamic memory in use and
+ * to avoid dangling timers and light sources.
+ */
+ cant_go_back = (newdungeon && In_endgame(newlevel));
+ if (!cant_go_back) {
+ update_mlstmv(); /* current monsters are becoming inactive */
+ bufon(fd); /* use buffered output */
+ }
+ savelev(fd, ledger_no(&u.uz),
+ cant_go_back ? FREE_SAVE : (WRITE_SAVE | FREE_SAVE));
+ bclose(fd);
+ if (cant_go_back) {
+ /* discard unreachable levels; keep #0 */
+ for (l_idx = maxledgerno(); l_idx > 0; --l_idx)
+ delete_levelfile(l_idx);
+ /* mark #overview data for all dungeon branches as uninteresting */
+ for (l_idx = 0; l_idx < n_dgns; ++l_idx)
+ remdun_mapseen(l_idx);
+ }
+
+ if (Is_rogue_level(newlevel) || Is_rogue_level(&u.uz))
+ assign_graphics(Is_rogue_level(newlevel) ? ROGUESET : PRIMARY);
#ifdef USE_TILES
- substitute_tiles(newlevel);
+ substitute_tiles(newlevel);
#endif
- /* record this level transition as a potential seen branch unless using
- * some non-standard means of transportation (level teleport).
- */
- if ((at_stairs || falling || portal) && (u.uz.dnum != newlevel->dnum))
- recbranch_mapseen(&u.uz, newlevel);
- assign_level(&u.uz0, &u.uz);
- assign_level(&u.uz, newlevel);
- assign_level(&u.utolev, newlevel);
- u.utotype = 0;
- if (dunlev_reached(&u.uz) < dunlev(&u.uz))
- dunlev_reached(&u.uz) = dunlev(&u.uz);
- reset_rndmonst(NON_PM); /* u.uz change affects monster generation */
-
- /* set default level change destination areas */
- /* the special level code may override these */
- (void) memset((genericptr_t) &updest, 0, sizeof updest);
- (void) memset((genericptr_t) &dndest, 0, sizeof dndest);
-
- if (!(level_info[new_ledger].flags & LFILE_EXISTS)) {
- /* entering this level for first time; make it now */
- if (level_info[new_ledger].flags & (FORGOTTEN|VISITED)) {
- impossible("goto_level: returning to discarded level?");
- level_info[new_ledger].flags &= ~(FORGOTTEN|VISITED);
- }
- mklev();
- new = TRUE; /* made the level */
- } else {
- /* returning to previously visited level; reload it */
- fd = open_levelfile(new_ledger, whynot);
- if (fd < 0) {
- pline1(whynot);
- pline("Probably someone removed it.");
- Strcpy(killer.name, whynot);
- done(TRICKED);
- /* we'll reach here if running in wizard mode */
- error("Cannot continue this game.");
- }
- minit(); /* ZEROCOMP */
- getlev(fd, hackpid, new_ledger, FALSE);
- (void) close(fd);
- oinit(); /* reassign level dependent obj probabilities */
- }
- /* do this prior to level-change pline messages */
- vision_reset(); /* clear old level's line-of-sight */
- vision_full_recalc = 0; /* don't let that reenable vision yet */
- flush_screen(-1); /* ensure all map flushes are postponed */
-
- if (portal && !In_endgame(&u.uz)) {
- /* find the portal on the new level */
- register struct trap *ttrap;
-
- for (ttrap = ftrap; ttrap; ttrap = ttrap->ntrap)
- if (ttrap->ttyp == MAGIC_PORTAL) break;
-
- if (!ttrap) panic("goto_level: no corresponding portal!");
- seetrap(ttrap);
- u_on_newpos(ttrap->tx, ttrap->ty);
- } else if (at_stairs && !In_endgame(&u.uz)) {
- if (up) {
- if (at_ladder)
- u_on_newpos(xdnladder, ydnladder);
- else if (newdungeon)
- u_on_sstairs(1);
- else
- u_on_dnstairs();
- /* you climb up the {stairs|ladder};
- fly up the stairs; fly up along the ladder */
- pline("%s %s up%s the %s.",
- (Punished && !Levitation) ? "With great effort you" :
- "You",
- Flying ? "fly" : "climb",
- (Flying && at_ladder) ? " along" : "",
- at_ladder ? "ladder" : "stairs");
- } else { /* down */
- if (at_ladder)
- u_on_newpos(xupladder, yupladder);
- else if (newdungeon)
- u_on_sstairs(0);
- else
- u_on_upstairs();
- if (!u.dz) {
- ; /* stayed on same level? (no transit effects) */
- } else if (Flying) {
- if (flags.verbose)
- You("fly down %s.",
- at_ladder ? "along the ladder" : "the stairs");
- } else if (near_capacity() > UNENCUMBERED ||
- Punished || Fumbling) {
- You("fall down the %s.", at_ladder ? "ladder" : "stairs");
- if (Punished) {
- drag_down();
- if (carried(uball)) {
- if (uwep == uball)
- setuwep((struct obj *)0);
- if (uswapwep == uball)
- setuswapwep((struct obj *)0);
- if (uquiver == uball)
- setuqwep((struct obj *)0);
- freeinv(uball);
- }
- }
- /* falling off steed has its own losehp() call */
- if (u.usteed)
- dismount_steed(DISMOUNT_FELL);
- else
- losehp(Maybe_Half_Phys(rnd(3)),
- at_ladder ? "falling off a ladder" :
- "tumbling down a flight of stairs",
- KILLED_BY);
- selftouch("Falling, you");
- } else { /* ordinary descent */
- if (flags.verbose)
- You("%s.", at_ladder ? "climb down the ladder" :
- "descend the stairs");
- }
- }
- } else { /* trap door or level_tele or In_endgame */
- u_on_rndspot((up ? 1 : 0) | (was_in_W_tower ? 2 : 0));
- if (falling) {
- if (Punished) ballfall();
- selftouch("Falling, you");
- }
- }
-
- if (Punished) placebc();
- obj_delivery(FALSE);
- losedogs();
- kill_genocided_monsters(); /* for those wiped out while in limbo */
- /*
- * Expire all timers that have gone off while away. Must be
- * after migrating monsters and objects are delivered
- * (losedogs and obj_delivery).
- */
- run_timers();
-
- initrack();
-
- if ((mtmp = m_at(u.ux, u.uy)) != 0 && mtmp != u.usteed) {
- /* There's a monster at your target destination; it might be one
- which accompanied you--see mon_arrive(dogmove.c)--or perhaps
- it was already here. Randomly move you to an adjacent spot
- or else the monster to any nearby location. Prior to 3.3.0
- the latter was done unconditionally. */
- coord cc;
-
- if (!rn2(2) &&
- enexto(&cc, u.ux, u.uy, youmonst.data) &&
- distu(cc.x, cc.y) <= 2)
- u_on_newpos(cc.x, cc.y); /*[maybe give message here?]*/
- else
- mnexto(mtmp);
-
- if ((mtmp = m_at(u.ux, u.uy)) != 0) {
- /* there was an unconditional impossible("mnearto failed")
- here, but it's not impossible and we're prepared to cope
- with the situation, so only say something when debugging */
- if (wizard) pline("(monster in hero's way)");
- if (!rloc(mtmp, TRUE))
- /* no room to move it; send it away, to return later */
- migrate_to_level(mtmp, ledger_no(&u.uz),
- MIGR_RANDOM, (coord *)0);
- }
- }
-
- /* initial movement of bubbles just before vision_recalc */
- if (Is_waterlevel(&u.uz))
- movebubbles();
-
- if (level_info[new_ledger].flags & FORGOTTEN) {
- forget_map(ALL_MAP); /* forget the map */
- forget_traps(); /* forget all traps too */
- familiar = TRUE;
- level_info[new_ledger].flags &= ~FORGOTTEN;
- }
-
- /* Reset the screen. */
- vision_reset(); /* reset the blockages */
- docrt(); /* does a full vision recalc */
- flush_screen(-1);
-
- /*
- * Move all plines beyond the screen reset.
- */
-
- /* special levels can have a custom arrival message */
- deliver_splev_message();
-
- /* give room entrance message, if any */
- check_special_room(FALSE);
-
- /* deliver objects traveling with player */
- obj_delivery(TRUE);
-
- /* Check whether we just entered Gehennom. */
- if (!In_hell(&u.uz0) && Inhell) {
- if (Is_valley(&u.uz)) {
- You("arrive at the Valley of the Dead...");
- pline_The("odor of burnt flesh and decay pervades the air.");
+ /* record this level transition as a potential seen branch unless using
+ * some non-standard means of transportation (level teleport).
+ */
+ if ((at_stairs || falling || portal) && (u.uz.dnum != newlevel->dnum))
+ recbranch_mapseen(&u.uz, newlevel);
+ assign_level(&u.uz0, &u.uz);
+ assign_level(&u.uz, newlevel);
+ assign_level(&u.utolev, newlevel);
+ u.utotype = 0;
+ if (dunlev_reached(&u.uz) < dunlev(&u.uz))
+ dunlev_reached(&u.uz) = dunlev(&u.uz);
+ reset_rndmonst(NON_PM); /* u.uz change affects monster generation */
+
+ /* set default level change destination areas */
+ /* the special level code may override these */
+ (void) memset((genericptr_t) &updest, 0, sizeof updest);
+ (void) memset((genericptr_t) &dndest, 0, sizeof dndest);
+
+ if (!(level_info[new_ledger].flags & LFILE_EXISTS)) {
+ /* entering this level for first time; make it now */
+ if (level_info[new_ledger].flags & (FORGOTTEN|VISITED)) {
+ impossible("goto_level: returning to discarded level?");
+ level_info[new_ledger].flags &= ~(FORGOTTEN|VISITED);
+ }
+ mklev();
+ new = TRUE; /* made the level */
+ } else {
+ /* returning to previously visited level; reload it */
+ fd = open_levelfile(new_ledger, whynot);
+ if (fd < 0) {
+ pline1(whynot);
+ pline("Probably someone removed it.");
+ Strcpy(killer.name, whynot);
+ done(TRICKED);
+ /* we'll reach here if running in wizard mode */
+ error("Cannot continue this game.");
+ }
+ minit(); /* ZEROCOMP */
+ getlev(fd, hackpid, new_ledger, FALSE);
+ (void) close(fd);
+ oinit(); /* reassign level dependent obj probabilities */
+ }
+ /* do this prior to level-change pline messages */
+ vision_reset(); /* clear old level's line-of-sight */
+ vision_full_recalc = 0; /* don't let that reenable vision yet */
+ flush_screen(-1); /* ensure all map flushes are postponed */
+
+ if (portal && !In_endgame(&u.uz)) {
+ /* find the portal on the new level */
+ register struct trap *ttrap;
+
+ for (ttrap = ftrap; ttrap; ttrap = ttrap->ntrap)
+ if (ttrap->ttyp == MAGIC_PORTAL) break;
+
+ if (!ttrap) panic("goto_level: no corresponding portal!");
+ seetrap(ttrap);
+ u_on_newpos(ttrap->tx, ttrap->ty);
+ } else if (at_stairs && !In_endgame(&u.uz)) {
+ if (up) {
+ if (at_ladder)
+ u_on_newpos(xdnladder, ydnladder);
+ else if (newdungeon)
+ u_on_sstairs(1);
+ else
+ u_on_dnstairs();
+ /* you climb up the {stairs|ladder};
+ fly up the stairs; fly up along the ladder */
+ pline("%s %s up%s the %s.",
+ (Punished && !Levitation) ? "With great effort you" :
+ "You",
+ Flying ? "fly" : "climb",
+ (Flying && at_ladder) ? " along" : "",
+ at_ladder ? "ladder" : "stairs");
+ } else { /* down */
+ if (at_ladder)
+ u_on_newpos(xupladder, yupladder);
+ else if (newdungeon)
+ u_on_sstairs(0);
+ else
+ u_on_upstairs();
+ if (!u.dz) {
+ ; /* stayed on same level? (no transit effects) */
+ } else if (Flying) {
+ if (flags.verbose)
+ You("fly down %s.",
+ at_ladder ? "along the ladder" : "the stairs");
+ } else if (near_capacity() > UNENCUMBERED ||
+ Punished || Fumbling) {
+ You("fall down the %s.", at_ladder ? "ladder" : "stairs");
+ if (Punished) {
+ drag_down();
+ if (carried(uball)) {
+ if (uwep == uball)
+ setuwep((struct obj *)0);
+ if (uswapwep == uball)
+ setuswapwep((struct obj *)0);
+ if (uquiver == uball)
+ setuqwep((struct obj *)0);
+ freeinv(uball);
+ }
+ }
+ /* falling off steed has its own losehp() call */
+ if (u.usteed)
+ dismount_steed(DISMOUNT_FELL);
+ else
+ losehp(Maybe_Half_Phys(rnd(3)),
+ at_ladder ? "falling off a ladder" :
+ "tumbling down a flight of stairs",
+ KILLED_BY);
+ selftouch("Falling, you");
+ } else { /* ordinary descent */
+ if (flags.verbose)
+ You("%s.", at_ladder ? "climb down the ladder" :
+ "descend the stairs");
+ }
+ }
+ } else { /* trap door or level_tele or In_endgame */
+ u_on_rndspot((up ? 1 : 0) | (was_in_W_tower ? 2 : 0));
+ if (falling) {
+ if (Punished) ballfall();
+ selftouch("Falling, you");
+ }
+ }
+
+ if (Punished) placebc();
+ obj_delivery(FALSE);
+ losedogs();
+ kill_genocided_monsters(); /* for those wiped out while in limbo */
+ /*
+ * Expire all timers that have gone off while away. Must be
+ * after migrating monsters and objects are delivered
+ * (losedogs and obj_delivery).
+ */
+ run_timers();
+
+ initrack();
+
+ if ((mtmp = m_at(u.ux, u.uy)) != 0 && mtmp != u.usteed) {
+ /* There's a monster at your target destination; it might be one
+ which accompanied you--see mon_arrive(dogmove.c)--or perhaps
+ it was already here. Randomly move you to an adjacent spot
+ or else the monster to any nearby location. Prior to 3.3.0
+ the latter was done unconditionally. */
+ coord cc;
+
+ if (!rn2(2) &&
+ enexto(&cc, u.ux, u.uy, youmonst.data) &&
+ distu(cc.x, cc.y) <= 2)
+ u_on_newpos(cc.x, cc.y); /*[maybe give message here?]*/
+ else
+ mnexto(mtmp);
+
+ if ((mtmp = m_at(u.ux, u.uy)) != 0) {
+ /* there was an unconditional impossible("mnearto failed")
+ here, but it's not impossible and we're prepared to cope
+ with the situation, so only say something when debugging */
+ if (wizard) pline("(monster in hero's way)");
+ if (!rloc(mtmp, TRUE))
+ /* no room to move it; send it away, to return later */
+ migrate_to_level(mtmp, ledger_no(&u.uz),
+ MIGR_RANDOM, (coord *)0);
+ }
+ }
+
+ /* initial movement of bubbles just before vision_recalc */
+ if (Is_waterlevel(&u.uz))
+ movebubbles();
+
+ if (level_info[new_ledger].flags & FORGOTTEN) {
+ forget_map(ALL_MAP); /* forget the map */
+ forget_traps(); /* forget all traps too */
+ familiar = TRUE;
+ level_info[new_ledger].flags &= ~FORGOTTEN;
+ }
+
+ /* Reset the screen. */
+ vision_reset(); /* reset the blockages */
+ docrt(); /* does a full vision recalc */
+ flush_screen(-1);
+
+ /*
+ * Move all plines beyond the screen reset.
+ */
+
+ /* special levels can have a custom arrival message */
+ deliver_splev_message();
+
+ /* give room entrance message, if any */
+ check_special_room(FALSE);
+
+ /* deliver objects traveling with player */
+ obj_delivery(TRUE);
+
+ /* Check whether we just entered Gehennom. */
+ if (!In_hell(&u.uz0) && Inhell) {
+ if (Is_valley(&u.uz)) {
+ You("arrive at the Valley of the Dead...");
+ pline_The("odor of burnt flesh and decay pervades the air.");
#ifdef MICRO
- display_nhwindow(WIN_MESSAGE, FALSE);
+ display_nhwindow(WIN_MESSAGE, FALSE);
#endif
- You_hear("groans and moans everywhere.");
- } else pline("It is hot here. You smell smoke...");
- }
- /* in case we've managed to bypass the Valley's stairway down */
- if (Inhell && !Is_valley(&u.uz)) u.uevent.gehennom_entered = 1;
-
- if (familiar) {
- static const char * const fam_msgs[4] = {
- "You have a sense of deja vu.",
- "You feel like you've been here before.",
- "This place %s familiar...",
- 0 /* no message */
- };
- static const char * const halu_fam_msgs[4] = {
- "Whoa! Everything %s different.",
- "You are surrounded by twisty little passages, all alike.",
- "Gee, this %s like uncle Conan's place...",
- 0 /* no message */
- };
- const char *mesg;
- char buf[BUFSZ];
- int which = rn2(4);
-
- if (Hallucination)
- mesg = halu_fam_msgs[which];
- else
- mesg = fam_msgs[which];
- if (mesg && index(mesg, '%')) {
- Sprintf(buf, mesg, !Blind ? "looks" : "seems");
- mesg = buf;
- }
- if (mesg) pline1(mesg);
- }
-
- /* special location arrival messages/events */
- if (In_endgame(&u.uz)) {
- if (new && on_level(&u.uz, &astral_level))
- final_level(); /* guardian angel,&c */
- else if (newdungeon && u.uhave.amulet)
- resurrect(); /* force confrontation with Wizard */
- } else if (In_quest(&u.uz)) {
- onquest(); /* might be reaching locate|goal level */
- } else if (In_V_tower(&u.uz)) {
- if (newdungeon && In_hell(&u.uz0))
- pline_The("heat and smoke are gone.");
- } else if (Is_knox(&u.uz)) {
- /* alarm stops working once Croesus has died */
- if (new || !mvitals[PM_CROESUS].died) {
- You("have penetrated a high security area!");
- pline("An alarm sounds!");
- for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- mtmp->msleeping = 0;
- }
- }
- } else {
- if (new && Is_rogue_level(&u.uz))
- You("enter what seems to be an older, more primitive world.");
- /* main dungeon message from your quest leader */
- if (!In_quest(&u.uz0) && at_dgn_entrance("The Quest") &&
- !(u.uevent.qcompleted || u.uevent.qexpelled ||
- quest_status.leader_is_dead)) {
- if (!u.uevent.qcalled) {
- u.uevent.qcalled = 1;
- com_pager(2); /* main "leader needs help" message */
- } else { /* reminder message */
- com_pager(Role_if(PM_ROGUE) ? 4 : 3);
- }
- }
- }
-
- assign_level(&u.uz0, &u.uz); /* reset u.uz0 */
+ You_hear("groans and moans everywhere.");
+ } else pline("It is hot here. You smell smoke...");
+ }
+ /* in case we've managed to bypass the Valley's stairway down */
+ if (Inhell && !Is_valley(&u.uz)) u.uevent.gehennom_entered = 1;
+
+ if (familiar) {
+ static const char * const fam_msgs[4] = {
+ "You have a sense of deja vu.",
+ "You feel like you've been here before.",
+ "This place %s familiar...",
+ 0 /* no message */
+ };
+ static const char * const halu_fam_msgs[4] = {
+ "Whoa! Everything %s different.",
+ "You are surrounded by twisty little passages, all alike.",
+ "Gee, this %s like uncle Conan's place...",
+ 0 /* no message */
+ };
+ const char *mesg;
+ char buf[BUFSZ];
+ int which = rn2(4);
+
+ if (Hallucination)
+ mesg = halu_fam_msgs[which];
+ else
+ mesg = fam_msgs[which];
+ if (mesg && index(mesg, '%')) {
+ Sprintf(buf, mesg, !Blind ? "looks" : "seems");
+ mesg = buf;
+ }
+ if (mesg) pline1(mesg);
+ }
+
+ /* special location arrival messages/events */
+ if (In_endgame(&u.uz)) {
+ if (new && on_level(&u.uz, &astral_level))
+ final_level(); /* guardian angel,&c */
+ else if (newdungeon && u.uhave.amulet)
+ resurrect(); /* force confrontation with Wizard */
+ } else if (In_quest(&u.uz)) {
+ onquest(); /* might be reaching locate|goal level */
+ } else if (In_V_tower(&u.uz)) {
+ if (newdungeon && In_hell(&u.uz0))
+ pline_The("heat and smoke are gone.");
+ } else if (Is_knox(&u.uz)) {
+ /* alarm stops working once Croesus has died */
+ if (new || !mvitals[PM_CROESUS].died) {
+ You("have penetrated a high security area!");
+ pline("An alarm sounds!");
+ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ mtmp->msleeping = 0;
+ }
+ }
+ } else {
+ if (new && Is_rogue_level(&u.uz))
+ You("enter what seems to be an older, more primitive world.");
+ /* main dungeon message from your quest leader */
+ if (!In_quest(&u.uz0) && at_dgn_entrance("The Quest") &&
+ !(u.uevent.qcompleted || u.uevent.qexpelled ||
+ quest_status.leader_is_dead)) {
+ if (!u.uevent.qcalled) {
+ u.uevent.qcalled = 1;
+ com_pager(2); /* main "leader needs help" message */
+ } else { /* reminder message */
+ com_pager(Role_if(PM_ROGUE) ? 4 : 3);
+ }
+ }
+ }
+
+ assign_level(&u.uz0, &u.uz); /* reset u.uz0 */
#ifdef INSURANCE
- save_currentstate();
+ save_currentstate();
#endif
- /* assume this will always return TRUE when changing level */
- (void) in_out_region(u.ux, u.uy);
- (void) pickup(1);
+ /* assume this will always return TRUE when changing level */
+ (void) in_out_region(u.ux, u.uy);
+ (void) pickup(1);
}
STATIC_OVL void
final_level()
{
- struct monst *mtmp;
+ struct monst *mtmp;
- /* reset monster hostility relative to player */
- for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- reset_hostility(mtmp);
- }
+ /* reset monster hostility relative to player */
+ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ reset_hostility(mtmp);
+ }
- /* create some player-monsters */
- create_mplayers(rn1(4, 3), TRUE);
+ /* create some player-monsters */
+ create_mplayers(rn1(4, 3), TRUE);
- /* create a guardian angel next to player, if worthy */
- gain_guardian_angel();
+ /* create a guardian angel next to player, if worthy */
+ gain_guardian_angel();
}
static char *dfr_pre_msg = 0, /* pline() before level change */
- *dfr_post_msg = 0; /* pline() after level change */
+ *dfr_post_msg = 0; /* pline() after level change */
/* change levels at the end of this turn, after monsters finish moving */
void
int portal_flag;
const char *pre_msg, *post_msg;
{
- int typmask = 0100; /* non-zero triggers `deferred_goto' */
-
- /* destination flags (`goto_level' args) */
- if (at_stairs) typmask |= 1;
- if (falling) typmask |= 2;
- if (portal_flag) typmask |= 4;
- if (portal_flag < 0) typmask |= 0200; /* flag for portal removal */
- u.utotype = typmask;
- /* destination level */
- assign_level(&u.utolev, tolev);
-
- if (pre_msg)
- dfr_pre_msg = dupstr(pre_msg);
- if (post_msg)
- dfr_post_msg = dupstr(post_msg);
+ int typmask = 0100; /* non-zero triggers `deferred_goto' */
+
+ /* destination flags (`goto_level' args) */
+ if (at_stairs) typmask |= 1;
+ if (falling) typmask |= 2;
+ if (portal_flag) typmask |= 4;
+ if (portal_flag < 0) typmask |= 0200; /* flag for portal removal */
+ u.utotype = typmask;
+ /* destination level */
+ assign_level(&u.utolev, tolev);
+
+ if (pre_msg)
+ dfr_pre_msg = dupstr(pre_msg);
+ if (post_msg)
+ dfr_post_msg = dupstr(post_msg);
}
/* handle something like portal ejection */
void
deferred_goto()
{
- if (!on_level(&u.uz, &u.utolev)) {
- d_level dest;
- int typmask = u.utotype; /* save it; goto_level zeroes u.utotype */
-
- assign_level(&dest, &u.utolev);
- if (dfr_pre_msg) pline1(dfr_pre_msg);
- goto_level(&dest, !!(typmask&1), !!(typmask&2), !!(typmask&4));
- if (typmask & 0200) { /* remove portal */
- struct trap *t = t_at(u.ux, u.uy);
-
- if (t) {
- deltrap(t);
- newsym(u.ux, u.uy);
- }
- }
- if (dfr_post_msg) pline1(dfr_post_msg);
- }
- u.utotype = 0; /* our caller keys off of this */
- if (dfr_pre_msg)
- free((genericptr_t)dfr_pre_msg), dfr_pre_msg = 0;
- if (dfr_post_msg)
- free((genericptr_t)dfr_post_msg), dfr_post_msg = 0;
+ if (!on_level(&u.uz, &u.utolev)) {
+ d_level dest;
+ int typmask = u.utotype; /* save it; goto_level zeroes u.utotype */
+
+ assign_level(&dest, &u.utolev);
+ if (dfr_pre_msg) pline1(dfr_pre_msg);
+ goto_level(&dest, !!(typmask&1), !!(typmask&2), !!(typmask&4));
+ if (typmask & 0200) { /* remove portal */
+ struct trap *t = t_at(u.ux, u.uy);
+
+ if (t) {
+ deltrap(t);
+ newsym(u.ux, u.uy);
+ }
+ }
+ if (dfr_post_msg) pline1(dfr_post_msg);
+ }
+ u.utotype = 0; /* our caller keys off of this */
+ if (dfr_pre_msg)
+ free((genericptr_t)dfr_pre_msg), dfr_pre_msg = 0;
+ if (dfr_post_msg)
+ free((genericptr_t)dfr_post_msg), dfr_post_msg = 0;
}
/*
is_uwep = (corpse == uwep);
chewed = (corpse->oeaten != 0);
Strcpy(cname, corpse_xname(corpse,
- chewed ? "bite-covered" : (const char *)0,
- CXN_SINGULAR));
+ chewed ? "bite-covered" : (const char *)0,
+ CXN_SINGULAR));
mcarry = (where == OBJ_MINVENT) ? corpse->ocarry : 0;
if (where == OBJ_CONTAINED) {
- struct monst *mtmp2;
+ struct monst *mtmp2;
- container = corpse->ocontainer;
- mtmp2 = get_container_location(container, &container_where, (int *)0);
- /* container_where is the outermost container's location even if nested */
- if (container_where == OBJ_MINVENT && mtmp2) mcarry = mtmp2;
+ container = corpse->ocontainer;
+ mtmp2 = get_container_location(container, &container_where, (int *)0);
+ /* container_where is the outermost container's location even if nested */
+ if (container_where == OBJ_MINVENT && mtmp2) mcarry = mtmp2;
}
mtmp = revive(corpse, FALSE); /* corpse is gone if successful */
if (mtmp) {
- switch (where) {
- case OBJ_INVENT:
- if (is_uwep)
- pline_The("%s writhes out of your grasp!", cname);
- else
- You_feel("squirming in your backpack!");
- break;
-
- case OBJ_FLOOR:
- if (cansee(mtmp->mx, mtmp->my))
- pline("%s rises from the dead!", chewed ?
- Adjmonnam(mtmp, "bite-covered") : Monnam(mtmp));
- break;
-
- case OBJ_MINVENT: /* probably a nymph's */
- if (cansee(mtmp->mx, mtmp->my)) {
- if (canseemon(mcarry))
- pline("Startled, %s drops %s as it revives!",
- mon_nam(mcarry), an(cname));
- else
- pline("%s suddenly appears!", chewed ?
- Adjmonnam(mtmp, "bite-covered") : Monnam(mtmp));
- }
- break;
- case OBJ_CONTAINED:
- {
- char sackname[BUFSZ];
-
- if (container_where == OBJ_MINVENT &&
- cansee(mtmp->mx, mtmp->my) &&
- mcarry && canseemon(mcarry) && container) {
- pline("%s writhes out of %s!",
- Amonnam(mtmp), yname(container));
- } else if (container_where == OBJ_INVENT && container) {
- Strcpy(sackname, an(xname(container)));
- pline("%s %s out of %s in your pack!",
- Blind ? Something : Amonnam(mtmp),
- locomotion(mtmp->data,"writhes"),
- sackname);
- } else if (container_where == OBJ_FLOOR && container &&
- cansee(mtmp->mx, mtmp->my)) {
- Strcpy(sackname, an(xname(container)));
- pline("%s escapes from %s!", Amonnam(mtmp), sackname);
- }
- break;
- }
- default:
- /* we should be able to handle the other cases... */
- impossible("revive_corpse: lost corpse @ %d", where);
- break;
- }
- return TRUE;
+ switch (where) {
+ case OBJ_INVENT:
+ if (is_uwep)
+ pline_The("%s writhes out of your grasp!", cname);
+ else
+ You_feel("squirming in your backpack!");
+ break;
+
+ case OBJ_FLOOR:
+ if (cansee(mtmp->mx, mtmp->my))
+ pline("%s rises from the dead!", chewed ?
+ Adjmonnam(mtmp, "bite-covered") : Monnam(mtmp));
+ break;
+
+ case OBJ_MINVENT: /* probably a nymph's */
+ if (cansee(mtmp->mx, mtmp->my)) {
+ if (canseemon(mcarry))
+ pline("Startled, %s drops %s as it revives!",
+ mon_nam(mcarry), an(cname));
+ else
+ pline("%s suddenly appears!", chewed ?
+ Adjmonnam(mtmp, "bite-covered") : Monnam(mtmp));
+ }
+ break;
+ case OBJ_CONTAINED:
+ {
+ char sackname[BUFSZ];
+
+ if (container_where == OBJ_MINVENT &&
+ cansee(mtmp->mx, mtmp->my) &&
+ mcarry && canseemon(mcarry) && container) {
+ pline("%s writhes out of %s!",
+ Amonnam(mtmp), yname(container));
+ } else if (container_where == OBJ_INVENT && container) {
+ Strcpy(sackname, an(xname(container)));
+ pline("%s %s out of %s in your pack!",
+ Blind ? Something : Amonnam(mtmp),
+ locomotion(mtmp->data,"writhes"),
+ sackname);
+ } else if (container_where == OBJ_FLOOR && container &&
+ cansee(mtmp->mx, mtmp->my)) {
+ Strcpy(sackname, an(xname(container)));
+ pline("%s escapes from %s!", Amonnam(mtmp), sackname);
+ }
+ break;
+ }
+ default:
+ /* we should be able to handle the other cases... */
+ impossible("revive_corpse: lost corpse @ %d", where);
+ break;
+ }
+ return TRUE;
}
return FALSE;
}
/* corpse will revive somewhere else if there is a monster in the way;
Riders get a chance to try to bump the obstacle out of their way */
if ((mptr->mflags3 & M3_DISPLACES) != 0 && body->where == OBJ_FLOOR &&
- get_obj_location(body, &x, &y, 0) && (mtmp = m_at(x, y)) != 0) {
- boolean notice_it = canseemon(mtmp); /* before rloc() */
- char *monname = Monnam(mtmp);
-
- if (rloc(mtmp, TRUE)) {
- if (notice_it && !canseemon(mtmp))
- pline("%s vanishes.", monname);
- else if (!notice_it && canseemon(mtmp))
- pline("%s appears.", Monnam(mtmp)); /* not pre-rloc monname */
- else if (notice_it && dist2(mtmp->mx, mtmp->my, x, y) > 2)
- pline("%s teleports.", monname); /* saw it and still see it */
- }
+ get_obj_location(body, &x, &y, 0) && (mtmp = m_at(x, y)) != 0) {
+ boolean notice_it = canseemon(mtmp); /* before rloc() */
+ char *monname = Monnam(mtmp);
+
+ if (rloc(mtmp, TRUE)) {
+ if (notice_it && !canseemon(mtmp))
+ pline("%s vanishes.", monname);
+ else if (!notice_it && canseemon(mtmp))
+ pline("%s appears.", Monnam(mtmp)); /* not pre-rloc monname */
+ else if (notice_it && dist2(mtmp->mx, mtmp->my, x, y) > 2)
+ pline("%s teleports.", monname); /* saw it and still see it */
+ }
}
/* if we succeed, the corpse is gone */
if (!revive_corpse(body)) {
- long when;
- int action;
-
- if (is_rider(mptr) && rn2(99)) { /* Rider usually tries again */
- action = REVIVE_MON;
- for (when = 3L; when < 67L; when++)
- if (!rn2(3)) break;
- } else { /* rot this corpse away */
- You_feel("%sless hassled.", is_rider(mptr) ? "much " : "");
- action = ROT_CORPSE;
- when = 250L - (monstermoves - body->age);
- if (when < 1L) when = 1L;
- }
- (void) start_timer(when, TIMER_OBJECT, action, arg);
+ long when;
+ int action;
+
+ if (is_rider(mptr) && rn2(99)) { /* Rider usually tries again */
+ action = REVIVE_MON;
+ for (when = 3L; when < 67L; when++)
+ if (!rn2(3)) break;
+ } else { /* rot this corpse away */
+ You_feel("%sless hassled.", is_rider(mptr) ? "much " : "");
+ action = ROT_CORPSE;
+ when = 250L - (monstermoves - body->age);
+ if (when < 1L) when = 1L;
+ }
+ (void) start_timer(when, TIMER_OBJECT, action, arg);
}
}
int
donull()
{
- return(1); /* Do nothing, but let other things happen */
+ return(1); /* Do nothing, but let other things happen */
}
STATIC_PTR int
wipeoff(VOID_ARGS)
{
- if(u.ucreamed < 4) u.ucreamed = 0;
- else u.ucreamed -= 4;
- if (Blinded < 4) Blinded = 0;
- else Blinded -= 4;
- if (!Blinded) {
- pline("You've got the glop off.");
- u.ucreamed = 0;
- if (!gulp_blnd_check()) {
- Blinded = 1;
- make_blinded(0L,TRUE);
- }
- return(0);
- } else if (!u.ucreamed) {
- Your("%s feels clean now.", body_part(FACE));
- return(0);
- }
- return(1); /* still busy */
+ if(u.ucreamed < 4) u.ucreamed = 0;
+ else u.ucreamed -= 4;
+ if (Blinded < 4) Blinded = 0;
+ else Blinded -= 4;
+ if (!Blinded) {
+ pline("You've got the glop off.");
+ u.ucreamed = 0;
+ if (!gulp_blnd_check()) {
+ Blinded = 1;
+ make_blinded(0L,TRUE);
+ }
+ return(0);
+ } else if (!u.ucreamed) {
+ Your("%s feels clean now.", body_part(FACE));
+ return(0);
+ }
+ return(1); /* still busy */
}
int
dowipe()
{
- if(u.ucreamed) {
- static NEARDATA char buf[39];
-
- Sprintf(buf, "wiping off your %s", body_part(FACE));
- set_occupation(wipeoff, buf, 0);
- /* Not totally correct; what if they change back after now
- * but before they're finished wiping?
- */
- return(1);
- }
- Your("%s is already clean.", body_part(FACE));
- return(1);
+ if(u.ucreamed) {
+ static NEARDATA char buf[39];
+
+ Sprintf(buf, "wiping off your %s", body_part(FACE));
+ set_occupation(wipeoff, buf, 0);
+ /* Not totally correct; what if they change back after now
+ * but before they're finished wiping?
+ */
+ return(1);
+ }
+ Your("%s is already clean.", body_part(FACE));
+ return(1);
}
void
register long side;
register int timex;
{
- /* KMH -- STEED
- * If you are riding, your steed gets the wounded legs instead.
- * You still call this function, but don't lose hp.
- * Caller is also responsible for adjusting messages.
- */
-
- if(!Wounded_legs) {
- ATEMP(A_DEX)--;
- context.botl = 1;
- }
-
- if(!Wounded_legs || (HWounded_legs & TIMEOUT))
- HWounded_legs = timex;
- EWounded_legs = side;
- (void)encumber_msg();
+ /* KMH -- STEED
+ * If you are riding, your steed gets the wounded legs instead.
+ * You still call this function, but don't lose hp.
+ * Caller is also responsible for adjusting messages.
+ */
+
+ if(!Wounded_legs) {
+ ATEMP(A_DEX)--;
+ context.botl = 1;
+ }
+
+ if(!Wounded_legs || (HWounded_legs & TIMEOUT))
+ HWounded_legs = timex;
+ EWounded_legs = side;
+ (void)encumber_msg();
}
void
heal_legs()
{
- if (Wounded_legs) {
- if (ATEMP(A_DEX) < 0) {
- ATEMP(A_DEX)++;
- context.botl = 1;
- }
-
- if (!u.usteed)
- {
- const char *legs = body_part(LEG);
-
- if ((EWounded_legs & BOTH_SIDES) == BOTH_SIDES)
- legs = makeplural(legs);
- /* this used to say "somewhat better" but that was
- misleading since legs are being fully healed */
- Your("%s %s better.", legs, vtense(legs, "feel"));
- }
-
- HWounded_legs = EWounded_legs = 0;
-
- /* Wounded_legs reduces carrying capacity, so we want
- an encumbrance check when they're healed. However,
- while dismounting, first steed's legs get healed,
- then hero is dropped to floor and a new encumbrance
- check is made [in dismount_steed()]. So don't give
- encumbrance feedback during the dismount stage
- because it could seem to be shown out of order and
- it might be immediately contradicted [able to carry
- more when steed becomes healthy, then possible floor
- feedback, then able to carry less when back on foot]. */
- if (!in_steed_dismounting) (void)encumber_msg();
- }
+ if (Wounded_legs) {
+ if (ATEMP(A_DEX) < 0) {
+ ATEMP(A_DEX)++;
+ context.botl = 1;
+ }
+
+ if (!u.usteed)
+ {
+ const char *legs = body_part(LEG);
+
+ if ((EWounded_legs & BOTH_SIDES) == BOTH_SIDES)
+ legs = makeplural(legs);
+ /* this used to say "somewhat better" but that was
+ misleading since legs are being fully healed */
+ Your("%s %s better.", legs, vtense(legs, "feel"));
+ }
+
+ HWounded_legs = EWounded_legs = 0;
+
+ /* Wounded_legs reduces carrying capacity, so we want
+ an encumbrance check when they're healed. However,
+ while dismounting, first steed's legs get healed,
+ then hero is dropped to floor and a new encumbrance
+ check is made [in dismount_steed()]. So don't give
+ encumbrance feedback during the dismount stage
+ because it could seem to be shown out of order and
+ it might be immediately contradicted [able to carry
+ more when steed becomes healthy, then possible floor
+ feedback, then able to carry less when back on foot]. */
+ if (!in_steed_dismounting) (void)encumber_msg();
+ }
}
/*do.c*/
boolean revived = FALSE;
for(otmp = level.objects[x][y]; otmp; otmp = otmp2) {
- otmp2 = otmp->nexthere;
- if (otmp->otyp == CORPSE &&
- (is_rider(&mons[otmp->corpsenm]) ||
- otmp->corpsenm == PM_WIZARD_OF_YENDOR)) {
- /* move any living monster already at that location */
- if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data))
- rloc_to(mtmp, cc.x, cc.y);
- if(msg) Norep("%s", msg);
- revived = revive_corpse(otmp);
- }
+ otmp2 = otmp->nexthere;
+ if (otmp->otyp == CORPSE &&
+ (is_rider(&mons[otmp->corpsenm]) ||
+ otmp->corpsenm == PM_WIZARD_OF_YENDOR)) {
+ /* move any living monster already at that location */
+ if((mtmp = m_at(x,y)) && enexto(&cc, x, y, mtmp->data))
+ rloc_to(mtmp, cc.x, cc.y);
+ if(msg) Norep("%s", msg);
+ revived = revive_corpse(otmp);
+ }
}
/* this location might not be safe, if not, move revived monster */
if (revived) {
- mtmp = m_at(x,y);
- if (mtmp && !goodpos(x, y, mtmp, 0) &&
- enexto(&cc, x, y, mtmp->data)) {
- rloc_to(mtmp, cc.x, cc.y);
- }
- /* else impossible? */
+ mtmp = m_at(x,y);
+ if (mtmp && !goodpos(x, y, mtmp, 0) &&
+ enexto(&cc, x, y, mtmp->data)) {
+ rloc_to(mtmp, cc.x, cc.y);
+ }
+ /* else impossible? */
}
return (revived);
sx = u.ux + u.dx, sy = u.uy + u.dy; /* boulder starting position */
while ((otmp = sobj_at(BOULDER, sx, sy)) != 0) {
- /* make sure that this boulder is visible as the top object */
- if (otmp != level.objects[sx][sy]) movobj(otmp, sx, sy);
-
- rx = u.ux + 2 * u.dx; /* boulder destination position */
- ry = u.uy + 2 * u.dy;
- nomul(0);
- if (Levitation || Is_airlevel(&u.uz)) {
- if (Blind) feel_location(sx, sy);
- You("don't have enough leverage to push %s.", the(xname(otmp)));
- /* Give them a chance to climb over it? */
- return -1;
- }
- if (verysmall(youmonst.data) && !u.usteed) {
- if (Blind) feel_location(sx, sy);
- pline("You're too small to push that %s.", xname(otmp));
- goto cannot_push;
- }
- if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
- levl[rx][ry].typ != IRONBARS &&
- (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) ||
- doorless_door(rx, ry)) &&
- !sobj_at(BOULDER, rx, ry)) {
- ttmp = t_at(rx, ry);
- mtmp = m_at(rx, ry);
-
- /* KMH -- Sokoban doesn't let you push boulders diagonally */
- if (Sokoban && u.dx && u.dy) {
- if (Blind) feel_location(sx,sy);
- pline("%s won't roll diagonally on this %s.",
- The(xname(otmp)), surface(sx, sy));
- goto cannot_push;
- }
-
- if (revive_nasty(rx, ry, "You sense movement on the other side."))
- return (-1);
-
- if (mtmp && !noncorporeal(mtmp->data) &&
- (!mtmp->mtrapped ||
- !(ttmp && ((ttmp->ttyp == PIT) ||
- (ttmp->ttyp == SPIKED_PIT))))) {
- if (Blind) feel_location(sx, sy);
- if (canspotmon(mtmp))
- pline("There's %s on the other side.", a_monnam(mtmp));
- else {
- You_hear("a monster behind %s.", the(xname(otmp)));
- map_invisible(rx, ry);
- }
- if (flags.verbose)
- pline("Perhaps that's why %s cannot move it.",
- u.usteed ? y_monnam(u.usteed) : "you");
- goto cannot_push;
- }
-
- if (ttmp) {
- /* if a trap operates on the boulder, don't attempt
- to move any others at this location; return -1
- if another boulder is in hero's way, or 0 if he
- should advance to the vacated boulder position */
- switch(ttmp->ttyp) {
- case LANDMINE:
- if (rn2(10)) {
- obj_extract_self(otmp);
- place_object(otmp, rx, ry);
- newsym(sx, sy);
- pline("KAABLAMM!!! %s %s land mine.",
- Tobjnam(otmp, "trigger"),
- ttmp->madeby_u ? "your" : "a");
- blow_up_landmine(ttmp);
- /* if the boulder remains, it should fill the pit */
- fill_pit(u.ux, u.uy);
- if (cansee(rx,ry)) newsym(rx,ry);
- return sobj_at(BOULDER, sx, sy) ? -1 : 0;
- }
- break;
- case SPIKED_PIT:
- case PIT:
- obj_extract_self(otmp);
- /* vision kludge to get messages right;
- the pit will temporarily be seen even
- if this is one among multiple boulders */
- if (!Blind) viz_array[ry][rx] |= IN_SIGHT;
- if (!flooreffects(otmp, rx, ry, "fall")) {
- place_object(otmp, rx, ry);
- }
- if (mtmp && !Blind) newsym(rx, ry);
- return sobj_at(BOULDER, sx, sy) ? -1 : 0;
- case HOLE:
- case TRAPDOOR:
- if (Blind)
- pline("Kerplunk! You no longer feel %s.",
- the(xname(otmp)));
- else
- pline("%s%s and %s a %s in the %s!",
- Tobjnam(otmp,
- (ttmp->ttyp == TRAPDOOR) ? "trigger" : "fall"),
- (ttmp->ttyp == TRAPDOOR) ? "" : " into",
- otense(otmp, "plug"),
- (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",
- surface(rx, ry));
- deltrap(ttmp);
- delobj(otmp);
- bury_objs(rx, ry);
- levl[rx][ry].wall_info &= ~W_NONDIGGABLE;
- levl[rx][ry].candig = 1;
- if (cansee(rx,ry)) newsym(rx,ry);
- return sobj_at(BOULDER, sx, sy) ? -1 : 0;
- case LEVEL_TELEP:
- case TELEP_TRAP:
- {
- int newlev = 0; /* lint suppression */
- d_level dest;
-
- if (ttmp->ttyp == LEVEL_TELEP) {
- newlev = random_teleport_level();
- if (newlev == depth(&u.uz) || In_endgame(&u.uz))
- /* trap didn't work; skip "disappears" message */
- goto dopush;
- }
- if (u.usteed)
+ /* make sure that this boulder is visible as the top object */
+ if (otmp != level.objects[sx][sy]) movobj(otmp, sx, sy);
+
+ rx = u.ux + 2 * u.dx; /* boulder destination position */
+ ry = u.uy + 2 * u.dy;
+ nomul(0);
+ if (Levitation || Is_airlevel(&u.uz)) {
+ if (Blind) feel_location(sx, sy);
+ You("don't have enough leverage to push %s.", the(xname(otmp)));
+ /* Give them a chance to climb over it? */
+ return -1;
+ }
+ if (verysmall(youmonst.data) && !u.usteed) {
+ if (Blind) feel_location(sx, sy);
+ pline("You're too small to push that %s.", xname(otmp));
+ goto cannot_push;
+ }
+ if (isok(rx,ry) && !IS_ROCK(levl[rx][ry].typ) &&
+ levl[rx][ry].typ != IRONBARS &&
+ (!IS_DOOR(levl[rx][ry].typ) || !(u.dx && u.dy) ||
+ doorless_door(rx, ry)) &&
+ !sobj_at(BOULDER, rx, ry)) {
+ ttmp = t_at(rx, ry);
+ mtmp = m_at(rx, ry);
+
+ /* KMH -- Sokoban doesn't let you push boulders diagonally */
+ if (Sokoban && u.dx && u.dy) {
+ if (Blind) feel_location(sx,sy);
+ pline("%s won't roll diagonally on this %s.",
+ The(xname(otmp)), surface(sx, sy));
+ goto cannot_push;
+ }
+
+ if (revive_nasty(rx, ry, "You sense movement on the other side."))
+ return (-1);
+
+ if (mtmp && !noncorporeal(mtmp->data) &&
+ (!mtmp->mtrapped ||
+ !(ttmp && ((ttmp->ttyp == PIT) ||
+ (ttmp->ttyp == SPIKED_PIT))))) {
+ if (Blind) feel_location(sx, sy);
+ if (canspotmon(mtmp))
+ pline("There's %s on the other side.", a_monnam(mtmp));
+ else {
+ You_hear("a monster behind %s.", the(xname(otmp)));
+ map_invisible(rx, ry);
+ }
+ if (flags.verbose)
+ pline("Perhaps that's why %s cannot move it.",
+ u.usteed ? y_monnam(u.usteed) : "you");
+ goto cannot_push;
+ }
+
+ if (ttmp) {
+ /* if a trap operates on the boulder, don't attempt
+ to move any others at this location; return -1
+ if another boulder is in hero's way, or 0 if he
+ should advance to the vacated boulder position */
+ switch(ttmp->ttyp) {
+ case LANDMINE:
+ if (rn2(10)) {
+ obj_extract_self(otmp);
+ place_object(otmp, rx, ry);
+ newsym(sx, sy);
+ pline("KAABLAMM!!! %s %s land mine.",
+ Tobjnam(otmp, "trigger"),
+ ttmp->madeby_u ? "your" : "a");
+ blow_up_landmine(ttmp);
+ /* if the boulder remains, it should fill the pit */
+ fill_pit(u.ux, u.uy);
+ if (cansee(rx,ry)) newsym(rx,ry);
+ return sobj_at(BOULDER, sx, sy) ? -1 : 0;
+ }
+ break;
+ case SPIKED_PIT:
+ case PIT:
+ obj_extract_self(otmp);
+ /* vision kludge to get messages right;
+ the pit will temporarily be seen even
+ if this is one among multiple boulders */
+ if (!Blind) viz_array[ry][rx] |= IN_SIGHT;
+ if (!flooreffects(otmp, rx, ry, "fall")) {
+ place_object(otmp, rx, ry);
+ }
+ if (mtmp && !Blind) newsym(rx, ry);
+ return sobj_at(BOULDER, sx, sy) ? -1 : 0;
+ case HOLE:
+ case TRAPDOOR:
+ if (Blind)
+ pline("Kerplunk! You no longer feel %s.",
+ the(xname(otmp)));
+ else
+ pline("%s%s and %s a %s in the %s!",
+ Tobjnam(otmp,
+ (ttmp->ttyp == TRAPDOOR) ? "trigger" : "fall"),
+ (ttmp->ttyp == TRAPDOOR) ? "" : " into",
+ otense(otmp, "plug"),
+ (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",
+ surface(rx, ry));
+ deltrap(ttmp);
+ delobj(otmp);
+ bury_objs(rx, ry);
+ levl[rx][ry].wall_info &= ~W_NONDIGGABLE;
+ levl[rx][ry].candig = 1;
+ if (cansee(rx,ry)) newsym(rx,ry);
+ return sobj_at(BOULDER, sx, sy) ? -1 : 0;
+ case LEVEL_TELEP:
+ case TELEP_TRAP:
+ {
+ int newlev = 0; /* lint suppression */
+ d_level dest;
+
+ if (ttmp->ttyp == LEVEL_TELEP) {
+ newlev = random_teleport_level();
+ if (newlev == depth(&u.uz) || In_endgame(&u.uz))
+ /* trap didn't work; skip "disappears" message */
+ goto dopush;
+ }
+ if (u.usteed)
pline("%s pushes %s and suddenly it disappears!",
- upstart(y_monnam(u.usteed)), the(xname(otmp)));
- else
+ upstart(y_monnam(u.usteed)), the(xname(otmp)));
+ else
You("push %s and suddenly it disappears!",
- the(xname(otmp)));
- if (ttmp->ttyp == TELEP_TRAP) {
- (void)rloco(otmp);
- } else {
- obj_extract_self(otmp);
- add_to_migration(otmp);
- get_level(&dest, newlev);
- otmp->ox = dest.dnum;
- otmp->oy = dest.dlevel;
- otmp->owornmask = (long)MIGR_RANDOM;
- }
- seetrap(ttmp);
- return sobj_at(BOULDER, sx, sy) ? -1 : 0;
- }
- default:
- break; /* boulder not affected by this trap */
- }
- }
-
- if (closed_door(rx, ry))
- goto nopushmsg;
- if (boulder_hits_pool(otmp, rx, ry, TRUE))
- continue;
- /*
- * Re-link at top of fobj chain so that pile order is preserved
- * when level is restored.
- */
- if (otmp != fobj) {
- remove_object(otmp);
- place_object(otmp, otmp->ox, otmp->oy);
- }
-
- {
+ the(xname(otmp)));
+ if (ttmp->ttyp == TELEP_TRAP) {
+ (void)rloco(otmp);
+ } else {
+ obj_extract_self(otmp);
+ add_to_migration(otmp);
+ get_level(&dest, newlev);
+ otmp->ox = dest.dnum;
+ otmp->oy = dest.dlevel;
+ otmp->owornmask = (long)MIGR_RANDOM;
+ }
+ seetrap(ttmp);
+ return sobj_at(BOULDER, sx, sy) ? -1 : 0;
+ }
+ default:
+ break; /* boulder not affected by this trap */
+ }
+ }
+
+ if (closed_door(rx, ry))
+ goto nopushmsg;
+ if (boulder_hits_pool(otmp, rx, ry, TRUE))
+ continue;
+ /*
+ * Re-link at top of fobj chain so that pile order is preserved
+ * when level is restored.
+ */
+ if (otmp != fobj) {
+ remove_object(otmp);
+ place_object(otmp, otmp->ox, otmp->oy);
+ }
+
+ {
#ifdef LINT /* static long lastmovetime; */
- long lastmovetime;
- lastmovetime = 0;
+ long lastmovetime;
+ lastmovetime = 0;
#else
- /* note: reset to zero after save/restore cycle */
- static NEARDATA long lastmovetime;
+ /* note: reset to zero after save/restore cycle */
+ static NEARDATA long lastmovetime;
#endif
dopush:
- if (!u.usteed) {
- if (moves > lastmovetime+2 || moves < lastmovetime)
- pline("With %s effort you move %s.",
- throws_rocks(youmonst.data) ? "little" : "great",
- the(xname(otmp)));
- exercise(A_STR, TRUE);
- } else
- pline("%s moves %s.",
- upstart(y_monnam(u.usteed)), the(xname(otmp)));
- lastmovetime = moves;
- }
-
- /* Move the boulder *after* the message. */
- if (glyph_is_invisible(levl[rx][ry].glyph))
- unmap_object(rx, ry);
- movobj(otmp, rx, ry); /* does newsym(rx,ry) */
- if (Blind) {
- feel_location(rx,ry);
- feel_location(sx, sy);
- } else {
- newsym(sx, sy);
- }
- } else {
+ if (!u.usteed) {
+ if (moves > lastmovetime+2 || moves < lastmovetime)
+ pline("With %s effort you move %s.",
+ throws_rocks(youmonst.data) ? "little" : "great",
+ the(xname(otmp)));
+ exercise(A_STR, TRUE);
+ } else
+ pline("%s moves %s.",
+ upstart(y_monnam(u.usteed)), the(xname(otmp)));
+ lastmovetime = moves;
+ }
+
+ /* Move the boulder *after* the message. */
+ if (glyph_is_invisible(levl[rx][ry].glyph))
+ unmap_object(rx, ry);
+ movobj(otmp, rx, ry); /* does newsym(rx,ry) */
+ if (Blind) {
+ feel_location(rx,ry);
+ feel_location(sx, sy);
+ } else {
+ newsym(sx, sy);
+ }
+ } else {
nopushmsg:
- if (u.usteed)
- pline("%s tries to move %s, but cannot.",
- upstart(y_monnam(u.usteed)), the(xname(otmp)));
- else
- You("try to move %s, but in vain.", the(xname(otmp)));
- if (Blind) feel_location(sx, sy);
+ if (u.usteed)
+ pline("%s tries to move %s, but cannot.",
+ upstart(y_monnam(u.usteed)), the(xname(otmp)));
+ else
+ You("try to move %s, but in vain.", the(xname(otmp)));
+ if (Blind) feel_location(sx, sy);
cannot_push:
- if (throws_rocks(youmonst.data)) {
- if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
- You("aren't skilled enough to %s %s from %s.",
- (flags.pickup && !Sokoban) ? "pick up" : "push aside",
- the(xname(otmp)), y_monnam(u.usteed));
- } else {
- pline("However, you can easily %s.",
- (flags.pickup && !Sokoban) ?
- "pick it up" : "push it aside");
- sokoban_guilt();
- break;
- }
- break;
- }
-
- if (!u.usteed && (((!invent || inv_weight() <= -850) &&
- (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ)
- && IS_ROCK(levl[sx][u.uy].typ))))
- || verysmall(youmonst.data))) {
- pline("However, you can squeeze yourself into a small opening.");
- sokoban_guilt();
- break;
- } else
- return (-1);
- }
+ if (throws_rocks(youmonst.data)) {
+ if (u.usteed && P_SKILL(P_RIDING) < P_BASIC) {
+ You("aren't skilled enough to %s %s from %s.",
+ (flags.pickup && !Sokoban) ? "pick up" : "push aside",
+ the(xname(otmp)), y_monnam(u.usteed));
+ } else {
+ pline("However, you can easily %s.",
+ (flags.pickup && !Sokoban) ?
+ "pick it up" : "push it aside");
+ sokoban_guilt();
+ break;
+ }
+ break;
+ }
+
+ if (!u.usteed && (((!invent || inv_weight() <= -850) &&
+ (!u.dx || !u.dy || (IS_ROCK(levl[u.ux][sy].typ)
+ && IS_ROCK(levl[sx][u.uy].typ))))
+ || verysmall(youmonst.data))) {
+ pline("However, you can squeeze yourself into a small opening.");
+ sokoban_guilt();
+ break;
+ } else
+ return (-1);
+ }
}
return (0);
}
const char *digtxt = (char *)0, *dmgtxt = (char *)0;
if (context.digging.down) /* not continuing previous dig (w/ pick-axe) */
- (void) memset((genericptr_t)&context.digging, 0, sizeof(struct dig_info));
+ (void) memset((genericptr_t)&context.digging, 0, sizeof(struct dig_info));
if (!boulder && IS_ROCK(lev->typ) && !may_dig(x,y)) {
- You("hurt your teeth on the %s.",
- IS_TREE(lev->typ) ? "tree" : "hard stone");
- nomul(0);
- return 1;
+ You("hurt your teeth on the %s.",
+ IS_TREE(lev->typ) ? "tree" : "hard stone");
+ nomul(0);
+ return 1;
} else if (context.digging.pos.x != x || context.digging.pos.y != y ||
- !on_level(&context.digging.level, &u.uz)) {
- context.digging.down = FALSE;
- context.digging.chew = TRUE;
- context.digging.warned = FALSE;
- context.digging.pos.x = x;
- context.digging.pos.y = y;
- assign_level(&context.digging.level, &u.uz);
- /* solid rock takes more work & time to dig through */
- context.digging.effort =
- (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc;
- You("start chewing %s %s.",
- (boulder || IS_TREE(lev->typ)) ? "on a" : "a hole in the",
- boulder ? "boulder" :
- IS_TREE(lev->typ) ? "tree" : IS_ROCK(lev->typ) ? "rock" : "door");
- watch_dig((struct monst *)0, x, y, FALSE);
- return 1;
+ !on_level(&context.digging.level, &u.uz)) {
+ context.digging.down = FALSE;
+ context.digging.chew = TRUE;
+ context.digging.warned = FALSE;
+ context.digging.pos.x = x;
+ context.digging.pos.y = y;
+ assign_level(&context.digging.level, &u.uz);
+ /* solid rock takes more work & time to dig through */
+ context.digging.effort =
+ (IS_ROCK(lev->typ) && !IS_TREE(lev->typ) ? 30 : 60) + u.udaminc;
+ You("start chewing %s %s.",
+ (boulder || IS_TREE(lev->typ)) ? "on a" : "a hole in the",
+ boulder ? "boulder" :
+ IS_TREE(lev->typ) ? "tree" : IS_ROCK(lev->typ) ? "rock" : "door");
+ watch_dig((struct monst *)0, x, y, FALSE);
+ return 1;
} else if ((context.digging.effort += (30 + u.udaminc)) <= 100) {
- if (flags.verbose)
- You("%s chewing on the %s.",
- context.digging.chew ? "continue" : "begin",
- boulder ? "boulder" :
- IS_TREE(lev->typ) ? "tree" :
- IS_ROCK(lev->typ) ? "rock" : "door");
- context.digging.chew = TRUE;
- watch_dig((struct monst *)0, x, y, FALSE);
- return 1;
+ if (flags.verbose)
+ You("%s chewing on the %s.",
+ context.digging.chew ? "continue" : "begin",
+ boulder ? "boulder" :
+ IS_TREE(lev->typ) ? "tree" :
+ IS_ROCK(lev->typ) ? "rock" : "door");
+ context.digging.chew = TRUE;
+ watch_dig((struct monst *)0, x, y, FALSE);
+ return 1;
}
/* Okay, you've chewed through something */
u.uhunger += rnd(20);
if (boulder) {
- delobj(boulder); /* boulder goes bye-bye */
- You("eat the boulder."); /* yum */
-
- /*
- * The location could still block because of
- * 1. More than one boulder
- * 2. Boulder stuck in a wall/stone/door.
- *
- * [perhaps use does_block() below (from vision.c)]
- */
- if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) {
- block_point(x,y); /* delobj will unblock the point */
- /* reset dig state */
- (void) memset((genericptr_t)&context.digging, 0, sizeof(struct dig_info));
- return 1;
- }
+ delobj(boulder); /* boulder goes bye-bye */
+ You("eat the boulder."); /* yum */
+
+ /*
+ * The location could still block because of
+ * 1. More than one boulder
+ * 2. Boulder stuck in a wall/stone/door.
+ *
+ * [perhaps use does_block() below (from vision.c)]
+ */
+ if (IS_ROCK(lev->typ) || closed_door(x,y) || sobj_at(BOULDER,x,y)) {
+ block_point(x,y); /* delobj will unblock the point */
+ /* reset dig state */
+ (void) memset((genericptr_t)&context.digging, 0, sizeof(struct dig_info));
+ return 1;
+ }
} else if (IS_WALL(lev->typ)) {
- if (*in_rooms(x, y, SHOPBASE)) {
- add_damage(x, y, 10L * ACURRSTR);
- dmgtxt = "damage";
- }
- digtxt = "chew a hole in the wall.";
- if (level.flags.is_maze_lev) {
- lev->typ = ROOM;
- } else if (level.flags.is_cavernous_lev && !in_town(x, y)) {
- lev->typ = CORR;
- } else {
- lev->typ = DOOR;
- lev->doormask = D_NODOOR;
- }
+ if (*in_rooms(x, y, SHOPBASE)) {
+ add_damage(x, y, 10L * ACURRSTR);
+ dmgtxt = "damage";
+ }
+ digtxt = "chew a hole in the wall.";
+ if (level.flags.is_maze_lev) {
+ lev->typ = ROOM;
+ } else if (level.flags.is_cavernous_lev && !in_town(x, y)) {
+ lev->typ = CORR;
+ } else {
+ lev->typ = DOOR;
+ lev->doormask = D_NODOOR;
+ }
} else if (IS_TREE(lev->typ)) {
- digtxt = "chew through the tree.";
- lev->typ = ROOM;
+ digtxt = "chew through the tree.";
+ lev->typ = ROOM;
} else if (lev->typ == SDOOR) {
- if (lev->doormask & D_TRAPPED) {
- lev->doormask = D_NODOOR;
- b_trapped("secret door", 0);
- } else {
- digtxt = "chew through the secret door.";
- lev->doormask = D_BROKEN;
- }
- lev->typ = DOOR;
+ if (lev->doormask & D_TRAPPED) {
+ lev->doormask = D_NODOOR;
+ b_trapped("secret door", 0);
+ } else {
+ digtxt = "chew through the secret door.";
+ lev->doormask = D_BROKEN;
+ }
+ lev->typ = DOOR;
} else if (IS_DOOR(lev->typ)) {
- if (*in_rooms(x, y, SHOPBASE)) {
- add_damage(x, y, 400L);
- dmgtxt = "break";
- }
- if (lev->doormask & D_TRAPPED) {
- lev->doormask = D_NODOOR;
- b_trapped("door", 0);
- } else {
- digtxt = "chew through the door.";
- lev->doormask = D_BROKEN;
- }
+ if (*in_rooms(x, y, SHOPBASE)) {
+ add_damage(x, y, 400L);
+ dmgtxt = "break";
+ }
+ if (lev->doormask & D_TRAPPED) {
+ lev->doormask = D_NODOOR;
+ b_trapped("door", 0);
+ } else {
+ digtxt = "chew through the door.";
+ lev->doormask = D_BROKEN;
+ }
} else { /* STONE or SCORR */
- digtxt = "chew a passage through the rock.";
- lev->typ = CORR;
+ digtxt = "chew a passage through the rock.";
+ lev->typ = CORR;
}
unblock_point(x, y); /* vision */
register struct obj *obj;
register xchar ox, oy;
{
- /* optimize by leaving on the fobj chain? */
- remove_object(obj);
- newsym(obj->ox, obj->oy);
- place_object(obj, ox, oy);
- newsym(ox, oy);
+ /* optimize by leaving on the fobj chain? */
+ remove_object(obj);
+ newsym(obj->ox, obj->oy);
+ place_object(obj, ox, oy);
+ newsym(ox, oy);
}
static NEARDATA const char fell_on_sink[] = "fell onto a sink";
STATIC_OVL void
dosinkfall()
{
- register struct obj *obj;
- int dmg;
- boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS),
- innate_lev = ((HLevitation & (FROMOUTSIDE|FROMFORM)) != 0L),
- ufall = (!innate_lev && !(HFlying || EFlying)); /* BFlying */
-
- if (!ufall) {
- You(innate_lev ? "wobble unsteadily for a moment." :
- "gain control of your flight.");
- } else {
- long save_ELev = ELevitation, save_HLev = HLevitation;
-
- /* fake removal of levitation in advance so that final
- disclosure will be right in case this turns out to
- be fatal; fortunately the fact that rings and boots
- are really still worn has no effect on bones data */
- ELevitation = HLevitation = 0L;
- You("crash to the floor!");
- dmg = rn1(8, 25 - (int)ACURR(A_CON));
- losehp(Maybe_Half_Phys(dmg),
- fell_on_sink, NO_KILLER_PREFIX);
- exercise(A_DEX, FALSE);
- selftouch("Falling, you");
- for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
- if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) {
- You("fell on %s.", doname(obj));
- losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink, NO_KILLER_PREFIX);
- exercise(A_CON, FALSE);
- }
- ELevitation = save_ELev;
- HLevitation = save_HLev;
- }
-
- /*
- * Interrupt multi-turn putting on/taking off of armor (in which
- * case we reached the sink due to being teleported while busy;
- * in 3.4.3, Boots_on()/Boots_off() [called via (*aftermv)() when
- * 'multi' reaches 0] triggered a crash if we were donning/doffing
- * levitation boots [because the Boots_off() below causes 'uarmf'
- * to be null by the time 'aftermv' gets called]).
- *
- * Interrupt donning/doffing if we fall onto the sink, or if the
- * code below is going to remove levitation boots even when we
- * haven't fallen (innate floating or flying becoming unblocked).
- */
- if (ufall || lev_boots) {
- (void) stop_donning(lev_boots ? uarmf : (struct obj *)0);
- /* recalculate in case uarmf just got set to null */
- lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS);
- }
-
- /* remove worn levitation items */
- ELevitation &= ~W_ARTI;
- HLevitation &= ~(I_SPECIAL|TIMEOUT);
- HLevitation++;
- if(uleft && uleft->otyp == RIN_LEVITATION) {
- obj = uleft;
- Ring_off(obj);
- off_msg(obj);
- }
- if(uright && uright->otyp == RIN_LEVITATION) {
- obj = uright;
- Ring_off(obj);
- off_msg(obj);
- }
- if (lev_boots) {
- obj = uarmf;
- (void)Boots_off();
- off_msg(obj);
- }
- HLevitation--;
- /* probably moot; we're either still levitating or went
- through float_down(), but make sure BFlying is up to date */
- float_vs_flight();
+ register struct obj *obj;
+ int dmg;
+ boolean lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS),
+ innate_lev = ((HLevitation & (FROMOUTSIDE|FROMFORM)) != 0L),
+ ufall = (!innate_lev && !(HFlying || EFlying)); /* BFlying */
+
+ if (!ufall) {
+ You(innate_lev ? "wobble unsteadily for a moment." :
+ "gain control of your flight.");
+ } else {
+ long save_ELev = ELevitation, save_HLev = HLevitation;
+
+ /* fake removal of levitation in advance so that final
+ disclosure will be right in case this turns out to
+ be fatal; fortunately the fact that rings and boots
+ are really still worn has no effect on bones data */
+ ELevitation = HLevitation = 0L;
+ You("crash to the floor!");
+ dmg = rn1(8, 25 - (int)ACURR(A_CON));
+ losehp(Maybe_Half_Phys(dmg),
+ fell_on_sink, NO_KILLER_PREFIX);
+ exercise(A_DEX, FALSE);
+ selftouch("Falling, you");
+ for (obj = level.objects[u.ux][u.uy]; obj; obj = obj->nexthere)
+ if (obj->oclass == WEAPON_CLASS || is_weptool(obj)) {
+ You("fell on %s.", doname(obj));
+ losehp(Maybe_Half_Phys(rnd(3)), fell_on_sink, NO_KILLER_PREFIX);
+ exercise(A_CON, FALSE);
+ }
+ ELevitation = save_ELev;
+ HLevitation = save_HLev;
+ }
+
+ /*
+ * Interrupt multi-turn putting on/taking off of armor (in which
+ * case we reached the sink due to being teleported while busy;
+ * in 3.4.3, Boots_on()/Boots_off() [called via (*aftermv)() when
+ * 'multi' reaches 0] triggered a crash if we were donning/doffing
+ * levitation boots [because the Boots_off() below causes 'uarmf'
+ * to be null by the time 'aftermv' gets called]).
+ *
+ * Interrupt donning/doffing if we fall onto the sink, or if the
+ * code below is going to remove levitation boots even when we
+ * haven't fallen (innate floating or flying becoming unblocked).
+ */
+ if (ufall || lev_boots) {
+ (void) stop_donning(lev_boots ? uarmf : (struct obj *)0);
+ /* recalculate in case uarmf just got set to null */
+ lev_boots = (uarmf && uarmf->otyp == LEVITATION_BOOTS);
+ }
+
+ /* remove worn levitation items */
+ ELevitation &= ~W_ARTI;
+ HLevitation &= ~(I_SPECIAL|TIMEOUT);
+ HLevitation++;
+ if(uleft && uleft->otyp == RIN_LEVITATION) {
+ obj = uleft;
+ Ring_off(obj);
+ off_msg(obj);
+ }
+ if(uright && uright->otyp == RIN_LEVITATION) {
+ obj = uright;
+ Ring_off(obj);
+ off_msg(obj);
+ }
+ if (lev_boots) {
+ obj = uarmf;
+ (void)Boots_off();
+ off_msg(obj);
+ }
+ HLevitation--;
+ /* probably moot; we're either still levitating or went
+ through float_down(), but make sure BFlying is up to date */
+ float_vs_flight();
}
boolean
/* intended to be called only on ROCKs */
{
return (boolean)(!(IS_STWALL(levl[x][y].typ) &&
- (levl[x][y].wall_info & W_NONDIGGABLE)));
+ (levl[x][y].wall_info & W_NONDIGGABLE)));
}
boolean
register xchar x,y;
{
return (boolean)(!(IS_STWALL(levl[x][y].typ) &&
- (levl[x][y].wall_info & W_NONPASSWALL)));
+ (levl[x][y].wall_info & W_NONPASSWALL)));
}
boolean
struct permonst *mdat;
register xchar x,y;
{
- return((boolean) ((Sokoban && sobj_at(BOULDER,x,y)) ||
- (IS_ROCK(levl[x][y].typ)
- && (!tunnels(mdat) || needspick(mdat) || !may_dig(x,y))
- && !(passes_walls(mdat) && may_passwall(x,y)))));
+ return((boolean) ((Sokoban && sobj_at(BOULDER,x,y)) ||
+ (IS_ROCK(levl[x][y].typ)
+ && (!tunnels(mdat) || needspick(mdat) || !may_dig(x,y))
+ && !(passes_walls(mdat) && may_passwall(x,y)))));
}
/* caller has already decided that it's a tight diagonal; check whether a
/* too big? */
if (bigmonst(ptr) &&
- !(amorphous(ptr) || is_whirly(ptr) ||
- noncorporeal(ptr) || slithy(ptr) || can_fog(mon))) return 1;
+ !(amorphous(ptr) || is_whirly(ptr) ||
+ noncorporeal(ptr) || slithy(ptr) || can_fog(mon))) return 1;
/* lugging too much junk? */
amt = (mon == &youmonst) ? inv_weight() + weight_cap() :
- curr_mon_load(mon);
+ curr_mon_load(mon);
if (amt > 600) return 2;
/* Sokoban restriction applies to hero only */
invocation_pos(x, y)
xchar x, y;
{
- return((boolean)(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y));
+ return((boolean)(Invocation_lev(&u.uz) && x == inv_pos.x && y == inv_pos.y));
}
/* return TRUE if (dx,dy) is an OK place to move
* Check for physical obstacles. First, the place we are going.
*/
if (IS_ROCK(tmpr->typ) || tmpr->typ == IRONBARS) {
- if (Blind && mode == DO_MOVE) feel_location(x,y);
- if (Passes_walls && may_passwall(x,y)) {
- ; /* do nothing */
- } else if (tmpr->typ == IRONBARS) {
- if (!(Passes_walls || passes_bars(youmonst.data)))
- return FALSE;
- } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
- /* Eat the rock. */
- if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
- } else if (flags.autodig && !context.run && !context.nopick &&
- uwep && is_pick(uwep)) {
- /* MRKR: Automatic digging when wielding the appropriate tool */
- if (mode == DO_MOVE)
- (void) use_pick_axe2(uwep);
- return FALSE;
- } else {
- if (mode == DO_MOVE) {
- if (Is_stronghold(&u.uz) && is_db_wall(x,y))
- pline_The("drawbridge is up!");
- /* sokoban restriction stays even after puzzle is solved */
- if (Passes_walls && !may_passwall(x,y) && In_sokoban(&u.uz))
- pline_The("Sokoban walls resist your ability.");
- }
- return FALSE;
- }
+ if (Blind && mode == DO_MOVE) feel_location(x,y);
+ if (Passes_walls && may_passwall(x,y)) {
+ ; /* do nothing */
+ } else if (tmpr->typ == IRONBARS) {
+ if (!(Passes_walls || passes_bars(youmonst.data)))
+ return FALSE;
+ } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
+ /* Eat the rock. */
+ if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
+ } else if (flags.autodig && !context.run && !context.nopick &&
+ uwep && is_pick(uwep)) {
+ /* MRKR: Automatic digging when wielding the appropriate tool */
+ if (mode == DO_MOVE)
+ (void) use_pick_axe2(uwep);
+ return FALSE;
+ } else {
+ if (mode == DO_MOVE) {
+ if (Is_stronghold(&u.uz) && is_db_wall(x,y))
+ pline_The("drawbridge is up!");
+ /* sokoban restriction stays even after puzzle is solved */
+ if (Passes_walls && !may_passwall(x,y) && In_sokoban(&u.uz))
+ pline_The("Sokoban walls resist your ability.");
+ }
+ return FALSE;
+ }
} else if (IS_DOOR(tmpr->typ)) {
- if (closed_door(x,y)) {
- if (Blind && mode == DO_MOVE) feel_location(x,y);
- if (Passes_walls)
- ; /* do nothing */
- else if (can_ooze(&youmonst)) {
- if (mode == DO_MOVE) You("ooze under the door.");
- } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
- /* Eat the door. */
- if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
- } else {
- if (mode == DO_MOVE) {
- if (amorphous(youmonst.data))
- You("try to ooze under the door, but can't squeeze your possessions through.");
- else if (x == ux || y == uy) {
- if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) {
- if (u.usteed) {
- You_cant("lead %s through that closed door.",
- y_monnam(u.usteed));
- } else {
- pline("Ouch! You bump into a door.");
- exercise(A_DEX, FALSE);
- }
- } else pline("That door is closed.");
- }
- } else if (mode == TEST_TRAV) goto testdiag;
- return FALSE;
- }
- } else {
- testdiag:
- if (dx && dy && !Passes_walls
- && (!doorless_door(x, y) || block_door(x, y))) {
- /* Diagonal moves into a door are not allowed. */
- if (Blind && mode == DO_MOVE)
- feel_location(x,y);
- return FALSE;
- }
- }
+ if (closed_door(x,y)) {
+ if (Blind && mode == DO_MOVE) feel_location(x,y);
+ if (Passes_walls)
+ ; /* do nothing */
+ else if (can_ooze(&youmonst)) {
+ if (mode == DO_MOVE) You("ooze under the door.");
+ } else if (tunnels(youmonst.data) && !needspick(youmonst.data)) {
+ /* Eat the door. */
+ if (mode == DO_MOVE && still_chewing(x,y)) return FALSE;
+ } else {
+ if (mode == DO_MOVE) {
+ if (amorphous(youmonst.data))
+ You("try to ooze under the door, but can't squeeze your possessions through.");
+ else if (x == ux || y == uy) {
+ if (Blind || Stunned || ACURR(A_DEX) < 10 || Fumbling) {
+ if (u.usteed) {
+ You_cant("lead %s through that closed door.",
+ y_monnam(u.usteed));
+ } else {
+ pline("Ouch! You bump into a door.");
+ exercise(A_DEX, FALSE);
+ }
+ } else pline("That door is closed.");
+ }
+ } else if (mode == TEST_TRAV) goto testdiag;
+ return FALSE;
+ }
+ } else {
+ testdiag:
+ if (dx && dy && !Passes_walls
+ && (!doorless_door(x, y) || block_door(x, y))) {
+ /* Diagonal moves into a door are not allowed. */
+ if (Blind && mode == DO_MOVE)
+ feel_location(x,y);
+ return FALSE;
+ }
+ }
}
if (dx && dy
- && bad_rock(youmonst.data,ux,y) && bad_rock(youmonst.data,x,uy)) {
- /* Move at a diagonal. */
- switch (cant_squeeze_thru(&youmonst)) {
- case 3:
- if (mode == DO_MOVE) You("cannot pass that way.");
- return FALSE;
- case 2:
- if (mode == DO_MOVE) You("are carrying too much to get through.");
- return FALSE;
- case 1:
- if (mode == DO_MOVE) Your("body is too large to fit through.");
- return FALSE;
- default:
- break; /* can squeeze through */
- }
+ && bad_rock(youmonst.data,ux,y) && bad_rock(youmonst.data,x,uy)) {
+ /* Move at a diagonal. */
+ switch (cant_squeeze_thru(&youmonst)) {
+ case 3:
+ if (mode == DO_MOVE) You("cannot pass that way.");
+ return FALSE;
+ case 2:
+ if (mode == DO_MOVE) You("are carrying too much to get through.");
+ return FALSE;
+ case 1:
+ if (mode == DO_MOVE) Your("body is too large to fit through.");
+ return FALSE;
+ default:
+ break; /* can squeeze through */
+ }
} else if (dx && dy && worm_cross(ux, uy, x, y)) {
- /* consecutive long worm segments are at <ux,y> and <x,uy> */
- if (mode == DO_MOVE) pline("%s is in your way.", Monnam(m_at(ux, y)));
- return FALSE;
+ /* consecutive long worm segments are at <ux,y> and <x,uy> */
+ if (mode == DO_MOVE) pline("%s is in your way.", Monnam(m_at(ux, y)));
+ return FALSE;
}
/* Pick travel path that does not require crossing a trap.
* Avoid water and lava using the usual running rules.
* (but not u.ux/u.uy because findtravelpath walks toward u.ux/u.uy) */
if (context.run == 8 && mode != DO_MOVE && (x != u.ux || y != u.uy)) {
- struct trap* t = t_at(x, y);
+ struct trap* t = t_at(x, y);
- if ((t && t->tseen) ||
- (!Levitation && !Flying &&
- !is_clinger(youmonst.data) &&
- is_pool_or_lava(x, y) && levl[x][y].seenv))
- return FALSE;
+ if ((t && t->tseen) ||
+ (!Levitation && !Flying &&
+ !is_clinger(youmonst.data) &&
+ is_pool_or_lava(x, y) && levl[x][y].seenv))
+ return FALSE;
}
ust = &levl[ux][uy];
/* Now see if other things block our way . . */
if (dx && dy && !Passes_walls && IS_DOOR(ust->typ) &&
- (!doorless_door(ux, uy) || block_entry(x, y))) {
- /* Can't move at a diagonal out of a doorway with door. */
- return FALSE;
+ (!doorless_door(ux, uy) || block_entry(x, y))) {
+ /* Can't move at a diagonal out of a doorway with door. */
+ return FALSE;
}
if (sobj_at(BOULDER,x,y) && (Sokoban || !Passes_walls)) {
- if (!(Blind || Hallucination) && (context.run >= 2) && mode != TEST_TRAV)
- return FALSE;
- if (mode == DO_MOVE) {
- /* tunneling monsters will chew before pushing */
- if (tunnels(youmonst.data) && !needspick(youmonst.data) &&
- !Sokoban) {
- if (still_chewing(x,y)) return FALSE;
- } else
- if (moverock() < 0) return FALSE;
- } else if (mode == TEST_TRAV) {
- struct obj* obj;
-
- /* don't pick two boulders in a row, unless there's a way thru */
- if (sobj_at(BOULDER,ux,uy) && !Sokoban) {
- if (!Passes_walls &&
- !(tunnels(youmonst.data) && !needspick(youmonst.data)) &&
- !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK) &&
- !((obj = carrying(WAN_DIGGING)) &&
- !objects[obj->otyp].oc_name_known))
- return FALSE;
- }
- }
- /* assume you'll be able to push it when you get there... */
+ if (!(Blind || Hallucination) && (context.run >= 2) && mode != TEST_TRAV)
+ return FALSE;
+ if (mode == DO_MOVE) {
+ /* tunneling monsters will chew before pushing */
+ if (tunnels(youmonst.data) && !needspick(youmonst.data) &&
+ !Sokoban) {
+ if (still_chewing(x,y)) return FALSE;
+ } else
+ if (moverock() < 0) return FALSE;
+ } else if (mode == TEST_TRAV) {
+ struct obj* obj;
+
+ /* don't pick two boulders in a row, unless there's a way thru */
+ if (sobj_at(BOULDER,ux,uy) && !Sokoban) {
+ if (!Passes_walls &&
+ !(tunnels(youmonst.data) && !needspick(youmonst.data)) &&
+ !carrying(PICK_AXE) && !carrying(DWARVISH_MATTOCK) &&
+ !((obj = carrying(WAN_DIGGING)) &&
+ !objects[obj->otyp].oc_name_known))
+ return FALSE;
+ }
+ }
+ /* assume you'll be able to push it when you get there... */
}
/* OK, it is a legal place to move. */
int
wiz_debug_cmd_traveldisplay() /* in this case, toggle display of travel debug info */
{
- trav_debug = !trav_debug;
- return 0;
+ trav_debug = !trav_debug;
+ return 0;
}
#endif /* DEBUG */
{
/* if travel to adjacent, reachable location, use normal movement rules */
if (!guess && context.travel1 && distmin(u.ux, u.uy, u.tx, u.ty) == 1 &&
- !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
- context.run = 0;
- if (test_move(u.ux, u.uy, u.tx-u.ux, u.ty-u.uy, TEST_MOVE)) {
- u.dx = u.tx-u.ux;
- u.dy = u.ty-u.uy;
- nomul(0);
- iflags.travelcc.x = iflags.travelcc.y = -1;
- return TRUE;
- }
- context.run = 8;
+ !(u.ux != u.tx && u.uy != u.ty && NODIAG(u.umonnum))) {
+ context.run = 0;
+ if (test_move(u.ux, u.uy, u.tx-u.ux, u.ty-u.uy, TEST_MOVE)) {
+ u.dx = u.tx-u.ux;
+ u.dy = u.ty-u.uy;
+ nomul(0);
+ iflags.travelcc.x = iflags.travelcc.y = -1;
+ return TRUE;
+ }
+ context.run = 8;
}
if (u.tx != u.ux || u.ty != u.uy) {
- xchar travel[COLNO][ROWNO];
- xchar travelstepx[2][COLNO*ROWNO];
- xchar travelstepy[2][COLNO*ROWNO];
- xchar tx, ty, ux, uy;
- int n = 1; /* max offset in travelsteps */
- int set = 0; /* two sets current and previous */
- int radius = 1; /* search radius */
- int i;
-
- /* If guessing, first find an "obvious" goal location. The obvious
- * goal is the position the player knows of, or might figure out
- * (couldsee) that is closest to the target on a straight path.
- */
- if (guess) {
- tx = u.ux; ty = u.uy; ux = u.tx; uy = u.ty;
- } else {
- tx = u.tx; ty = u.ty; ux = u.ux; uy = u.uy;
- }
+ xchar travel[COLNO][ROWNO];
+ xchar travelstepx[2][COLNO*ROWNO];
+ xchar travelstepy[2][COLNO*ROWNO];
+ xchar tx, ty, ux, uy;
+ int n = 1; /* max offset in travelsteps */
+ int set = 0; /* two sets current and previous */
+ int radius = 1; /* search radius */
+ int i;
+
+ /* If guessing, first find an "obvious" goal location. The obvious
+ * goal is the position the player knows of, or might figure out
+ * (couldsee) that is closest to the target on a straight path.
+ */
+ if (guess) {
+ tx = u.ux; ty = u.uy; ux = u.tx; uy = u.ty;
+ } else {
+ tx = u.tx; ty = u.ty; ux = u.ux; uy = u.uy;
+ }
noguess:
- (void) memset((genericptr_t)travel, 0, sizeof(travel));
- travelstepx[0][0] = tx;
- travelstepy[0][0] = ty;
-
- while (n != 0) {
- int nn = 0;
-
- for (i = 0; i < n; i++) {
- int dir;
- int x = travelstepx[set][i];
- int y = travelstepy[set][i];
- static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
- /* no diagonal movement for grid bugs */
- int dirmax = NODIAG(u.umonnum) ? 4 : 8;
-
- for (dir = 0; dir < dirmax; ++dir) {
- int nx = x+xdir[ordered[dir]];
- int ny = y+ydir[ordered[dir]];
-
- if (!isok(nx, ny)) continue;
- if ((!Passes_walls && !can_ooze(&youmonst) &&
- closed_door(x, y)) || sobj_at(BOULDER, x, y)) {
- /* closed doors and boulders usually
- * cause a delay, so prefer another path */
- if (travel[x][y] > radius-3) {
- travelstepx[1-set][nn] = x;
- travelstepy[1-set][nn] = y;
- /* don't change travel matrix! */
- nn++;
- continue;
- }
- }
- if (test_move(x, y, nx-x, ny-y, TEST_TRAV) &&
- (levl[nx][ny].seenv || (!Blind && couldsee(nx, ny)))) {
- if (nx == ux && ny == uy) {
- if (!guess) {
- u.dx = x-ux;
- u.dy = y-uy;
- if (x == u.tx && y == u.ty) {
- nomul(0);
- /* reset run so domove run checks work */
- context.run = 8;
- iflags.travelcc.x = iflags.travelcc.y = -1;
- }
- return TRUE;
- }
- } else if (!travel[nx][ny]) {
- travelstepx[1-set][nn] = nx;
- travelstepy[1-set][nn] = ny;
- travel[nx][ny] = radius;
- nn++;
- }
- }
- }
- }
+ (void) memset((genericptr_t)travel, 0, sizeof(travel));
+ travelstepx[0][0] = tx;
+ travelstepy[0][0] = ty;
+
+ while (n != 0) {
+ int nn = 0;
+
+ for (i = 0; i < n; i++) {
+ int dir;
+ int x = travelstepx[set][i];
+ int y = travelstepy[set][i];
+ static int ordered[] = { 0, 2, 4, 6, 1, 3, 5, 7 };
+ /* no diagonal movement for grid bugs */
+ int dirmax = NODIAG(u.umonnum) ? 4 : 8;
+
+ for (dir = 0; dir < dirmax; ++dir) {
+ int nx = x+xdir[ordered[dir]];
+ int ny = y+ydir[ordered[dir]];
+
+ if (!isok(nx, ny)) continue;
+ if ((!Passes_walls && !can_ooze(&youmonst) &&
+ closed_door(x, y)) || sobj_at(BOULDER, x, y)) {
+ /* closed doors and boulders usually
+ * cause a delay, so prefer another path */
+ if (travel[x][y] > radius-3) {
+ travelstepx[1-set][nn] = x;
+ travelstepy[1-set][nn] = y;
+ /* don't change travel matrix! */
+ nn++;
+ continue;
+ }
+ }
+ if (test_move(x, y, nx-x, ny-y, TEST_TRAV) &&
+ (levl[nx][ny].seenv || (!Blind && couldsee(nx, ny)))) {
+ if (nx == ux && ny == uy) {
+ if (!guess) {
+ u.dx = x-ux;
+ u.dy = y-uy;
+ if (x == u.tx && y == u.ty) {
+ nomul(0);
+ /* reset run so domove run checks work */
+ context.run = 8;
+ iflags.travelcc.x = iflags.travelcc.y = -1;
+ }
+ return TRUE;
+ }
+ } else if (!travel[nx][ny]) {
+ travelstepx[1-set][nn] = nx;
+ travelstepy[1-set][nn] = ny;
+ travel[nx][ny] = radius;
+ nn++;
+ }
+ }
+ }
+ }
#ifdef DEBUG
- if (trav_debug) {
- /* Use of warning glyph is arbitrary. It stands out. */
- tmp_at(DISP_ALL, warning_to_glyph(1));
- for (i = 0; i < nn; ++i) {
- tmp_at(travelstepx[1-set][i], travelstepy[1-set][i]);
- }
- delay_output();
- if (flags.runmode == RUN_CRAWL) {
- delay_output();
- delay_output();
- }
- tmp_at(DISP_END,0);
- }
+ if (trav_debug) {
+ /* Use of warning glyph is arbitrary. It stands out. */
+ tmp_at(DISP_ALL, warning_to_glyph(1));
+ for (i = 0; i < nn; ++i) {
+ tmp_at(travelstepx[1-set][i], travelstepy[1-set][i]);
+ }
+ delay_output();
+ if (flags.runmode == RUN_CRAWL) {
+ delay_output();
+ delay_output();
+ }
+ tmp_at(DISP_END,0);
+ }
#endif /* DEBUG */
- n = nn;
- set = 1-set;
- radius++;
- }
-
- /* if guessing, find best location in travel matrix and go there */
- if (guess) {
- int px = tx, py = ty; /* pick location */
- int dist, nxtdist, d2, nd2;
-
- dist = distmin(ux, uy, tx, ty);
- d2 = dist2(ux, uy, tx, ty);
- for (tx = 1; tx < COLNO; ++tx)
- for (ty = 0; ty < ROWNO; ++ty)
- if (travel[tx][ty]) {
- nxtdist = distmin(ux, uy, tx, ty);
- if (nxtdist == dist && couldsee(tx, ty)) {
- nd2 = dist2(ux, uy, tx, ty);
- if (nd2 < d2) {
- /* prefer non-zigzag path */
- px = tx; py = ty;
- d2 = nd2;
- }
- } else if (nxtdist < dist && couldsee(tx, ty)) {
- px = tx; py = ty;
- dist = nxtdist;
- d2 = dist2(ux, uy, tx, ty);
- }
- }
-
- if (px == u.ux && py == u.uy) {
- /* no guesses, just go in the general direction */
- u.dx = sgn(u.tx - u.ux);
- u.dy = sgn(u.ty - u.uy);
- if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
- return TRUE;
- goto found;
- }
+ n = nn;
+ set = 1-set;
+ radius++;
+ }
+
+ /* if guessing, find best location in travel matrix and go there */
+ if (guess) {
+ int px = tx, py = ty; /* pick location */
+ int dist, nxtdist, d2, nd2;
+
+ dist = distmin(ux, uy, tx, ty);
+ d2 = dist2(ux, uy, tx, ty);
+ for (tx = 1; tx < COLNO; ++tx)
+ for (ty = 0; ty < ROWNO; ++ty)
+ if (travel[tx][ty]) {
+ nxtdist = distmin(ux, uy, tx, ty);
+ if (nxtdist == dist && couldsee(tx, ty)) {
+ nd2 = dist2(ux, uy, tx, ty);
+ if (nd2 < d2) {
+ /* prefer non-zigzag path */
+ px = tx; py = ty;
+ d2 = nd2;
+ }
+ } else if (nxtdist < dist && couldsee(tx, ty)) {
+ px = tx; py = ty;
+ dist = nxtdist;
+ d2 = dist2(ux, uy, tx, ty);
+ }
+ }
+
+ if (px == u.ux && py == u.uy) {
+ /* no guesses, just go in the general direction */
+ u.dx = sgn(u.tx - u.ux);
+ u.dy = sgn(u.ty - u.uy);
+ if (test_move(u.ux, u.uy, u.dx, u.dy, TEST_MOVE))
+ return TRUE;
+ goto found;
+ }
#ifdef DEBUG
- if (trav_debug) {
- /* Use of warning glyph is arbitrary. It stands out. */
- tmp_at(DISP_ALL, warning_to_glyph(2));
- tmp_at(px, py);
- delay_output();
- if (flags.runmode == RUN_CRAWL) {
- delay_output();
- delay_output();
- delay_output();
- delay_output();
- }
- tmp_at(DISP_END,0);
- }
+ if (trav_debug) {
+ /* Use of warning glyph is arbitrary. It stands out. */
+ tmp_at(DISP_ALL, warning_to_glyph(2));
+ tmp_at(px, py);
+ delay_output();
+ if (flags.runmode == RUN_CRAWL) {
+ delay_output();
+ delay_output();
+ delay_output();
+ delay_output();
+ }
+ tmp_at(DISP_END,0);
+ }
#endif /* DEBUG */
- tx = px;
- ty = py;
- ux = u.ux;
- uy = u.uy;
- set = 0;
- n = radius = 1;
- guess = FALSE;
- goto noguess;
- }
- return FALSE;
+ tx = px;
+ ty = py;
+ ux = u.ux;
+ uy = u.uy;
+ set = 0;
+ n = radius = 1;
+ guess = FALSE;
+ goto noguess;
+ }
+ return FALSE;
}
found:
switch (u.utraptype) {
case TT_BEARTRAP:
- if (flags.verbose) {
- predicament = "caught in a bear trap";
- if (u.usteed)
- Norep("%s is %s.", upstart(steedname), predicament);
- else
- Norep("You are %s.", predicament);
- }
- /* [why does diagonal movement give quickest escape?] */
- if ((u.dx && u.dy) || !rn2(5)) u.utrap--;
- break;
+ if (flags.verbose) {
+ predicament = "caught in a bear trap";
+ if (u.usteed)
+ Norep("%s is %s.", upstart(steedname), predicament);
+ else
+ Norep("You are %s.", predicament);
+ }
+ /* [why does diagonal movement give quickest escape?] */
+ if ((u.dx && u.dy) || !rn2(5)) u.utrap--;
+ break;
case TT_PIT:
- if (desttrap && desttrap->tseen &&
- (desttrap->ttyp == PIT || desttrap->ttyp == SPIKED_PIT))
- return TRUE; /* move into adjacent pit */
- /* try to escape; position stays same regardless of success */
- climb_pit();
- break;
+ if (desttrap && desttrap->tseen &&
+ (desttrap->ttyp == PIT || desttrap->ttyp == SPIKED_PIT))
+ return TRUE; /* move into adjacent pit */
+ /* try to escape; position stays same regardless of success */
+ climb_pit();
+ break;
case TT_WEB:
- if (uwep && uwep->oartifact == ART_STING) {
- u.utrap = 0;
- pline("Sting cuts through the web!");
- break; /* escape trap but don't move */
- }
- if (--u.utrap) {
- if (flags.verbose) {
- predicament = "stuck to the web";
- if (u.usteed)
- Norep("%s is %s.", upstart(steedname), predicament);
- else
- Norep("You are %s.", predicament);
- }
- } else {
- if (u.usteed)
- pline("%s breaks out of the web.", upstart(steedname));
- else
- You("disentangle yourself.");
- }
- break;
+ if (uwep && uwep->oartifact == ART_STING) {
+ u.utrap = 0;
+ pline("Sting cuts through the web!");
+ break; /* escape trap but don't move */
+ }
+ if (--u.utrap) {
+ if (flags.verbose) {
+ predicament = "stuck to the web";
+ if (u.usteed)
+ Norep("%s is %s.", upstart(steedname), predicament);
+ else
+ Norep("You are %s.", predicament);
+ }
+ } else {
+ if (u.usteed)
+ pline("%s breaks out of the web.", upstart(steedname));
+ else
+ You("disentangle yourself.");
+ }
+ break;
case TT_LAVA:
- if (flags.verbose) {
- predicament = "stuck in the lava";
- if (u.usteed)
- Norep("%s is %s.", upstart(steedname), predicament);
- else
- Norep("You are %s.", predicament);
- }
- if (!is_lava(x, y)) {
- u.utrap--;
- if ((u.utrap & 0xff) == 0) {
- u.utrap = 0;
- if (u.usteed)
- You("lead %s to the edge of the lava.", steedname);
- else
- You("pull yourself to the edge of the lava.");
- }
- }
- u.umoved = TRUE;
- break;
+ if (flags.verbose) {
+ predicament = "stuck in the lava";
+ if (u.usteed)
+ Norep("%s is %s.", upstart(steedname), predicament);
+ else
+ Norep("You are %s.", predicament);
+ }
+ if (!is_lava(x, y)) {
+ u.utrap--;
+ if ((u.utrap & 0xff) == 0) {
+ u.utrap = 0;
+ if (u.usteed)
+ You("lead %s to the edge of the lava.", steedname);
+ else
+ You("pull yourself to the edge of the lava.");
+ }
+ }
+ u.umoved = TRUE;
+ break;
case TT_INFLOOR:
case TT_BURIEDBALL:
- anchored = (u.utraptype == TT_BURIEDBALL);
- if (anchored) {
- coord cc;
-
- cc.x = u.ux, cc.y = u.uy;
- /* can move normally within radius 1 of buried ball */
- if (buried_ball(&cc) && dist2(x, y, cc.x, cc.y) <= 2) {
- /* ugly hack: we need to issue some message here
- in case "you are chained to the buried ball"
- was the most recent message given, otherwise
- our next attempt to move out of tether range
- after this successful move would have its
- can't-do-that message suppressed by Norep */
- if (flags.verbose)
- Norep("You move within the chain's reach.");
- return TRUE;
- }
- }
- if (--u.utrap) {
- if (flags.verbose) {
- if (anchored) {
- predicament = "chained to the";
- culprit = "buried ball";
- } else {
- predicament = "stuck in the";
- culprit = surface(u.ux, u.uy);
- }
- if (u.usteed) {
- if (anchored)
- Norep("You and %s are %s %s.", steedname,
- predicament, culprit);
- else
- Norep("%s is %s %s.", upstart(steedname),
- predicament, culprit);
- } else
- Norep("You are %s %s.", predicament, culprit);
- }
- } else {
- if (u.usteed)
- pline("%s finally %s free.", upstart(steedname),
- !anchored ? "lurches" : "wrenches the ball");
- else
- You("finally %s free.",
- !anchored ? "wriggle" : "wrench the ball");
- if (anchored)
- buried_ball_to_punishment();
- }
- break;
+ anchored = (u.utraptype == TT_BURIEDBALL);
+ if (anchored) {
+ coord cc;
+
+ cc.x = u.ux, cc.y = u.uy;
+ /* can move normally within radius 1 of buried ball */
+ if (buried_ball(&cc) && dist2(x, y, cc.x, cc.y) <= 2) {
+ /* ugly hack: we need to issue some message here
+ in case "you are chained to the buried ball"
+ was the most recent message given, otherwise
+ our next attempt to move out of tether range
+ after this successful move would have its
+ can't-do-that message suppressed by Norep */
+ if (flags.verbose)
+ Norep("You move within the chain's reach.");
+ return TRUE;
+ }
+ }
+ if (--u.utrap) {
+ if (flags.verbose) {
+ if (anchored) {
+ predicament = "chained to the";
+ culprit = "buried ball";
+ } else {
+ predicament = "stuck in the";
+ culprit = surface(u.ux, u.uy);
+ }
+ if (u.usteed) {
+ if (anchored)
+ Norep("You and %s are %s %s.", steedname,
+ predicament, culprit);
+ else
+ Norep("%s is %s %s.", upstart(steedname),
+ predicament, culprit);
+ } else
+ Norep("You are %s %s.", predicament, culprit);
+ }
+ } else {
+ if (u.usteed)
+ pline("%s finally %s free.", upstart(steedname),
+ !anchored ? "lurches" : "wrenches the ball");
+ else
+ You("finally %s free.",
+ !anchored ? "wriggle" : "wrench the ball");
+ if (anchored)
+ buried_ball_to_punishment();
+ }
+ break;
default:
- impossible("trapmove: stuck in unknown trap? (%d)", (int)u.utraptype);
- break;
+ impossible("trapmove: stuck in unknown trap? (%d)", (int)u.utraptype);
+ break;
}
return FALSE;
}
void
domove()
{
- register struct monst *mtmp;
- register struct rm *tmpr;
- register xchar x,y;
- struct trap *trap;
- int wtcap;
- boolean on_ice;
- xchar chainx, chainy, ballx, bally; /* ball&chain new positions */
- int bc_control; /* control for ball&chain */
- boolean cause_delay = FALSE; /* dragging ball will skip a move */
-
- u_wipe_engr(rnd(5));
-
- if (context.travel) {
- if (!findtravelpath(FALSE))
- (void) findtravelpath(TRUE);
- context.travel1 = 0;
- }
-
- if(((wtcap = near_capacity()) >= OVERLOADED
- || (wtcap > SLT_ENCUMBER &&
- (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
- : (u.uhp < 10 && u.uhp != u.uhpmax))))
- && !Is_airlevel(&u.uz)) {
- if(wtcap < OVERLOADED) {
- You("don't have enough stamina to move.");
- exercise(A_CON, FALSE);
- } else
- You("collapse under your load.");
- nomul(0);
- return;
- }
- if(u.uswallow) {
- u.dx = u.dy = 0;
- u.ux = x = u.ustuck->mx;
- u.uy = y = u.ustuck->my;
- mtmp = u.ustuck;
- } else {
- if (Is_airlevel(&u.uz) && rn2(4) &&
- !Levitation && !Flying) {
- switch(rn2(3)) {
- case 0:
- You("tumble in place.");
- exercise(A_DEX, FALSE);
- break;
- case 1:
- You_cant("control your movements very well."); break;
- case 2:
- pline("It's hard to walk in thin air.");
- exercise(A_DEX, TRUE);
- break;
- }
- return;
- }
-
- /* check slippery ice */
- on_ice = !Levitation && is_ice(u.ux, u.uy);
- if (on_ice) {
- static int skates = 0;
- if (!skates) skates = find_skates();
- if ((uarmf && uarmf->otyp == skates)
- || resists_cold(&youmonst) || Flying
- || is_floater(youmonst.data) || is_clinger(youmonst.data)
- || is_whirly(youmonst.data))
- on_ice = FALSE;
- else if (!rn2(Cold_resistance ? 3 : 2)) {
- HFumbling |= FROMOUTSIDE;
- HFumbling &= ~TIMEOUT;
- HFumbling += 1; /* slip on next move */
- }
- }
- if (!on_ice && (HFumbling & FROMOUTSIDE))
- HFumbling &= ~FROMOUTSIDE;
-
- x = u.ux + u.dx;
- y = u.uy + u.dy;
- if(Stunned || (Confusion && !rn2(5))) {
- register int tries = 0;
-
- do {
- if(tries++ > 50) {
- nomul(0);
- return;
- }
- confdir();
- x = u.ux + u.dx;
- y = u.uy + u.dy;
- } while(!isok(x, y) || bad_rock(youmonst.data, x, y));
- }
- /* turbulence might alter your actual destination */
- if (u.uinwater) {
- water_friction();
- if (!u.dx && !u.dy) {
- nomul(0);
- return;
- }
- x = u.ux + u.dx;
- y = u.uy + u.dy;
- }
- if(!isok(x, y)) {
- nomul(0);
- return;
- }
- if (((trap = t_at(x, y)) && trap->tseen) ||
- (Blind && !Levitation && !Flying &&
- !is_clinger(youmonst.data) &&
- is_pool_or_lava(x, y) && levl[x][y].seenv)) {
- if(context.run >= 2) {
- nomul(0);
- context.move = 0;
- return;
- } else
- nomul(0);
- }
-
- if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
- if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
- /* perhaps it fled (or was teleported or ... ) */
- u.ustuck = 0;
- } else if (sticks(youmonst.data)) {
- /* When polymorphed into a sticking monster,
- * u.ustuck means it's stuck to you, not you to it.
- */
- You("release %s.", mon_nam(u.ustuck));
- u.ustuck = 0;
- } else {
- /* If holder is asleep or paralyzed:
- * 37.5% chance of getting away,
- * 12.5% chance of waking/releasing it;
- * otherwise:
- * 7.5% chance of getting away.
- * [strength ought to be a factor]
- * If holder is tame and there is no conflict,
- * guaranteed escape.
- */
- switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
- case 0: case 1: case 2:
- pull_free:
- You("pull free from %s.", mon_nam(u.ustuck));
- u.ustuck = 0;
- break;
- case 3:
- if (!u.ustuck->mcanmove) {
- /* it's free to move on next turn */
- u.ustuck->mfrozen = 1;
- u.ustuck->msleeping = 0;
- }
- /*FALLTHRU*/
- default:
- if (u.ustuck->mtame &&
- !Conflict && !u.ustuck->mconf)
- goto pull_free;
- You("cannot escape from %s!", mon_nam(u.ustuck));
- nomul(0);
- return;
- }
- }
- }
-
- mtmp = m_at(x,y);
- if (mtmp) {
- /* Don't attack if you're running, and can see it */
- /* We should never get here if forcefight */
- if (context.run &&
- ((!Blind && mon_visible(mtmp) &&
- ((mtmp->m_ap_type != M_AP_FURNITURE &&
- mtmp->m_ap_type != M_AP_OBJECT) ||
- Protection_from_shape_changers)) ||
- sensemon(mtmp))) {
- nomul(0);
- context.move = 0;
- return;
- }
- }
- }
-
- u.ux0 = u.ux;
- u.uy0 = u.uy;
- bhitpos.x = x;
- bhitpos.y = y;
- tmpr = &levl[x][y];
-
- /* attack monster */
- if(mtmp) {
- nomul(0);
- /* only attack if we know it's there */
- /* or if we used the 'F' command to fight blindly */
- /* or if it hides_under, in which case we call attack() to print
- * the Wait! message.
- * This is different from ceiling hiders, who aren't handled in
- * attack().
- */
-
- /* If they used a 'm' command, trying to move onto a monster
- * prints the below message and wastes a turn. The exception is
- * if the monster is unseen and the player doesn't remember an
- * invisible monster--then, we fall through to attack() and
- * attack_check(), which still wastes a turn, but prints a
- * different message and makes the player remember the monster. */
- if(context.nopick &&
- (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))){
- if(mtmp->m_ap_type && !Protection_from_shape_changers
- && !sensemon(mtmp))
- stumble_onto_mimic(mtmp);
- else if (mtmp->mpeaceful && !Hallucination)
- pline("Pardon me, %s.", m_monnam(mtmp));
- else
- You("move right into %s.", mon_nam(mtmp));
- return;
- }
- if(context.forcefight || !mtmp->mundetected || sensemon(mtmp) ||
- ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) &&
- !is_safepet(mtmp))){
- /* try to attack; note that it might evade */
- /* also, we don't attack tame when _safepet_ */
- if(attack(mtmp)) return;
- }
- }
-
- /* specifying 'F' with no monster wastes a turn */
- if (context.forcefight ||
- /* remembered an 'I' && didn't use a move command */
- (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
- struct obj *boulder = sobj_at(BOULDER, x, y);
- boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
- solid = !accessible(x, y);
- int glyph = glyph_at(x, y); /* might be monster */
- char buf[BUFSZ];
-
- /* if a statue is displayed at the target location,
- player is attempting to attack it [and boulder
- handlng below is suitable for handling that] */
- if (glyph_is_statue(glyph) ||
- (Hallucination && glyph_is_monster(glyph)))
- boulder = sobj_at(STATUE, x, y);
-
- /* force fight at boulder/statue or wall/door while wielding
- pick: start digging to break the boulder or wall */
- if (context.forcefight &&
- /* can we dig? */
- uwep && dig_typ(uwep, x, y) &&
- /* should we dig? */
- !glyph_is_invisible(glyph) &&
- !glyph_is_monster(glyph)) {
- (void)use_pick_axe2(uwep);
- return;
- }
-
- if (boulder)
- Strcpy(buf, ansimpleoname(boulder));
- else if (solid)
- Strcpy(buf, the(defsyms[glyph_to_cmap(glyph)].explanation));
- else if (!Underwater)
- Strcpy(buf, "thin air");
- else if (is_pool(x, y))
- Strcpy(buf, "empty water");
- else /* Underwater, targetting non-water */
- Sprintf(buf, "a vacant spot on the %s", surface(x,y));
- You("%s%s %s.",
- !(boulder || solid) ? "" :
- !explo ? "harmlessly " : "futilely ",
- explo ? "explode at" : "attack",
- buf);
- unmap_object(x, y); /* known empty -- remove 'I' if present */
- if (boulder) map_object(boulder, TRUE);
- newsym(x, y);
- nomul(0);
- if (explo) {
- wake_nearby();
- u.mh = -1; /* dead in the current form */
- rehumanize();
- }
- return;
- }
- if (glyph_is_invisible(levl[x][y].glyph)) {
- unmap_object(x, y);
- newsym(x, y);
- }
- /* not attacking an animal, so we try to move */
- if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
- nomul(0);
- return;
- }
- if(!youmonst.data->mmove) {
- You("are rooted %s.",
- Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
- "in place" : "to the ground");
- nomul(0);
- return;
- }
- if(u.utrap) {
- if (!trapmove(x, y, trap)) return;
- }
-
- if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, DO_MOVE)) {
- context.move = 0;
- nomul(0);
- return;
- }
-
- /* Move ball and chain. */
- if (Punished)
- if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy,
- &cause_delay, TRUE))
- return;
-
- /* Check regions entering/leaving */
- if (!in_out_region(x,y))
- return;
-
- /* now move the hero */
- mtmp = m_at(x, y);
- u.ux += u.dx;
- u.uy += u.dy;
- /* Move your steed, too */
- if (u.usteed) {
- u.usteed->mx = u.ux;
- u.usteed->my = u.uy;
- exercise_steed();
- }
-
- /*
- * If safepet at destination then move the pet to the hero's
- * previous location using the same conditions as in attack().
- * there are special extenuating circumstances:
- * (1) if the pet dies then your god angers,
- * (2) if the pet gets trapped then your god may disapprove,
- * (3) if the pet was already trapped and you attempt to free it
- * not only do you encounter the trap but you may frighten your
- * pet causing it to go wild! moral: don't abuse this privilege.
- *
- * Ceiling-hiding pets are skipped by this section of code, to
- * be caught by the normal falling-monster code.
- */
- if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
- /* if trapped, there's a chance the pet goes wild */
- if (mtmp->mtrapped) {
- if (!rn2(mtmp->mtame)) {
- mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
- if (mtmp->mleashed) m_unleash(mtmp, TRUE);
- growl(mtmp);
- } else {
- yelp(mtmp);
- }
- }
- mtmp->mundetected = 0;
- if (mtmp->m_ap_type) seemimic(mtmp);
- else if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my);
-
- if (mtmp->mtrapped &&
- (trap = t_at(mtmp->mx, mtmp->my)) != 0 &&
- (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) &&
- sobj_at(BOULDER, trap->tx, trap->ty)) {
- /* can't swap places with pet pinned in a pit by a boulder */
- u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
- } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
- /* can't swap places when pet can't move to your spot */
- u.ux = u.ux0, u.uy = u.uy0;
- You("stop. %s can't move diagonally.",
- upstart(y_monnam(mtmp)));
- } else if (u.ux0 != x && u.uy0 != y &&
- bad_rock(mtmp->data, x, u.uy0) &&
- bad_rock(mtmp->data, u.ux0, y) &&
- (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
- /* can't swap places when pet won't fit thru the opening */
- u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
- You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
- } else {
- char pnambuf[BUFSZ];
-
- /* save its current description in case of polymorph */
- Strcpy(pnambuf, y_monnam(mtmp));
- mtmp->mtrapped = 0;
- remove_monster(x, y);
- place_monster(mtmp, u.ux0, u.uy0);
- newsym(x, y);
- newsym(u.ux0, u.uy0);
-
- You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
- pnambuf);
-
- /* check for displacing it into pools and traps */
- switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
- case 0:
- break;
- case 1: /* trapped */
- case 3: /* changed levels */
- /* there's already been a trap message, reinforce it */
- abuse_dog(mtmp);
- adjalign(-3);
- break;
- case 2:
- /* drowned or died...
- * you killed your pet by direct action, so get experience
- * and possibly penalties;
- * we want the level gain message, if it happens, to occur
- * before the guilt message below
- */
- {
- /* minliquid() and mintrap() call mondead() rather than
- killed() so we duplicate some of the latter here */
- int tmp, mndx;
-
- u.uconduct.killer++;
- mndx = monsndx(mtmp->data);
- tmp = experience(mtmp, (int)mvitals[mndx].died);
- more_experienced(tmp, 0);
- newexplevel(); /* will decide if you go up */
- }
- /* That's no way to treat a pet! Your god gets angry.
- *
- * [This has always been pretty iffy. Why does your
- * patron deity care at all, let alone enough to get mad?]
- */
- if (rn2(4)) {
- You_feel("guilty about losing your pet like this.");
- u.ugangr++;
- adjalign(-15);
- }
- break;
- default:
- pline("that's strange, unknown mintrap result!");
- break;
- }
- }
- }
-
- reset_occupations();
- if (context.run) {
- if ( context.run < 8 )
- if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) ||
- IS_FURNITURE(tmpr->typ))
- nomul(0);
- }
-
- if (hides_under(youmonst.data) || (youmonst.data->mlet == S_EEL) ||
- u.dx || u.dy)
- (void) hideunder(&youmonst);
-
- /*
- * Mimics (or whatever) become noticeable if they move and are
- * imitating something that doesn't move. We could extend this
- * to non-moving monsters...
- */
- if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
- || youmonst.m_ap_type == M_AP_FURNITURE))
- youmonst.m_ap_type = M_AP_NOTHING;
-
- check_leash(u.ux0,u.uy0);
-
- if(u.ux0 != u.ux || u.uy0 != u.uy) {
- u.umoved = TRUE;
- /* Clean old position -- vision_recalc() will print our new one. */
- newsym(u.ux0,u.uy0);
- /* Since the hero has moved, adjust what can be seen/unseen. */
- vision_recalc(1); /* Do the work now in the recover time. */
- invocation_message();
- }
-
- if (Punished) /* put back ball and chain */
- move_bc(0,bc_control,ballx,bally,chainx,chainy);
-
- spoteffects(TRUE);
-
- /* delay next move because of ball dragging */
- /* must come after we finished picking up, in spoteffects() */
- if (cause_delay) {
- nomul(-2);
- nomovemsg = "";
- }
-
- if (context.run && flags.runmode != RUN_TPORT) {
- /* display every step or every 7th step depending upon mode */
- if (flags.runmode != RUN_LEAP || !(moves % 7L)) {
- if (flags.time) context.botl = 1;
- curs_on_u();
- delay_output();
- if (flags.runmode == RUN_CRAWL) {
- delay_output();
- delay_output();
- delay_output();
- delay_output();
- }
- }
- }
+ register struct monst *mtmp;
+ register struct rm *tmpr;
+ register xchar x,y;
+ struct trap *trap = NULL;
+ int wtcap;
+ boolean on_ice;
+ xchar chainx, chainy, ballx, bally; /* ball&chain new positions */
+ int bc_control; /* control for ball&chain */
+ boolean cause_delay = FALSE; /* dragging ball will skip a move */
+
+ u_wipe_engr(rnd(5));
+
+ if (context.travel) {
+ if (!findtravelpath(FALSE))
+ (void) findtravelpath(TRUE);
+ context.travel1 = 0;
+ }
+
+ if(((wtcap = near_capacity()) >= OVERLOADED
+ || (wtcap > SLT_ENCUMBER &&
+ (Upolyd ? (u.mh < 5 && u.mh != u.mhmax)
+ : (u.uhp < 10 && u.uhp != u.uhpmax))))
+ && !Is_airlevel(&u.uz)) {
+ if(wtcap < OVERLOADED) {
+ You("don't have enough stamina to move.");
+ exercise(A_CON, FALSE);
+ } else
+ You("collapse under your load.");
+ nomul(0);
+ return;
+ }
+ if(u.uswallow) {
+ u.dx = u.dy = 0;
+ u.ux = x = u.ustuck->mx;
+ u.uy = y = u.ustuck->my;
+ mtmp = u.ustuck;
+ } else {
+ if (Is_airlevel(&u.uz) && rn2(4) &&
+ !Levitation && !Flying) {
+ switch(rn2(3)) {
+ case 0:
+ You("tumble in place.");
+ exercise(A_DEX, FALSE);
+ break;
+ case 1:
+ You_cant("control your movements very well."); break;
+ case 2:
+ pline("It's hard to walk in thin air.");
+ exercise(A_DEX, TRUE);
+ break;
+ }
+ return;
+ }
+
+ /* check slippery ice */
+ on_ice = !Levitation && is_ice(u.ux, u.uy);
+ if (on_ice) {
+ static int skates = 0;
+ if (!skates) skates = find_skates();
+ if ((uarmf && uarmf->otyp == skates)
+ || resists_cold(&youmonst) || Flying
+ || is_floater(youmonst.data) || is_clinger(youmonst.data)
+ || is_whirly(youmonst.data))
+ on_ice = FALSE;
+ else if (!rn2(Cold_resistance ? 3 : 2)) {
+ HFumbling |= FROMOUTSIDE;
+ HFumbling &= ~TIMEOUT;
+ HFumbling += 1; /* slip on next move */
+ }
+ }
+ if (!on_ice && (HFumbling & FROMOUTSIDE))
+ HFumbling &= ~FROMOUTSIDE;
+
+ x = u.ux + u.dx;
+ y = u.uy + u.dy;
+ if(Stunned || (Confusion && !rn2(5))) {
+ register int tries = 0;
+
+ do {
+ if(tries++ > 50) {
+ nomul(0);
+ return;
+ }
+ confdir();
+ x = u.ux + u.dx;
+ y = u.uy + u.dy;
+ } while(!isok(x, y) || bad_rock(youmonst.data, x, y));
+ }
+ /* turbulence might alter your actual destination */
+ if (u.uinwater) {
+ water_friction();
+ if (!u.dx && !u.dy) {
+ nomul(0);
+ return;
+ }
+ x = u.ux + u.dx;
+ y = u.uy + u.dy;
+ }
+ if(!isok(x, y)) {
+ nomul(0);
+ return;
+ }
+ if (((trap = t_at(x, y)) && trap->tseen) ||
+ (Blind && !Levitation && !Flying &&
+ !is_clinger(youmonst.data) &&
+ is_pool_or_lava(x, y) && levl[x][y].seenv)) {
+ if(context.run >= 2) {
+ nomul(0);
+ context.move = 0;
+ return;
+ } else
+ nomul(0);
+ }
+
+ if (u.ustuck && (x != u.ustuck->mx || y != u.ustuck->my)) {
+ if (distu(u.ustuck->mx, u.ustuck->my) > 2) {
+ /* perhaps it fled (or was teleported or ... ) */
+ u.ustuck = 0;
+ } else if (sticks(youmonst.data)) {
+ /* When polymorphed into a sticking monster,
+ * u.ustuck means it's stuck to you, not you to it.
+ */
+ You("release %s.", mon_nam(u.ustuck));
+ u.ustuck = 0;
+ } else {
+ /* If holder is asleep or paralyzed:
+ * 37.5% chance of getting away,
+ * 12.5% chance of waking/releasing it;
+ * otherwise:
+ * 7.5% chance of getting away.
+ * [strength ought to be a factor]
+ * If holder is tame and there is no conflict,
+ * guaranteed escape.
+ */
+ switch (rn2(!u.ustuck->mcanmove ? 8 : 40)) {
+ case 0: case 1: case 2:
+ pull_free:
+ You("pull free from %s.", mon_nam(u.ustuck));
+ u.ustuck = 0;
+ break;
+ case 3:
+ if (!u.ustuck->mcanmove) {
+ /* it's free to move on next turn */
+ u.ustuck->mfrozen = 1;
+ u.ustuck->msleeping = 0;
+ }
+ /*FALLTHRU*/
+ default:
+ if (u.ustuck->mtame &&
+ !Conflict && !u.ustuck->mconf)
+ goto pull_free;
+ You("cannot escape from %s!", mon_nam(u.ustuck));
+ nomul(0);
+ return;
+ }
+ }
+ }
+
+ mtmp = m_at(x,y);
+ if (mtmp) {
+ /* Don't attack if you're running, and can see it */
+ /* We should never get here if forcefight */
+ if (context.run &&
+ ((!Blind && mon_visible(mtmp) &&
+ ((mtmp->m_ap_type != M_AP_FURNITURE &&
+ mtmp->m_ap_type != M_AP_OBJECT) ||
+ Protection_from_shape_changers)) ||
+ sensemon(mtmp))) {
+ nomul(0);
+ context.move = 0;
+ return;
+ }
+ }
+ }
+
+ u.ux0 = u.ux;
+ u.uy0 = u.uy;
+ bhitpos.x = x;
+ bhitpos.y = y;
+ tmpr = &levl[x][y];
+
+ /* attack monster */
+ if(mtmp) {
+ nomul(0);
+ /* only attack if we know it's there */
+ /* or if we used the 'F' command to fight blindly */
+ /* or if it hides_under, in which case we call attack() to print
+ * the Wait! message.
+ * This is different from ceiling hiders, who aren't handled in
+ * attack().
+ */
+
+ /* If they used a 'm' command, trying to move onto a monster
+ * prints the below message and wastes a turn. The exception is
+ * if the monster is unseen and the player doesn't remember an
+ * invisible monster--then, we fall through to attack() and
+ * attack_check(), which still wastes a turn, but prints a
+ * different message and makes the player remember the monster. */
+ if(context.nopick &&
+ (canspotmon(mtmp) || glyph_is_invisible(levl[x][y].glyph))){
+ if(mtmp->m_ap_type && !Protection_from_shape_changers
+ && !sensemon(mtmp))
+ stumble_onto_mimic(mtmp);
+ else if (mtmp->mpeaceful && !Hallucination)
+ pline("Pardon me, %s.", m_monnam(mtmp));
+ else
+ You("move right into %s.", mon_nam(mtmp));
+ return;
+ }
+ if(context.forcefight || !mtmp->mundetected || sensemon(mtmp) ||
+ ((hides_under(mtmp->data) || mtmp->data->mlet == S_EEL) &&
+ !is_safepet(mtmp))){
+ /* try to attack; note that it might evade */
+ /* also, we don't attack tame when _safepet_ */
+ if(attack(mtmp)) return;
+ }
+ }
+
+ /* specifying 'F' with no monster wastes a turn */
+ if (context.forcefight ||
+ /* remembered an 'I' && didn't use a move command */
+ (glyph_is_invisible(levl[x][y].glyph) && !context.nopick)) {
+ struct obj *boulder = sobj_at(BOULDER, x, y);
+ boolean explo = (Upolyd && attacktype(youmonst.data, AT_EXPL)),
+ solid = !accessible(x, y);
+ int glyph = glyph_at(x, y); /* might be monster */
+ char buf[BUFSZ];
+
+ /* if a statue is displayed at the target location,
+ player is attempting to attack it [and boulder
+ handlng below is suitable for handling that] */
+ if (glyph_is_statue(glyph) ||
+ (Hallucination && glyph_is_monster(glyph)))
+ boulder = sobj_at(STATUE, x, y);
+
+ /* force fight at boulder/statue or wall/door while wielding
+ pick: start digging to break the boulder or wall */
+ if (context.forcefight &&
+ /* can we dig? */
+ uwep && dig_typ(uwep, x, y) &&
+ /* should we dig? */
+ !glyph_is_invisible(glyph) &&
+ !glyph_is_monster(glyph)) {
+ (void)use_pick_axe2(uwep);
+ return;
+ }
+
+ if (boulder)
+ Strcpy(buf, ansimpleoname(boulder));
+ else if (solid)
+ Strcpy(buf, the(defsyms[glyph_to_cmap(glyph)].explanation));
+ else if (!Underwater)
+ Strcpy(buf, "thin air");
+ else if (is_pool(x, y))
+ Strcpy(buf, "empty water");
+ else /* Underwater, targetting non-water */
+ Sprintf(buf, "a vacant spot on the %s", surface(x,y));
+ You("%s%s %s.",
+ !(boulder || solid) ? "" :
+ !explo ? "harmlessly " : "futilely ",
+ explo ? "explode at" : "attack",
+ buf);
+ unmap_object(x, y); /* known empty -- remove 'I' if present */
+ if (boulder) map_object(boulder, TRUE);
+ newsym(x, y);
+ nomul(0);
+ if (explo) {
+ wake_nearby();
+ u.mh = -1; /* dead in the current form */
+ rehumanize();
+ }
+ return;
+ }
+ if (glyph_is_invisible(levl[x][y].glyph)) {
+ unmap_object(x, y);
+ newsym(x, y);
+ }
+ /* not attacking an animal, so we try to move */
+ if ((u.dx || u.dy) && u.usteed && stucksteed(FALSE)) {
+ nomul(0);
+ return;
+ }
+ if(!youmonst.data->mmove) {
+ You("are rooted %s.",
+ Levitation || Is_airlevel(&u.uz) || Is_waterlevel(&u.uz) ?
+ "in place" : "to the ground");
+ nomul(0);
+ return;
+ }
+ if(u.utrap) {
+ if (!trapmove(x, y, trap)) return;
+ }
+
+ if (!test_move(u.ux, u.uy, x-u.ux, y-u.uy, DO_MOVE)) {
+ context.move = 0;
+ nomul(0);
+ return;
+ }
+
+ /* Move ball and chain. */
+ if (Punished)
+ if (!drag_ball(x,y, &bc_control, &ballx, &bally, &chainx, &chainy,
+ &cause_delay, TRUE))
+ return;
+
+ /* Check regions entering/leaving */
+ if (!in_out_region(x,y))
+ return;
+
+ /* now move the hero */
+ mtmp = m_at(x, y);
+ u.ux += u.dx;
+ u.uy += u.dy;
+ /* Move your steed, too */
+ if (u.usteed) {
+ u.usteed->mx = u.ux;
+ u.usteed->my = u.uy;
+ exercise_steed();
+ }
+
+ /*
+ * If safepet at destination then move the pet to the hero's
+ * previous location using the same conditions as in attack().
+ * there are special extenuating circumstances:
+ * (1) if the pet dies then your god angers,
+ * (2) if the pet gets trapped then your god may disapprove,
+ * (3) if the pet was already trapped and you attempt to free it
+ * not only do you encounter the trap but you may frighten your
+ * pet causing it to go wild! moral: don't abuse this privilege.
+ *
+ * Ceiling-hiding pets are skipped by this section of code, to
+ * be caught by the normal falling-monster code.
+ */
+ if (is_safepet(mtmp) && !(is_hider(mtmp->data) && mtmp->mundetected)) {
+ /* if trapped, there's a chance the pet goes wild */
+ if (mtmp->mtrapped) {
+ if (!rn2(mtmp->mtame)) {
+ mtmp->mtame = mtmp->mpeaceful = mtmp->msleeping = 0;
+ if (mtmp->mleashed) m_unleash(mtmp, TRUE);
+ growl(mtmp);
+ } else {
+ yelp(mtmp);
+ }
+ }
+ mtmp->mundetected = 0;
+ if (mtmp->m_ap_type) seemimic(mtmp);
+ else if (!mtmp->mtame) newsym(mtmp->mx, mtmp->my);
+
+ if (mtmp->mtrapped &&
+ (trap = t_at(mtmp->mx, mtmp->my)) != 0 &&
+ (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT) &&
+ sobj_at(BOULDER, trap->tx, trap->ty)) {
+ /* can't swap places with pet pinned in a pit by a boulder */
+ u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
+ } else if (u.ux0 != x && u.uy0 != y && NODIAG(mtmp->data - mons)) {
+ /* can't swap places when pet can't move to your spot */
+ u.ux = u.ux0, u.uy = u.uy0;
+ You("stop. %s can't move diagonally.",
+ upstart(y_monnam(mtmp)));
+ } else if (u.ux0 != x && u.uy0 != y &&
+ bad_rock(mtmp->data, x, u.uy0) &&
+ bad_rock(mtmp->data, u.ux0, y) &&
+ (bigmonst(mtmp->data) || (curr_mon_load(mtmp) > 600))) {
+ /* can't swap places when pet won't fit thru the opening */
+ u.ux = u.ux0, u.uy = u.uy0; /* didn't move after all */
+ You("stop. %s won't fit through.", upstart(y_monnam(mtmp)));
+ } else {
+ char pnambuf[BUFSZ];
+
+ /* save its current description in case of polymorph */
+ Strcpy(pnambuf, y_monnam(mtmp));
+ mtmp->mtrapped = 0;
+ remove_monster(x, y);
+ place_monster(mtmp, u.ux0, u.uy0);
+ newsym(x, y);
+ newsym(u.ux0, u.uy0);
+
+ You("%s %s.", mtmp->mtame ? "swap places with" : "frighten",
+ pnambuf);
+
+ /* check for displacing it into pools and traps */
+ switch (minliquid(mtmp) ? 2 : mintrap(mtmp)) {
+ case 0:
+ break;
+ case 1: /* trapped */
+ case 3: /* changed levels */
+ /* there's already been a trap message, reinforce it */
+ abuse_dog(mtmp);
+ adjalign(-3);
+ break;
+ case 2:
+ /* drowned or died...
+ * you killed your pet by direct action, so get experience
+ * and possibly penalties;
+ * we want the level gain message, if it happens, to occur
+ * before the guilt message below
+ */
+ {
+ /* minliquid() and mintrap() call mondead() rather than
+ killed() so we duplicate some of the latter here */
+ int tmp, mndx;
+
+ u.uconduct.killer++;
+ mndx = monsndx(mtmp->data);
+ tmp = experience(mtmp, (int)mvitals[mndx].died);
+ more_experienced(tmp, 0);
+ newexplevel(); /* will decide if you go up */
+ }
+ /* That's no way to treat a pet! Your god gets angry.
+ *
+ * [This has always been pretty iffy. Why does your
+ * patron deity care at all, let alone enough to get mad?]
+ */
+ if (rn2(4)) {
+ You_feel("guilty about losing your pet like this.");
+ u.ugangr++;
+ adjalign(-15);
+ }
+ break;
+ default:
+ pline("that's strange, unknown mintrap result!");
+ break;
+ }
+ }
+ }
+
+ reset_occupations();
+ if (context.run) {
+ if ( context.run < 8 )
+ if (IS_DOOR(tmpr->typ) || IS_ROCK(tmpr->typ) ||
+ IS_FURNITURE(tmpr->typ))
+ nomul(0);
+ }
+
+ if (hides_under(youmonst.data) || (youmonst.data->mlet == S_EEL) ||
+ u.dx || u.dy)
+ (void) hideunder(&youmonst);
+
+ /*
+ * Mimics (or whatever) become noticeable if they move and are
+ * imitating something that doesn't move. We could extend this
+ * to non-moving monsters...
+ */
+ if ((u.dx || u.dy) && (youmonst.m_ap_type == M_AP_OBJECT
+ || youmonst.m_ap_type == M_AP_FURNITURE))
+ youmonst.m_ap_type = M_AP_NOTHING;
+
+ check_leash(u.ux0,u.uy0);
+
+ if(u.ux0 != u.ux || u.uy0 != u.uy) {
+ u.umoved = TRUE;
+ /* Clean old position -- vision_recalc() will print our new one. */
+ newsym(u.ux0,u.uy0);
+ /* Since the hero has moved, adjust what can be seen/unseen. */
+ vision_recalc(1); /* Do the work now in the recover time. */
+ invocation_message();
+ }
+
+ if (Punished) /* put back ball and chain */
+ move_bc(0,bc_control,ballx,bally,chainx,chainy);
+
+ spoteffects(TRUE);
+
+ /* delay next move because of ball dragging */
+ /* must come after we finished picking up, in spoteffects() */
+ if (cause_delay) {
+ nomul(-2);
+ nomovemsg = "";
+ }
+
+ if (context.run && flags.runmode != RUN_TPORT) {
+ /* display every step or every 7th step depending upon mode */
+ if (flags.runmode != RUN_LEAP || !(moves % 7L)) {
+ if (flags.time) context.botl = 1;
+ curs_on_u();
+ delay_output();
+ if (flags.runmode == RUN_CRAWL) {
+ delay_output();
+ delay_output();
+ delay_output();
+ delay_output();
+ }
+ }
+ }
}
/* combat increases metabolism */
execute if you decline to attack a peaceful monster */
gethungry();
if ((moves % 3L) != 0L && near_capacity() >= HVY_ENCUMBER) {
- int *hp = (!Upolyd ? &u.uhp : &u.mh);
+ int *hp = (!Upolyd ? &u.uhp : &u.mh);
- if (*hp > 1) {
- *hp -= 1;
- } else {
- You("pass out from exertion!");
- exercise(A_CON, FALSE);
- fall_asleep(-10, FALSE);
- }
+ if (*hp > 1) {
+ *hp -= 1;
+ } else {
+ You("pass out from exertion!");
+ exercise(A_CON, FALSE);
+ fall_asleep(-10, FALSE);
+ }
}
return (multi < 0); /* might have fainted (actually gone to sleep) */
}
void
invocation_message()
{
- /* a special clue-msg when on the Invocation position */
- if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
- char buf[BUFSZ];
- struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
-
- nomul(0); /* stop running or travelling */
- if (u.usteed) Sprintf(buf, "beneath %s", y_monnam(u.usteed));
- else if (Levitation || Flying) Strcpy(buf, "beneath you");
- else Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
-
- You_feel("a strange vibration %s.", buf);
- u.uevent.uvibrated = 1;
- if (otmp && otmp->spe == 7 && otmp->lamplit)
- pline("%s %s!", The(xname(otmp)),
- Blind ? "throbs palpably" : "glows with a strange light");
- }
+ /* a special clue-msg when on the Invocation position */
+ if(invocation_pos(u.ux, u.uy) && !On_stairs(u.ux, u.uy)) {
+ char buf[BUFSZ];
+ struct obj *otmp = carrying(CANDELABRUM_OF_INVOCATION);
+
+ nomul(0); /* stop running or travelling */
+ if (u.usteed) Sprintf(buf, "beneath %s", y_monnam(u.usteed));
+ else if (Levitation || Flying) Strcpy(buf, "beneath you");
+ else Sprintf(buf, "under your %s", makeplural(body_part(FOOT)));
+
+ You_feel("a strange vibration %s.", buf);
+ u.uevent.uvibrated = 1;
+ if (otmp && otmp->spe == 7 && otmp->lamplit)
+ pline("%s %s!", The(xname(otmp)),
+ Blind ? "throbs palpably" : "glows with a strange light");
+ }
}
/* moving onto different terrain;
{
struct rm *lev = &levl[u.ux][u.uy];
boolean blocklev = (IS_ROCK(lev->typ) || closed_door(u.ux, u.uy) ||
- (Is_waterlevel(&u.uz) && lev->typ == WATER));
+ (Is_waterlevel(&u.uz) && lev->typ == WATER));
if (blocklev) {
- /* called from spoteffects(), skip float_down() */
- if (Levitation) You_cant("levitate in here.");
- BLevitation |= FROMOUTSIDE;
+ /* called from spoteffects(), skip float_down() */
+ if (Levitation) You_cant("levitate in here.");
+ BLevitation |= FROMOUTSIDE;
} else if (BLevitation) {
- BLevitation &= ~FROMOUTSIDE;
- if (Levitation) float_up();
+ BLevitation &= ~FROMOUTSIDE;
+ if (Levitation) float_up();
}
/* the same terrain that blocks levitation also blocks flight */
if (blocklev) {
- if (Flying) You_cant("fly in here.");
- BFlying |= FROMOUTSIDE;
+ if (Flying) You_cant("fly in here.");
+ BFlying |= FROMOUTSIDE;
} else if (BFlying) {
- BFlying &= ~FROMOUTSIDE;
- float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
- /* [minor bug: we don't know whether this is beginning flight or
- resuming it; that could be tracked so that this message could
- be adjusted to "resume flying", but isn't worth the effort...] */
- if (Flying) You("start flying.");
+ BFlying &= ~FROMOUTSIDE;
+ float_vs_flight(); /* maybe toggle (BFlying & I_SPECIAL) */
+ /* [minor bug: we don't know whether this is beginning flight or
+ resuming it; that could be tracked so that this message could
+ be adjusted to "resume flying", but isn't worth the effort...] */
+ if (Flying) You("start flying.");
}
}
{
/* check for leaving water */
if (u.uinwater) {
- boolean still_inwater = FALSE; /* assume we're getting out */
-
- if (!is_pool(u.ux,u.uy)) {
- if (Is_waterlevel(&u.uz))
- You("pop into an air bubble.");
- else if (is_lava(u.ux, u.uy))
- You("leave the water..."); /* oops! */
- else
- You("are on solid %s again.",
- is_ice(u.ux, u.uy) ? "ice" : "land");
- } else if (Is_waterlevel(&u.uz)) {
- still_inwater = TRUE;
- } else if (Levitation) {
- You("pop out of the water like a cork!");
- } else if (Flying) {
- You("fly out of the water.");
- } else if (Wwalking) {
- You("slowly rise above the surface.");
- } else {
- still_inwater = TRUE;
- }
- if (!still_inwater) {
- boolean was_underwater = (Underwater && !Is_waterlevel(&u.uz));
-
- u.uinwater = 0; /* leave the water */
- if (was_underwater) { /* restore vision */
- docrt();
- vision_full_recalc = 1;
- }
- }
+ boolean still_inwater = FALSE; /* assume we're getting out */
+
+ if (!is_pool(u.ux,u.uy)) {
+ if (Is_waterlevel(&u.uz))
+ You("pop into an air bubble.");
+ else if (is_lava(u.ux, u.uy))
+ You("leave the water..."); /* oops! */
+ else
+ You("are on solid %s again.",
+ is_ice(u.ux, u.uy) ? "ice" : "land");
+ } else if (Is_waterlevel(&u.uz)) {
+ still_inwater = TRUE;
+ } else if (Levitation) {
+ You("pop out of the water like a cork!");
+ } else if (Flying) {
+ You("fly out of the water.");
+ } else if (Wwalking) {
+ You("slowly rise above the surface.");
+ } else {
+ still_inwater = TRUE;
+ }
+ if (!still_inwater) {
+ boolean was_underwater = (Underwater && !Is_waterlevel(&u.uz));
+
+ u.uinwater = 0; /* leave the water */
+ if (was_underwater) { /* restore vision */
+ docrt();
+ vision_full_recalc = 1;
+ }
+ }
}
/* check for entering water or lava */
if (!u.ustuck && !Levitation && !Flying &&
- is_pool_or_lava(u.ux, u.uy)) {
- if (u.usteed && (is_flyer(u.usteed->data) ||
- is_floater(u.usteed->data) || is_clinger(u.usteed->data))) {
- /* floating or clinging steed keeps hero safe (is_flyer() test
- is redundant; it can't be true since Flying yielded false) */
- return FALSE;
- } else if (u.usteed) {
- /* steed enters pool */
- dismount_steed(Underwater ? DISMOUNT_FELL : DISMOUNT_GENERIC);
- /* dismount_steed() -> float_down() -> pickup()
- (float_down doesn't do autopickup on Air or Water) */
- if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) return FALSE;
- /* even if we actually end up at same location, float_down()
- has already done spoteffect()'s trap and pickup actions */
- if (newspot) check_special_room(FALSE); /* spoteffects */
- return TRUE;
- }
- /* not mounted */
-
- /* drown(),lava_effects() return true if hero changes
- location while surviving the problem */
- if (is_lava(u.ux, u.uy)) {
- if (lava_effects()) return TRUE;
- } else if (!Wwalking &&
- (newspot || !u.uinwater || !(Swimming || Amphibious))) {
- if (drown()) return TRUE;
- }
+ is_pool_or_lava(u.ux, u.uy)) {
+ if (u.usteed && (is_flyer(u.usteed->data) ||
+ is_floater(u.usteed->data) || is_clinger(u.usteed->data))) {
+ /* floating or clinging steed keeps hero safe (is_flyer() test
+ is redundant; it can't be true since Flying yielded false) */
+ return FALSE;
+ } else if (u.usteed) {
+ /* steed enters pool */
+ dismount_steed(Underwater ? DISMOUNT_FELL : DISMOUNT_GENERIC);
+ /* dismount_steed() -> float_down() -> pickup()
+ (float_down doesn't do autopickup on Air or Water) */
+ if (Is_airlevel(&u.uz) || Is_waterlevel(&u.uz)) return FALSE;
+ /* even if we actually end up at same location, float_down()
+ has already done spoteffect()'s trap and pickup actions */
+ if (newspot) check_special_room(FALSE); /* spoteffects */
+ return TRUE;
+ }
+ /* not mounted */
+
+ /* drown(),lava_effects() return true if hero changes
+ location while surviving the problem */
+ if (is_lava(u.ux, u.uy)) {
+ if (lava_effects()) return TRUE;
+ } else if (!Wwalking &&
+ (newspot || !u.uinwater || !(Swimming || Amphibious))) {
+ if (drown()) return TRUE;
+ }
}
return FALSE;
}
spoteffects(pick)
boolean pick;
{
- static int inspoteffects = 0;
- static coord spotloc;
- static int spotterrain;
- static struct trap *spottrap = (struct trap *)0;
- static unsigned spottraptyp = NO_TRAP;
- struct trap *trap = t_at(u.ux, u.uy);
- register struct monst *mtmp;
-
- /* prevent recursion from affecting the hero all over again
- [hero poly'd to iron golem enters water here, drown() inflicts
- damage that triggers rehumanize() which calls spoteffects()...] */
- if (inspoteffects && u.ux == spotloc.x && u.uy == spotloc.y &&
- /* except when reason is transformed terrain (ice -> water) */
- spotterrain == levl[u.ux][u.uy].typ &&
- /* or transformed trap (land mine -> pit) */
- (!spottrap || !trap || trap->ttyp == spottraptyp))
- return;
-
- ++inspoteffects;
- spotterrain = levl[u.ux][u.uy].typ;
- spotloc.x = u.ux, spotloc.y = u.uy;
-
- /* moving onto different terrain might cause Levitation to toggle */
- if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0))
- switch_terrain();
-
- if (pooleffects(TRUE)) goto spotdone;
-
- check_special_room(FALSE);
- if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
- dosinkfall();
- if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
- boolean pit;
-
- /* if levitation is due to time out at the end of this
- turn, allowing it to do so could give the perception
- that a trap here is being triggered twice, so adjust
- the timeout to prevent that */
- if (trap && (HLevitation & TIMEOUT) == 1L &&
- !ELevitation && !(HLevitation & ~TIMEOUT)) {
- if (rn2(2)) { /* defer timeout */
- incr_itimeout(&HLevitation, 1L);
- } else { /* timeout early */
- if (float_down(I_SPECIAL|TIMEOUT, 0L)) {
- /* levitation has ended; we've already triggered
- any trap and [usually] performed autopickup */
- trap = 0;
- pick = FALSE;
- }
- }
- }
- /*
- * If not a pit, pickup before triggering trap.
- * If pit, trigger trap before pickup.
- */
- pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
- if (pick && !pit) (void) pickup(1);
-
- if (trap) {
-
- /*
- * dotrap on a fire trap calls melt_ice() which triggers
- * spoteffects() (again) which can trigger the same fire
- * trap (again). Use static spottrap to prevent that.
- * We track spottraptyp because some traps morph
- * (landmine to pit) and any new trap type
- * should get triggered.
- */
- if (!spottrap || spottraptyp != trap->ttyp) {
- spottrap = trap;
- spottraptyp = trap->ttyp;
- dotrap(trap, 0); /* fall into arrow trap, etc. */
- spottrap = (struct trap *)0;
- spottraptyp = NO_TRAP;
- }
- }
- if (pick && pit) (void) pickup(1);
- }
- /* Warning alerts you to ice danger */
- if (Warning && is_ice(u.ux,u.uy)) {
- static const char * const icewarnings[] = {
- "The ice seems very soft and slushy.",
- "You feel the ice shift beneath you!",
- "The ice, is gonna BREAK!", /* The Dead Zone */
- };
- long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
- if (time_left && time_left < 15L)
- pline1(
- (time_left < 5L) ? icewarnings[2] :
- (time_left < 10L) ? icewarnings[1] : icewarnings[0]);
- }
- if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
- mtmp->mundetected = mtmp->msleeping = 0;
- switch(mtmp->data->mlet) {
- case S_PIERCER:
- pline("%s suddenly drops from the %s!",
- Amonnam(mtmp), ceiling(u.ux,u.uy));
- if(mtmp->mtame) /* jumps to greet you, not attack */
- ;
- else if(uarmh && is_metallic(uarmh))
- pline("Its blow glances off your %s.",
- helm_simple_name(uarmh));
- else if (u.uac + 3 <= rnd(20))
- You("are almost hit by %s!",
- x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
- else {
- int dmg;
- You("are hit by %s!",
- x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
- dmg = d(4,6);
- if(Half_physical_damage) dmg = (dmg+1) / 2;
- mdamageu(mtmp, dmg);
- }
- break;
- default: /* monster surprises you. */
- if(mtmp->mtame)
- pline("%s jumps near you from the %s.",
- Amonnam(mtmp), ceiling(u.ux,u.uy));
- else if(mtmp->mpeaceful) {
- You("surprise %s!",
- Blind && !sensemon(mtmp) ?
- something : a_monnam(mtmp));
- mtmp->mpeaceful = 0;
- } else
- pline("%s attacks you by surprise!",
- Amonnam(mtmp));
- break;
- }
- mnexto(mtmp); /* have to move the monster */
- }
+ static int inspoteffects = 0;
+ static coord spotloc;
+ static int spotterrain;
+ static struct trap *spottrap = (struct trap *)0;
+ static unsigned spottraptyp = NO_TRAP;
+ struct trap *trap = t_at(u.ux, u.uy);
+ register struct monst *mtmp;
+
+ /* prevent recursion from affecting the hero all over again
+ [hero poly'd to iron golem enters water here, drown() inflicts
+ damage that triggers rehumanize() which calls spoteffects()...] */
+ if (inspoteffects && u.ux == spotloc.x && u.uy == spotloc.y &&
+ /* except when reason is transformed terrain (ice -> water) */
+ spotterrain == levl[u.ux][u.uy].typ &&
+ /* or transformed trap (land mine -> pit) */
+ (!spottrap || !trap || trap->ttyp == spottraptyp))
+ return;
+
+ ++inspoteffects;
+ spotterrain = levl[u.ux][u.uy].typ;
+ spotloc.x = u.ux, spotloc.y = u.uy;
+
+ /* moving onto different terrain might cause Levitation to toggle */
+ if (spotterrain != levl[u.ux0][u.uy0].typ || !on_level(&u.uz, &u.uz0))
+ switch_terrain();
+
+ if (pooleffects(TRUE)) goto spotdone;
+
+ check_special_room(FALSE);
+ if(IS_SINK(levl[u.ux][u.uy].typ) && Levitation)
+ dosinkfall();
+ if (!in_steed_dismounting) { /* if dismounting, we'll check again later */
+ boolean pit;
+
+ /* if levitation is due to time out at the end of this
+ turn, allowing it to do so could give the perception
+ that a trap here is being triggered twice, so adjust
+ the timeout to prevent that */
+ if (trap && (HLevitation & TIMEOUT) == 1L &&
+ !ELevitation && !(HLevitation & ~TIMEOUT)) {
+ if (rn2(2)) { /* defer timeout */
+ incr_itimeout(&HLevitation, 1L);
+ } else { /* timeout early */
+ if (float_down(I_SPECIAL|TIMEOUT, 0L)) {
+ /* levitation has ended; we've already triggered
+ any trap and [usually] performed autopickup */
+ trap = 0;
+ pick = FALSE;
+ }
+ }
+ }
+ /*
+ * If not a pit, pickup before triggering trap.
+ * If pit, trigger trap before pickup.
+ */
+ pit = (trap && (trap->ttyp == PIT || trap->ttyp == SPIKED_PIT));
+ if (pick && !pit) (void) pickup(1);
+
+ if (trap) {
+
+ /*
+ * dotrap on a fire trap calls melt_ice() which triggers
+ * spoteffects() (again) which can trigger the same fire
+ * trap (again). Use static spottrap to prevent that.
+ * We track spottraptyp because some traps morph
+ * (landmine to pit) and any new trap type
+ * should get triggered.
+ */
+ if (!spottrap || spottraptyp != trap->ttyp) {
+ spottrap = trap;
+ spottraptyp = trap->ttyp;
+ dotrap(trap, 0); /* fall into arrow trap, etc. */
+ spottrap = (struct trap *)0;
+ spottraptyp = NO_TRAP;
+ }
+ }
+ if (pick && pit) (void) pickup(1);
+ }
+ /* Warning alerts you to ice danger */
+ if (Warning && is_ice(u.ux,u.uy)) {
+ static const char * const icewarnings[] = {
+ "The ice seems very soft and slushy.",
+ "You feel the ice shift beneath you!",
+ "The ice, is gonna BREAK!", /* The Dead Zone */
+ };
+ long time_left = spot_time_left(u.ux, u.uy, MELT_ICE_AWAY);
+ if (time_left && time_left < 15L)
+ pline1(
+ (time_left < 5L) ? icewarnings[2] :
+ (time_left < 10L) ? icewarnings[1] : icewarnings[0]);
+ }
+ if((mtmp = m_at(u.ux, u.uy)) && !u.uswallow) {
+ mtmp->mundetected = mtmp->msleeping = 0;
+ switch(mtmp->data->mlet) {
+ case S_PIERCER:
+ pline("%s suddenly drops from the %s!",
+ Amonnam(mtmp), ceiling(u.ux,u.uy));
+ if(mtmp->mtame) /* jumps to greet you, not attack */
+ ;
+ else if(uarmh && is_metallic(uarmh))
+ pline("Its blow glances off your %s.",
+ helm_simple_name(uarmh));
+ else if (u.uac + 3 <= rnd(20))
+ You("are almost hit by %s!",
+ x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
+ else {
+ int dmg;
+ You("are hit by %s!",
+ x_monnam(mtmp, ARTICLE_A, "falling", 0, TRUE));
+ dmg = d(4,6);
+ if(Half_physical_damage) dmg = (dmg+1) / 2;
+ mdamageu(mtmp, dmg);
+ }
+ break;
+ default: /* monster surprises you. */
+ if(mtmp->mtame)
+ pline("%s jumps near you from the %s.",
+ Amonnam(mtmp), ceiling(u.ux,u.uy));
+ else if(mtmp->mpeaceful) {
+ You("surprise %s!",
+ Blind && !sensemon(mtmp) ?
+ something : a_monnam(mtmp));
+ mtmp->mpeaceful = 0;
+ } else
+ pline("%s attacks you by surprise!",
+ Amonnam(mtmp));
+ break;
+ }
+ mnexto(mtmp); /* have to move the monster */
+ }
spotdone:
- if (!--inspoteffects) {
- spotterrain = STONE; /* 0 */
- spotloc.x = spotloc.y = 0;
- }
- return;
+ if (!--inspoteffects) {
+ spotterrain = STONE; /* 0 */
+ spotloc.x = spotloc.y = 0;
+ }
+ return;
}
/* returns first matching monster */
struct permonst *mdat;
int roomno;
{
- register struct monst *mtmp;
-
- for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- if (mtmp->data == mdat &&
- index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
- return mtmp;
- }
- return (struct monst *)0;
+ register struct monst *mtmp;
+
+ for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ if (mtmp->data == mdat &&
+ index(in_rooms(mtmp->mx, mtmp->my, 0), roomno + ROOMOFFSET))
+ return mtmp;
+ }
+ return (struct monst *)0;
}
char *
register xchar x, y;
register int typewanted;
{
- static char buf[5];
- char rno, *ptr = &buf[4];
- int typefound, min_x, min_y, max_x, max_y_offset, step;
- register struct rm *lev;
+ static char buf[5];
+ char rno, *ptr = &buf[4];
+ int typefound, min_x, min_y, max_x, max_y_offset, step;
+ register struct rm *lev;
#define goodtype(rno) (!typewanted || \
- ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \
- ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \
-
- switch (rno = levl[x][y].roomno) {
- case NO_ROOM:
- return(ptr);
- case SHARED:
- step = 2;
- break;
- case SHARED_PLUS:
- step = 1;
- break;
- default: /* i.e. a regular room # */
- if (goodtype(rno))
- *(--ptr) = rno;
- return(ptr);
- }
-
- min_x = x - 1;
- max_x = x + 1;
- if (x < 1)
- min_x += step;
- else
- if (x >= COLNO)
- max_x -= step;
-
- min_y = y - 1;
- max_y_offset = 2;
- if (min_y < 0) {
- min_y += step;
- max_y_offset -= step;
- } else
- if ((min_y + max_y_offset) >= ROWNO)
- max_y_offset -= step;
-
- for (x = min_x; x <= max_x; x += step) {
- lev = &levl[x][min_y];
- y = 0;
- if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
- !index(ptr, rno) && goodtype(rno))
- *(--ptr) = rno;
- y += step;
- if (y > max_y_offset)
- continue;
- if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
- !index(ptr, rno) && goodtype(rno))
- *(--ptr) = rno;
- y += step;
- if (y > max_y_offset)
- continue;
- if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
- !index(ptr, rno) && goodtype(rno))
- *(--ptr) = rno;
- }
- return(ptr);
+ ((typefound = rooms[rno - ROOMOFFSET].rtype) == typewanted) || \
+ ((typewanted == SHOPBASE) && (typefound > SHOPBASE))) \
+
+ switch (rno = levl[x][y].roomno) {
+ case NO_ROOM:
+ return(ptr);
+ case SHARED:
+ step = 2;
+ break;
+ case SHARED_PLUS:
+ step = 1;
+ break;
+ default: /* i.e. a regular room # */
+ if (goodtype(rno))
+ *(--ptr) = rno;
+ return(ptr);
+ }
+
+ min_x = x - 1;
+ max_x = x + 1;
+ if (x < 1)
+ min_x += step;
+ else
+ if (x >= COLNO)
+ max_x -= step;
+
+ min_y = y - 1;
+ max_y_offset = 2;
+ if (min_y < 0) {
+ min_y += step;
+ max_y_offset -= step;
+ } else
+ if ((min_y + max_y_offset) >= ROWNO)
+ max_y_offset -= step;
+
+ for (x = min_x; x <= max_x; x += step) {
+ lev = &levl[x][min_y];
+ y = 0;
+ if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
+ !index(ptr, rno) && goodtype(rno))
+ *(--ptr) = rno;
+ y += step;
+ if (y > max_y_offset)
+ continue;
+ if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
+ !index(ptr, rno) && goodtype(rno))
+ *(--ptr) = rno;
+ y += step;
+ if (y > max_y_offset)
+ continue;
+ if (((rno = lev[y].roomno) >= ROOMOFFSET) &&
+ !index(ptr, rno) && goodtype(rno))
+ *(--ptr) = rno;
+ }
+ return(ptr);
}
/* is (x,y) in a town? */
in_town(x, y)
register int x, y;
{
- s_level *slev = Is_special(&u.uz);
- register struct mkroom *sroom;
- boolean has_subrooms = FALSE;
-
- if (!slev || !slev->flags.town) return FALSE;
-
- /*
- * See if (x,y) is in a room with subrooms, if so, assume it's the
- * town. If there are no subrooms, the whole level is in town.
- */
- for (sroom = &rooms[0]; sroom->hx > 0; sroom++) {
- if (sroom->nsubrooms > 0) {
- has_subrooms = TRUE;
- if (inside_room(sroom, x, y)) return TRUE;
- }
- }
-
- return !has_subrooms;
+ s_level *slev = Is_special(&u.uz);
+ register struct mkroom *sroom;
+ boolean has_subrooms = FALSE;
+
+ if (!slev || !slev->flags.town) return FALSE;
+
+ /*
+ * See if (x,y) is in a room with subrooms, if so, assume it's the
+ * town. If there are no subrooms, the whole level is in town.
+ */
+ for (sroom = &rooms[0]; sroom->hx > 0; sroom++) {
+ if (sroom->nsubrooms > 0) {
+ has_subrooms = TRUE;
+ if (inside_room(sroom, x, y)) return TRUE;
+ }
+ }
+
+ return !has_subrooms;
}
STATIC_OVL void
move_update(newlev)
register boolean newlev;
{
- char *ptr1, *ptr2, *ptr3, *ptr4;
-
- Strcpy(u.urooms0, u.urooms);
- Strcpy(u.ushops0, u.ushops);
- if (newlev) {
- u.urooms[0] = '\0';
- u.uentered[0] = '\0';
- u.ushops[0] = '\0';
- u.ushops_entered[0] = '\0';
- Strcpy(u.ushops_left, u.ushops0);
- return;
- }
- Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
-
- for (ptr1 = &u.urooms[0],
- ptr2 = &u.uentered[0],
- ptr3 = &u.ushops[0],
- ptr4 = &u.ushops_entered[0];
- *ptr1; ptr1++) {
- if (!index(u.urooms0, *ptr1))
- *(ptr2++) = *ptr1;
- if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
- *(ptr3++) = *ptr1;
- if (!index(u.ushops0, *ptr1))
- *(ptr4++) = *ptr1;
- }
- }
- *ptr2 = '\0';
- *ptr3 = '\0';
- *ptr4 = '\0';
-
- /* filter u.ushops0 -> u.ushops_left */
- for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
- if (!index(u.ushops, *ptr1))
- *(ptr2++) = *ptr1;
- *ptr2 = '\0';
+ char *ptr1, *ptr2, *ptr3, *ptr4;
+
+ Strcpy(u.urooms0, u.urooms);
+ Strcpy(u.ushops0, u.ushops);
+ if (newlev) {
+ u.urooms[0] = '\0';
+ u.uentered[0] = '\0';
+ u.ushops[0] = '\0';
+ u.ushops_entered[0] = '\0';
+ Strcpy(u.ushops_left, u.ushops0);
+ return;
+ }
+ Strcpy(u.urooms, in_rooms(u.ux, u.uy, 0));
+
+ for (ptr1 = &u.urooms[0],
+ ptr2 = &u.uentered[0],
+ ptr3 = &u.ushops[0],
+ ptr4 = &u.ushops_entered[0];
+ *ptr1; ptr1++) {
+ if (!index(u.urooms0, *ptr1))
+ *(ptr2++) = *ptr1;
+ if (IS_SHOP(*ptr1 - ROOMOFFSET)) {
+ *(ptr3++) = *ptr1;
+ if (!index(u.ushops0, *ptr1))
+ *(ptr4++) = *ptr1;
+ }
+ }
+ *ptr2 = '\0';
+ *ptr3 = '\0';
+ *ptr4 = '\0';
+
+ /* filter u.ushops0 -> u.ushops_left */
+ for (ptr1 = &u.ushops0[0], ptr2 = &u.ushops_left[0]; *ptr1; ptr1++)
+ if (!index(u.ushops, *ptr1))
+ *(ptr2++) = *ptr1;
+ *ptr2 = '\0';
}
void
check_special_room(newlev)
register boolean newlev;
{
- register struct monst *mtmp;
- char *ptr;
-
- move_update(newlev);
-
- if (*u.ushops0)
- u_left_shop(u.ushops_left, newlev);
-
- if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
- return; /* no entrance messages necessary */
-
- /* Did we just enter a shop? */
- if (*u.ushops_entered)
- u_entered_shop(u.ushops_entered);
-
- for (ptr = &u.uentered[0]; *ptr; ptr++) {
- int roomno = *ptr - ROOMOFFSET,
- rt = rooms[roomno].rtype;
- boolean msg_given = TRUE;
-
- /* Did we just enter some other special room? */
- /* vault.c insists that a vault remain a VAULT,
- * and temples should remain TEMPLEs,
- * but everything else gives a message only the first time */
- switch (rt) {
- case ZOO:
- pline("Welcome to David's treasure zoo!");
- break;
- case SWAMP:
- pline("It %s rather %s down here.",
- Blind ? "feels" : "looks",
- Blind ? "humid" : "muddy");
- break;
- case COURT:
- You("enter an opulent throne room!");
- break;
- case LEPREHALL:
- You("enter a leprechaun hall!");
- break;
- case MORGUE:
- if(midnight()) {
- const char *run = locomotion(youmonst.data, "Run");
- pline("%s away! %s away!", run, run);
- } else
- You("have an uncanny feeling...");
- break;
- case BEEHIVE:
- You("enter a giant beehive!");
- break;
- case COCKNEST:
- You("enter a disgusting nest!");
- break;
- case ANTHOLE:
- You("enter an anthole!");
- break;
- case BARRACKS:
- if(monstinroom(&mons[PM_SOLDIER], roomno) ||
- monstinroom(&mons[PM_SERGEANT], roomno) ||
- monstinroom(&mons[PM_LIEUTENANT], roomno) ||
- monstinroom(&mons[PM_CAPTAIN], roomno))
- You("enter a military barracks!");
- else
- You("enter an abandoned barracks.");
- break;
- case DELPHI:
- {
- struct monst *oracle = monstinroom(&mons[PM_ORACLE],
- roomno);
- if (oracle) {
- if (!oracle->mpeaceful)
- verbalize("You're in Delphi, %s.",
- plname);
- else
- verbalize("%s, %s, welcome to Delphi!",
- Hello((struct monst *) 0), plname);
- } else
- msg_given = FALSE;
- break;
- }
- case TEMPLE:
- intemple(roomno + ROOMOFFSET);
- /*FALLTHRU*/
- default:
- msg_given = (rt == TEMPLE);
- rt = 0;
- break;
- }
- if (msg_given) room_discovered(roomno);
-
- if (rt != 0) {
- rooms[roomno].rtype = OROOM;
- if (!search_special(rt)) {
- /* No more room of that type */
- switch(rt) {
- case COURT:
- level.flags.has_court = 0;
- break;
- case SWAMP:
- level.flags.has_swamp = 0;
- break;
- case MORGUE:
- level.flags.has_morgue = 0;
- break;
- case ZOO:
- level.flags.has_zoo = 0;
- break;
- case BARRACKS:
- level.flags.has_barracks = 0;
- break;
- case TEMPLE:
- level.flags.has_temple = 0;
- break;
- case BEEHIVE:
- level.flags.has_beehive = 0;
- break;
- }
- }
- if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO)
- for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- if (!Stealth && !rn2(3))
- mtmp->msleeping = 0;
- }
- }
- }
-
- return;
+ register struct monst *mtmp;
+ char *ptr;
+
+ move_update(newlev);
+
+ if (*u.ushops0)
+ u_left_shop(u.ushops_left, newlev);
+
+ if (!*u.uentered && !*u.ushops_entered) /* implied by newlev */
+ return; /* no entrance messages necessary */
+
+ /* Did we just enter a shop? */
+ if (*u.ushops_entered)
+ u_entered_shop(u.ushops_entered);
+
+ for (ptr = &u.uentered[0]; *ptr; ptr++) {
+ int roomno = *ptr - ROOMOFFSET,
+ rt = rooms[roomno].rtype;
+ boolean msg_given = TRUE;
+
+ /* Did we just enter some other special room? */
+ /* vault.c insists that a vault remain a VAULT,
+ * and temples should remain TEMPLEs,
+ * but everything else gives a message only the first time */
+ switch (rt) {
+ case ZOO:
+ pline("Welcome to David's treasure zoo!");
+ break;
+ case SWAMP:
+ pline("It %s rather %s down here.",
+ Blind ? "feels" : "looks",
+ Blind ? "humid" : "muddy");
+ break;
+ case COURT:
+ You("enter an opulent throne room!");
+ break;
+ case LEPREHALL:
+ You("enter a leprechaun hall!");
+ break;
+ case MORGUE:
+ if(midnight()) {
+ const char *run = locomotion(youmonst.data, "Run");
+ pline("%s away! %s away!", run, run);
+ } else
+ You("have an uncanny feeling...");
+ break;
+ case BEEHIVE:
+ You("enter a giant beehive!");
+ break;
+ case COCKNEST:
+ You("enter a disgusting nest!");
+ break;
+ case ANTHOLE:
+ You("enter an anthole!");
+ break;
+ case BARRACKS:
+ if(monstinroom(&mons[PM_SOLDIER], roomno) ||
+ monstinroom(&mons[PM_SERGEANT], roomno) ||
+ monstinroom(&mons[PM_LIEUTENANT], roomno) ||
+ monstinroom(&mons[PM_CAPTAIN], roomno))
+ You("enter a military barracks!");
+ else
+ You("enter an abandoned barracks.");
+ break;
+ case DELPHI:
+ {
+ struct monst *oracle = monstinroom(&mons[PM_ORACLE],
+ roomno);
+ if (oracle) {
+ if (!oracle->mpeaceful)
+ verbalize("You're in Delphi, %s.",
+ plname);
+ else
+ verbalize("%s, %s, welcome to Delphi!",
+ Hello((struct monst *) 0), plname);
+ } else
+ msg_given = FALSE;
+ break;
+ }
+ case TEMPLE:
+ intemple(roomno + ROOMOFFSET);
+ /*FALLTHRU*/
+ default:
+ msg_given = (rt == TEMPLE);
+ rt = 0;
+ break;
+ }
+ if (msg_given) room_discovered(roomno);
+
+ if (rt != 0) {
+ rooms[roomno].rtype = OROOM;
+ if (!search_special(rt)) {
+ /* No more room of that type */
+ switch(rt) {
+ case COURT:
+ level.flags.has_court = 0;
+ break;
+ case SWAMP:
+ level.flags.has_swamp = 0;
+ break;
+ case MORGUE:
+ level.flags.has_morgue = 0;
+ break;
+ case ZOO:
+ level.flags.has_zoo = 0;
+ break;
+ case BARRACKS:
+ level.flags.has_barracks = 0;
+ break;
+ case TEMPLE:
+ level.flags.has_temple = 0;
+ break;
+ case BEEHIVE:
+ level.flags.has_beehive = 0;
+ break;
+ }
+ }
+ if (rt == COURT || rt == SWAMP || rt == MORGUE || rt == ZOO)
+ for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ if (!Stealth && !rn2(3))
+ mtmp->msleeping = 0;
+ }
+ }
+ }
+
+ return;
}
int
dopickup()
{
- int count;
- struct trap *traphere = t_at(u.ux, u.uy);
- /* awful kludge to work around parse()'s pre-decrement */
- count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
- multi = 0; /* always reset */
- /* uswallow case added by GAN 01/29/87 */
- if(u.uswallow) {
- if (!u.ustuck->minvent) {
- if (is_animal(u.ustuck->data)) {
- You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
- pline("But it's kind of slimy, so you drop it.");
- } else
- You("don't %s anything in here to pick up.",
- Blind ? "feel" : "see");
- return(1);
- } else {
- int tmpcount = -count;
- return loot_mon(u.ustuck, &tmpcount, (boolean *)0);
- }
- }
- if(is_pool(u.ux, u.uy)) {
- if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
- || (Flying && !Breathless)) {
- You("cannot dive into the water to pick things up.");
- return(0);
- } else if (!Underwater) {
- You_cant("even see the bottom, let alone pick up %s.",
- something);
- return(0);
- }
- }
- if (is_lava(u.ux, u.uy)) {
- if (Wwalking || is_floater(youmonst.data) ||
- is_clinger(youmonst.data) || (Flying && !Breathless)) {
- You_cant("reach the bottom to pick things up.");
- return(0);
- } else if (!likes_lava(youmonst.data)) {
- You("would burn to a crisp trying to pick things up.");
- return(0);
- }
- }
- if (!OBJ_AT(u.ux, u.uy)) {
- There("is nothing here to pick up.");
- return 0;
- }
- if (!can_reach_floor(TRUE)) {
- if (traphere && uteetering_at_seen_pit(traphere))
- You("cannot reach the bottom of the pit.");
- else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
- rider_cant_reach();
- else if (Blind && !can_reach_floor(TRUE))
- You("cannot reach anything here.");
- else
- You("cannot reach the %s.", surface(u.ux,u.uy));
- return 0;
- }
-
- return (pickup(-count));
+ int count;
+ struct trap *traphere = t_at(u.ux, u.uy);
+ /* awful kludge to work around parse()'s pre-decrement */
+ count = (multi || (save_cm && *save_cm == ',')) ? multi + 1 : 0;
+ multi = 0; /* always reset */
+ /* uswallow case added by GAN 01/29/87 */
+ if(u.uswallow) {
+ if (!u.ustuck->minvent) {
+ if (is_animal(u.ustuck->data)) {
+ You("pick up %s tongue.", s_suffix(mon_nam(u.ustuck)));
+ pline("But it's kind of slimy, so you drop it.");
+ } else
+ You("don't %s anything in here to pick up.",
+ Blind ? "feel" : "see");
+ return(1);
+ } else {
+ int tmpcount = -count;
+ return loot_mon(u.ustuck, &tmpcount, (boolean *)0);
+ }
+ }
+ if(is_pool(u.ux, u.uy)) {
+ if (Wwalking || is_floater(youmonst.data) || is_clinger(youmonst.data)
+ || (Flying && !Breathless)) {
+ You("cannot dive into the water to pick things up.");
+ return(0);
+ } else if (!Underwater) {
+ You_cant("even see the bottom, let alone pick up %s.",
+ something);
+ return(0);
+ }
+ }
+ if (is_lava(u.ux, u.uy)) {
+ if (Wwalking || is_floater(youmonst.data) ||
+ is_clinger(youmonst.data) || (Flying && !Breathless)) {
+ You_cant("reach the bottom to pick things up.");
+ return(0);
+ } else if (!likes_lava(youmonst.data)) {
+ You("would burn to a crisp trying to pick things up.");
+ return(0);
+ }
+ }
+ if (!OBJ_AT(u.ux, u.uy)) {
+ There("is nothing here to pick up.");
+ return 0;
+ }
+ if (!can_reach_floor(TRUE)) {
+ if (traphere && uteetering_at_seen_pit(traphere))
+ You("cannot reach the bottom of the pit.");
+ else if (u.usteed && P_SKILL(P_RIDING) < P_BASIC)
+ rider_cant_reach();
+ else if (Blind && !can_reach_floor(TRUE))
+ You("cannot reach anything here.");
+ else
+ You("cannot reach the %s.", surface(u.ux,u.uy));
+ return 0;
+ }
+
+ return (pickup(-count));
}
/* stop running if we see something interesting */
/* Grid bugs stop if trying to move diagonal, even if blind. Maybe */
/* they polymorphed while in the middle of a long move. */
if (u.umonnum == PM_GRID_BUG && u.dx && u.dy) {
- nomul(0);
- return;
+ nomul(0);
+ return;
}
if(Blind || context.run == 0) return;
for(x = u.ux-1; x <= u.ux+1; x++) for(y = u.uy-1; y <= u.uy+1; y++) {
- if(!isok(x,y)) continue;
-
- if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue;
-
- if(x == u.ux && y == u.uy) continue;
-
- if((mtmp = m_at(x,y)) &&
- mtmp->m_ap_type != M_AP_FURNITURE &&
- mtmp->m_ap_type != M_AP_OBJECT &&
- (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
- if((context.run != 1 && !mtmp->mtame)
- || (x == u.ux+u.dx && y == u.uy+u.dy))
- goto stop;
- }
-
- if (levl[x][y].typ == STONE) continue;
- if (x == u.ux-u.dx && y == u.uy-u.dy) continue;
-
- if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) ||
- IS_AIR(levl[x][y].typ))
- continue;
- else if (closed_door(x,y) ||
- (mtmp && mtmp->m_ap_type == M_AP_FURNITURE &&
- (mtmp->mappearance == S_hcdoor ||
- mtmp->mappearance == S_vcdoor))) {
- if(x != u.ux && y != u.uy) continue;
- if(context.run != 1) goto stop;
- goto bcorr;
- } else if (levl[x][y].typ == CORR) {
+ if(!isok(x,y)) continue;
+
+ if(u.umonnum == PM_GRID_BUG && x != u.ux && y != u.uy) continue;
+
+ if(x == u.ux && y == u.uy) continue;
+
+ if((mtmp = m_at(x,y)) &&
+ mtmp->m_ap_type != M_AP_FURNITURE &&
+ mtmp->m_ap_type != M_AP_OBJECT &&
+ (!mtmp->minvis || See_invisible) && !mtmp->mundetected) {
+ if((context.run != 1 && !mtmp->mtame)
+ || (x == u.ux+u.dx && y == u.uy+u.dy))
+ goto stop;
+ }
+
+ if (levl[x][y].typ == STONE) continue;
+ if (x == u.ux-u.dx && y == u.uy-u.dy) continue;
+
+ if (IS_ROCK(levl[x][y].typ) || (levl[x][y].typ == ROOM) ||
+ IS_AIR(levl[x][y].typ))
+ continue;
+ else if (closed_door(x,y) ||
+ (mtmp && mtmp->m_ap_type == M_AP_FURNITURE &&
+ (mtmp->mappearance == S_hcdoor ||
+ mtmp->mappearance == S_vcdoor))) {
+ if(x != u.ux && y != u.uy) continue;
+ if(context.run != 1) goto stop;
+ goto bcorr;
+ } else if (levl[x][y].typ == CORR) {
bcorr:
- if(levl[u.ux][u.uy].typ != ROOM) {
- if(context.run == 1 || context.run == 3 || context.run == 8) {
- i = dist2(x,y,u.ux+u.dx,u.uy+u.dy);
- if(i > 2) continue;
- if(corrct == 1 && dist2(x,y,x0,y0) != 1)
- noturn = 1;
- if(i < i0) {
- i0 = i;
- x0 = x;
- y0 = y;
- m0 = mtmp ? 1 : 0;
- }
- }
- corrct++;
- }
- continue;
- } else if ((trap = t_at(x,y)) && trap->tseen) {
- if(context.run == 1) goto bcorr; /* if you must */
- if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
- continue;
- } else if (is_pool_or_lava(x,y)) {
- /* water and lava only stop you if directly in front, and stop
- * you even if you are running
- */
- if(!Levitation && !Flying && !is_clinger(youmonst.data) &&
- x == u.ux+u.dx && y == u.uy+u.dy)
- /* No Wwalking check; otherwise they'd be able
- * to test boots by trying to SHIFT-direction
- * into a pool and seeing if the game allowed it
- */
- goto stop;
- continue;
- } else { /* e.g. objects or trap or stairs */
- if(context.run == 1) goto bcorr;
- if(context.run == 8) continue;
- if(mtmp) continue; /* d */
- if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) ||
- ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
- continue;
- }
+ if(levl[u.ux][u.uy].typ != ROOM) {
+ if(context.run == 1 || context.run == 3 || context.run == 8) {
+ i = dist2(x,y,u.ux+u.dx,u.uy+u.dy);
+ if(i > 2) continue;
+ if(corrct == 1 && dist2(x,y,x0,y0) != 1)
+ noturn = 1;
+ if(i < i0) {
+ i0 = i;
+ x0 = x;
+ y0 = y;
+ m0 = mtmp ? 1 : 0;
+ }
+ }
+ corrct++;
+ }
+ continue;
+ } else if ((trap = t_at(x,y)) && trap->tseen) {
+ if(context.run == 1) goto bcorr; /* if you must */
+ if(x == u.ux+u.dx && y == u.uy+u.dy) goto stop;
+ continue;
+ } else if (is_pool_or_lava(x,y)) {
+ /* water and lava only stop you if directly in front, and stop
+ * you even if you are running
+ */
+ if(!Levitation && !Flying && !is_clinger(youmonst.data) &&
+ x == u.ux+u.dx && y == u.uy+u.dy)
+ /* No Wwalking check; otherwise they'd be able
+ * to test boots by trying to SHIFT-direction
+ * into a pool and seeing if the game allowed it
+ */
+ goto stop;
+ continue;
+ } else { /* e.g. objects or trap or stairs */
+ if(context.run == 1) goto bcorr;
+ if(context.run == 8) continue;
+ if(mtmp) continue; /* d */
+ if(((x == u.ux - u.dx) && (y != u.uy + u.dy)) ||
+ ((y == u.uy - u.dy) && (x != u.ux + u.dx)))
+ continue;
+ }
stop:
- nomul(0);
- return;
+ nomul(0);
+ return;
} /* end for loops */
if(corrct > 1 && context.run == 2) goto stop;
if((context.run == 1 || context.run == 3 || context.run == 8) &&
- !noturn && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1)))
+ !noturn && !m0 && i0 && (corrct == 1 || (corrct == 2 && i0 == 1)))
{
- /* make sure that we do not turn too far */
- if(i0 == 2) {
- if(u.dx == y0-u.uy && u.dy == u.ux-x0)
- i = 2; /* straight turn right */
- else
- i = -2; /* straight turn left */
- } else if(u.dx && u.dy) {
- if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
- i = -1; /* half turn left */
- else
- i = 1; /* half turn right */
- } else {
- if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy))
- i = 1; /* half turn right */
- else
- i = -1; /* half turn left */
- }
-
- i += u.last_str_turn;
- if(i <= 2 && i >= -2) {
- u.last_str_turn = i;
- u.dx = x0-u.ux;
- u.dy = y0-u.uy;
- }
+ /* make sure that we do not turn too far */
+ if(i0 == 2) {
+ if(u.dx == y0-u.uy && u.dy == u.ux-x0)
+ i = 2; /* straight turn right */
+ else
+ i = -2; /* straight turn left */
+ } else if(u.dx && u.dy) {
+ if((u.dx == u.dy && y0 == u.uy) || (u.dx != u.dy && y0 != u.uy))
+ i = -1; /* half turn left */
+ else
+ i = 1; /* half turn right */
+ } else {
+ if((x0-u.ux == y0-u.uy && !u.dy) || (x0-u.ux != y0-u.uy && u.dy))
+ i = 1; /* half turn right */
+ else
+ i = -1; /* half turn left */
+ }
+
+ i += u.last_str_turn;
+ if(i <= 2 && i >= -2) {
+ u.last_str_turn = i;
+ u.dx = x0-u.ux;
+ u.dy = y0-u.uy;
+ }
}
}
if (Passes_walls) return TRUE; /* or a xorn... */
/* pool could be next to a door, conceivably even inside a shop */
if (IS_DOOR(levl[x][y].typ) && (!doorless_door(x, y) || block_door(x, y)))
- return FALSE;
+ return FALSE;
/* finally, are we trying to squeeze through a too-narrow gap? */
return !(bad_rock(youmonst.data, u.ux, y) &&
- bad_rock(youmonst.data, x, u.uy));
+ bad_rock(youmonst.data, x, u.uy));
}
/* something like lookaround, but we are not running */
int
monster_nearby()
{
- register int x,y;
- register struct monst *mtmp;
-
- /* Also see the similar check in dochugw() in monmove.c */
- for(x = u.ux-1; x <= u.ux+1; x++)
- for(y = u.uy-1; y <= u.uy+1; y++) {
- if(!isok(x,y)) continue;
- if(x == u.ux && y == u.uy) continue;
- if((mtmp = m_at(x,y)) &&
- mtmp->m_ap_type != M_AP_FURNITURE &&
- mtmp->m_ap_type != M_AP_OBJECT &&
- (!mtmp->mpeaceful || Hallucination) &&
- (!is_hider(mtmp->data) || !mtmp->mundetected) &&
- !noattacks(mtmp->data) &&
- mtmp->mcanmove && !mtmp->msleeping && /* aplvax!jcn */
- !onscary(u.ux, u.uy, mtmp) &&
- canspotmon(mtmp))
- return(1);
- }
- return(0);
+ register int x,y;
+ register struct monst *mtmp;
+
+ /* Also see the similar check in dochugw() in monmove.c */
+ for(x = u.ux-1; x <= u.ux+1; x++)
+ for(y = u.uy-1; y <= u.uy+1; y++) {
+ if(!isok(x,y)) continue;
+ if(x == u.ux && y == u.uy) continue;
+ if((mtmp = m_at(x,y)) &&
+ mtmp->m_ap_type != M_AP_FURNITURE &&
+ mtmp->m_ap_type != M_AP_OBJECT &&
+ (!mtmp->mpeaceful || Hallucination) &&
+ (!is_hider(mtmp->data) || !mtmp->mundetected) &&
+ !noattacks(mtmp->data) &&
+ mtmp->mcanmove && !mtmp->msleeping && /* aplvax!jcn */
+ !onscary(u.ux, u.uy, mtmp) &&
+ canspotmon(mtmp))
+ return(1);
+ }
+ return(0);
}
void
nomul(nval)
- register int nval;
+ register int nval;
{
- if(multi < nval) return; /* This is a bug fix by ab@unido */
- u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
- u.usleep = 0;
- multi = nval;
- context.travel = context.travel1 = context.mv = context.run = 0;
+ if(multi < nval) return; /* This is a bug fix by ab@unido */
+ u.uinvulnerable = FALSE; /* Kludge to avoid ctrl-C bug -dlc */
+ u.usleep = 0;
+ multi = nval;
+ context.travel = context.travel1 = context.mv = context.run = 0;
}
/* called when a non-movement, multi-turn action has completed */
unmul(msg_override)
const char *msg_override;
{
- multi = 0; /* caller will usually have done this already */
- if (msg_override) nomovemsg = msg_override;
- else if (!nomovemsg) nomovemsg = You_can_move_again;
- if (*nomovemsg) pline1(nomovemsg);
- nomovemsg = 0;
- u.usleep = 0;
- if (afternmv) (*afternmv)();
- afternmv = 0;
+ multi = 0; /* caller will usually have done this already */
+ if (msg_override) nomovemsg = msg_override;
+ else if (!nomovemsg) nomovemsg = You_can_move_again;
+ if (*nomovemsg) pline1(nomovemsg);
+ nomovemsg = 0;
+ u.usleep = 0;
+ if (afternmv) (*afternmv)();
+ afternmv = 0;
}
STATIC_OVL void
maybe_wail()
{
static short powers[] = { TELEPORT, SEE_INVIS, POISON_RES, COLD_RES,
- SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES,
- TELEPORT_CONTROL, STEALTH, FAST, INVIS };
+ SHOCK_RES, FIRE_RES, SLEEP_RES, DISINT_RES,
+ TELEPORT_CONTROL, STEALTH, FAST, INVIS };
if (moves <= wailmsg + 50) return;
wailmsg = moves;
if (Role_if(PM_WIZARD) || Race_if(PM_ELF) || Role_if(PM_VALKYRIE)) {
- const char *who;
- int i, powercnt;
-
- who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ?
- urole.name.m : "Elf";
- if (u.uhp == 1) {
- pline("%s is about to die.", who);
- } else {
- for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
- if (u.uprops[powers[i]].intrinsic & INTRINSIC) ++powercnt;
-
- pline(powercnt >= 4 ? "%s, all your powers will be lost..."
- : "%s, your life force is running out.", who);
- }
+ const char *who;
+ int i, powercnt;
+
+ who = (Role_if(PM_WIZARD) || Role_if(PM_VALKYRIE)) ?
+ urole.name.m : "Elf";
+ if (u.uhp == 1) {
+ pline("%s is about to die.", who);
} else {
- You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
- : "the howling of the CwnAnnwn...");
+ for (i = 0, powercnt = 0; i < SIZE(powers); ++i)
+ if (u.uprops[powers[i]].intrinsic & INTRINSIC) ++powercnt;
+
+ pline(powercnt >= 4 ? "%s, all your powers will be lost..."
+ : "%s, your life force is running out.", who);
+ }
+ } else {
+ You_hear(u.uhp == 1 ? "the wailing of the Banshee..."
+ : "the howling of the CwnAnnwn...");
}
}
register const char *knam;
boolean k_format;
{
- if (Upolyd) {
- u.mh -= n;
- if (u.mhmax < u.mh) u.mhmax = u.mh;
- context.botl = 1;
- if (u.mh < 1)
- rehumanize();
- else if (n > 0 && u.mh*10 < u.mhmax && Unchanging)
- maybe_wail();
- return;
- }
-
- u.uhp -= n;
- if(u.uhp > u.uhpmax)
- u.uhpmax = u.uhp; /* perhaps n was negative */
- context.botl = 1;
- if(u.uhp < 1) {
- killer.format = k_format;
- if (killer.name != knam) /* the thing that killed you */
- Strcpy(killer.name, knam ? knam : "");
- You("die...");
- done(DIED);
- } else if (n > 0 && u.uhp*10 < u.uhpmax) {
- maybe_wail();
- }
+ if (Upolyd) {
+ u.mh -= n;
+ if (u.mhmax < u.mh) u.mhmax = u.mh;
+ context.botl = 1;
+ if (u.mh < 1)
+ rehumanize();
+ else if (n > 0 && u.mh*10 < u.mhmax && Unchanging)
+ maybe_wail();
+ return;
+ }
+
+ u.uhp -= n;
+ if(u.uhp > u.uhpmax)
+ u.uhpmax = u.uhp; /* perhaps n was negative */
+ context.botl = 1;
+ if(u.uhp < 1) {
+ killer.format = k_format;
+ if (killer.name != knam) /* the thing that killed you */
+ Strcpy(killer.name, knam ? knam : "");
+ You("die...");
+ done(DIED);
+ } else if (n > 0 && u.uhp*10 < u.uhpmax) {
+ maybe_wail();
+ }
}
int
weight_cap()
{
- register long carrcap;
-
- carrcap = 25*(ACURRSTR + ACURR(A_CON)) + 50;
- if (Upolyd) {
- /* consistent with can_carry() in mon.c */
- if (youmonst.data->mlet == S_NYMPH)
- carrcap = MAX_CARR_CAP;
- else if (!youmonst.data->cwt)
- carrcap = (carrcap * (long)youmonst.data->msize) / MZ_HUMAN;
- else if (!strongmonst(youmonst.data)
- || (strongmonst(youmonst.data) && (youmonst.data->cwt > WT_HUMAN)))
- carrcap = (carrcap * (long)youmonst.data->cwt / WT_HUMAN);
- }
-
- if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
- || (u.usteed && strongmonst(u.usteed->data))
- )
- carrcap = MAX_CARR_CAP;
- else {
- if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
- if (!Flying) {
- if(EWounded_legs & LEFT_SIDE) carrcap -= 100;
- if(EWounded_legs & RIGHT_SIDE) carrcap -= 100;
- }
- if (carrcap < 0) carrcap = 0;
- }
- return((int) carrcap);
+ register long carrcap;
+
+ carrcap = 25*(ACURRSTR + ACURR(A_CON)) + 50;
+ if (Upolyd) {
+ /* consistent with can_carry() in mon.c */
+ if (youmonst.data->mlet == S_NYMPH)
+ carrcap = MAX_CARR_CAP;
+ else if (!youmonst.data->cwt)
+ carrcap = (carrcap * (long)youmonst.data->msize) / MZ_HUMAN;
+ else if (!strongmonst(youmonst.data)
+ || (strongmonst(youmonst.data) && (youmonst.data->cwt > WT_HUMAN)))
+ carrcap = (carrcap * (long)youmonst.data->cwt / WT_HUMAN);
+ }
+
+ if (Levitation || Is_airlevel(&u.uz) /* pugh@cornell */
+ || (u.usteed && strongmonst(u.usteed->data))
+ )
+ carrcap = MAX_CARR_CAP;
+ else {
+ if(carrcap > MAX_CARR_CAP) carrcap = MAX_CARR_CAP;
+ if (!Flying) {
+ if(EWounded_legs & LEFT_SIDE) carrcap -= 100;
+ if(EWounded_legs & RIGHT_SIDE) carrcap -= 100;
+ }
+ if (carrcap < 0) carrcap = 0;
+ }
+ return((int) carrcap);
}
static int wc; /* current weight_cap(); valid after call to inv_weight() */
int
inv_weight()
{
- register struct obj *otmp = invent;
- register int wt = 0;
-
- while (otmp) {
- if (otmp->oclass == COIN_CLASS)
- wt += (int)(((long)otmp->quan + 50L) / 100L);
- else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
- wt += otmp->owt;
- otmp = otmp->nobj;
- }
- wc = weight_cap();
- return (wt - wc);
+ register struct obj *otmp = invent;
+ register int wt = 0;
+
+ while (otmp) {
+ if (otmp->oclass == COIN_CLASS)
+ wt += (int)(((long)otmp->quan + 50L) / 100L);
+ else if (otmp->otyp != BOULDER || !throws_rocks(youmonst.data))
+ wt += otmp->owt;
+ otmp = otmp->nobj;
+ }
+ wc = weight_cap();
+ return (wt - wc);
}
/*
const char *str;
{
if(near_capacity() >= EXT_ENCUMBER) {
- if(str)
- pline1(str);
- else
- You_cant("do that while carrying so much stuff.");
- return 1;
+ if(str)
+ pline1(str);
+ else
+ You_cant("do that while carrying so much stuff.");
+ return 1;
}
return 0;
}
inv_cnt(incl_gold)
boolean incl_gold;
{
- register struct obj *otmp = invent;
- register int ct = 0;
-
- while(otmp){
- if (incl_gold || otmp->invlet != GOLD_SYM) ct++;
- otmp = otmp->nobj;
- }
- return(ct);
+ register struct obj *otmp = invent;
+ register int ct = 0;
+
+ while(otmp){
+ if (incl_gold || otmp->invlet != GOLD_SYM) ct++;
+ otmp = otmp->nobj;
+ }
+ return(ct);
}
/* Counts the money in an object chain. */
struct obj *otmp;
{
while (otmp) {
- /* Must change when silver & copper is implemented: */
- if (otmp->oclass == COIN_CLASS) return otmp->quan;
- otmp = otmp->nobj;
+ /* Must change when silver & copper is implemented: */
+ if (otmp->oclass == COIN_CLASS) return otmp->quan;
+ otmp = otmp->nobj;
}
return 0L;
}
assigninvlet(otmp)
register struct obj *otmp;
{
- boolean inuse[52];
- register int i;
- register struct obj *obj;
-
- /* there should be at most one of these in inventory... */
- if (otmp->oclass == COIN_CLASS) {
- otmp->invlet = GOLD_SYM;
- return;
- }
-
- for(i = 0; i < 52; i++) inuse[i] = FALSE;
- for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
- i = obj->invlet;
- if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
- if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
- if(i == otmp->invlet) otmp->invlet = 0;
- }
- if((i = otmp->invlet) &&
- (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
- return;
- for(i = lastinvnr+1; i != lastinvnr; i++) {
- if(i == 52) { i = -1; continue; }
- if(!inuse[i]) break;
- }
- otmp->invlet = (inuse[i] ? NOINVSYM :
- (i < 26) ? ('a'+i) : ('A'+i-26));
- lastinvnr = i;
+ boolean inuse[52];
+ register int i;
+ register struct obj *obj;
+
+ /* there should be at most one of these in inventory... */
+ if (otmp->oclass == COIN_CLASS) {
+ otmp->invlet = GOLD_SYM;
+ return;
+ }
+
+ for(i = 0; i < 52; i++) inuse[i] = FALSE;
+ for(obj = invent; obj; obj = obj->nobj) if(obj != otmp) {
+ i = obj->invlet;
+ if('a' <= i && i <= 'z') inuse[i - 'a'] = TRUE; else
+ if('A' <= i && i <= 'Z') inuse[i - 'A' + 26] = TRUE;
+ if(i == otmp->invlet) otmp->invlet = 0;
+ }
+ if((i = otmp->invlet) &&
+ (('a' <= i && i <= 'z') || ('A' <= i && i <= 'Z')))
+ return;
+ for(i = lastinvnr+1; i != lastinvnr; i++) {
+ if(i == 52) { i = -1; continue; }
+ if(!inuse[i]) break;
+ }
+ otmp->invlet = (inuse[i] ? NOINVSYM :
+ (i < 26) ? ('a'+i) : ('A'+i-26));
+ lastinvnr = i;
}
/* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */
STATIC_OVL void
reorder_invent()
{
- struct obj *otmp, *prev, *next;
- boolean need_more_sorting;
-
- do {
- /*
- * We expect at most one item to be out of order, so this
- * isn't nearly as inefficient as it may first appear.
- */
- need_more_sorting = FALSE;
- for (otmp = invent, prev = 0; otmp; ) {
- next = otmp->nobj;
- if (next && inv_rank(next) < inv_rank(otmp)) {
- need_more_sorting = TRUE;
- if (prev) prev->nobj = next;
- else invent = next;
- otmp->nobj = next->nobj;
- next->nobj = otmp;
- prev = next;
- } else {
- prev = otmp;
- otmp = next;
- }
- }
- } while (need_more_sorting);
+ struct obj *otmp, *prev, *next;
+ boolean need_more_sorting;
+
+ do {
+ /*
+ * We expect at most one item to be out of order, so this
+ * isn't nearly as inefficient as it may first appear.
+ */
+ need_more_sorting = FALSE;
+ for (otmp = invent, prev = 0; otmp; ) {
+ next = otmp->nobj;
+ if (next && inv_rank(next) < inv_rank(otmp)) {
+ need_more_sorting = TRUE;
+ if (prev) prev->nobj = next;
+ else invent = next;
+ otmp->nobj = next->nobj;
+ next->nobj = otmp;
+ prev = next;
+ } else {
+ prev = otmp;
+ otmp = next;
+ }
+ }
+ } while (need_more_sorting);
}
#undef inv_rank
merge_choice(objlist, obj)
struct obj *objlist, *obj;
{
- struct monst *shkp;
- int save_nocharge;
-
- if (obj->otyp == SCR_SCARE_MONSTER) /* punt on these */
- return (struct obj *)0;
- /* if this is an item on the shop floor, the attributes it will
- have when carried are different from what they are now; prevent
- that from eliciting an incorrect result from mergable() */
- save_nocharge = obj->no_charge;
- if (objlist == invent && obj->where == OBJ_FLOOR &&
- (shkp = shop_keeper(inside_shop(obj->ox, obj->oy))) != 0) {
- if (obj->no_charge) obj->no_charge = 0;
- /* A billable object won't have its `unpaid' bit set, so would
- erroneously seem to be a candidate to merge with a similar
- ordinary object. That's no good, because once it's really
- picked up, it won't merge after all. It might merge with
- another unpaid object, but we can't check that here (depends
- too much upon shk's bill) and if it doesn't merge it would
- end up in the '#' overflow inventory slot, so reject it now. */
- else if (inhishop(shkp)) return (struct obj *)0;
- }
- while (objlist) {
- if (mergable(objlist, obj)) break;
- objlist = objlist->nobj;
- }
- obj->no_charge = save_nocharge;
- return objlist;
+ struct monst *shkp;
+ int save_nocharge;
+
+ if (obj->otyp == SCR_SCARE_MONSTER) /* punt on these */
+ return (struct obj *)0;
+ /* if this is an item on the shop floor, the attributes it will
+ have when carried are different from what they are now; prevent
+ that from eliciting an incorrect result from mergable() */
+ save_nocharge = obj->no_charge;
+ if (objlist == invent && obj->where == OBJ_FLOOR &&
+ (shkp = shop_keeper(inside_shop(obj->ox, obj->oy))) != 0) {
+ if (obj->no_charge) obj->no_charge = 0;
+ /* A billable object won't have its `unpaid' bit set, so would
+ erroneously seem to be a candidate to merge with a similar
+ ordinary object. That's no good, because once it's really
+ picked up, it won't merge after all. It might merge with
+ another unpaid object, but we can't check that here (depends
+ too much upon shk's bill) and if it doesn't merge it would
+ end up in the '#' overflow inventory slot, so reject it now. */
+ else if (inhishop(shkp)) return (struct obj *)0;
+ }
+ while (objlist) {
+ if (mergable(objlist, obj)) break;
+ objlist = objlist->nobj;
+ }
+ obj->no_charge = save_nocharge;
+ return objlist;
}
/* merge obj with otmp and delete obj if types agree */
merged(potmp, pobj)
struct obj **potmp, **pobj;
{
- register struct obj *otmp = *potmp, *obj = *pobj;
-
- if(mergable(otmp, obj)) {
- /* Approximate age: we do it this way because if we were to
- * do it "accurately" (merge only when ages are identical)
- * we'd wind up never merging any corpses.
- * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
- *
- * Don't do the age manipulation if lit. We would need
- * to stop the burn on both items, then merge the age,
- * then restart the burn.
- */
- if (!obj->lamplit)
- otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan))
- / (otmp->quan + obj->quan);
-
- otmp->quan += obj->quan;
+ register struct obj *otmp = *potmp, *obj = *pobj;
+
+ if(mergable(otmp, obj)) {
+ /* Approximate age: we do it this way because if we were to
+ * do it "accurately" (merge only when ages are identical)
+ * we'd wind up never merging any corpses.
+ * otmp->age = otmp->age*(1-proportion) + obj->age*proportion;
+ *
+ * Don't do the age manipulation if lit. We would need
+ * to stop the burn on both items, then merge the age,
+ * then restart the burn.
+ */
+ if (!obj->lamplit)
+ otmp->age = ((otmp->age*otmp->quan) + (obj->age*obj->quan))
+ / (otmp->quan + obj->quan);
+
+ otmp->quan += obj->quan;
/* temporary special case for gold objects!!!! */
- if (otmp->oclass == COIN_CLASS) otmp->owt = weight(otmp);
- else otmp->owt += obj->owt;
- if(!has_oname(otmp) && has_oname(obj))
- otmp = *potmp = oname(otmp, ONAME(obj));
- obj_extract_self(obj);
-
- /* really should merge the timeouts */
- if (obj->lamplit) obj_merge_light_sources(obj, otmp);
- if (obj->timed) obj_stop_timers(obj); /* follows lights */
-
- /* fixup for `#adjust' merging wielded darts, daggers, &c */
- if (obj->owornmask && carried(otmp)) {
- long wmask = otmp->owornmask | obj->owornmask;
-
- /* Both the items might be worn in competing slots;
- merger preference (regardless of which is which):
- primary weapon + alternate weapon -> primary weapon;
- primary weapon + quiver -> primary weapon;
- alternate weapon + quiver -> alternate weapon.
- (Prior to 3.3.0, it was not possible for the two
- stacks to be worn in different slots and `obj'
- didn't need to be unworn when merging.) */
- if (wmask & W_WEP) wmask = W_WEP;
- else if (wmask & W_SWAPWEP) wmask = W_SWAPWEP;
- else if (wmask & W_QUIVER) wmask = W_QUIVER;
- else {
- impossible("merging strangely worn items (%lx)", wmask);
- wmask = otmp->owornmask;
- }
- if ((otmp->owornmask & ~wmask) != 0L) setnotworn(otmp);
- setworn(otmp, wmask);
- setnotworn(obj);
- }
+ if (otmp->oclass == COIN_CLASS) otmp->owt = weight(otmp);
+ else otmp->owt += obj->owt;
+ if(!has_oname(otmp) && has_oname(obj))
+ otmp = *potmp = oname(otmp, ONAME(obj));
+ obj_extract_self(obj);
+
+ /* really should merge the timeouts */
+ if (obj->lamplit) obj_merge_light_sources(obj, otmp);
+ if (obj->timed) obj_stop_timers(obj); /* follows lights */
+
+ /* fixup for `#adjust' merging wielded darts, daggers, &c */
+ if (obj->owornmask && carried(otmp)) {
+ long wmask = otmp->owornmask | obj->owornmask;
+
+ /* Both the items might be worn in competing slots;
+ merger preference (regardless of which is which):
+ primary weapon + alternate weapon -> primary weapon;
+ primary weapon + quiver -> primary weapon;
+ alternate weapon + quiver -> alternate weapon.
+ (Prior to 3.3.0, it was not possible for the two
+ stacks to be worn in different slots and `obj'
+ didn't need to be unworn when merging.) */
+ if (wmask & W_WEP) wmask = W_WEP;
+ else if (wmask & W_SWAPWEP) wmask = W_SWAPWEP;
+ else if (wmask & W_QUIVER) wmask = W_QUIVER;
+ else {
+ impossible("merging strangely worn items (%lx)", wmask);
+ wmask = otmp->owornmask;
+ }
+ if ((otmp->owornmask & ~wmask) != 0L) setnotworn(otmp);
+ setworn(otmp, wmask);
+ setnotworn(obj);
+ }
#if 0
- /* (this should not be necessary, since items
- already in a monster's inventory don't ever get
- merged into other objects [only vice versa]) */
- else if (obj->owornmask && mcarried(otmp)) {
- if (obj == MON_WEP(otmp->ocarry)) {
- MON_WEP(otmp->ocarry) = otmp;
- otmp->owornmask = W_WEP;
- }
- }
+ /* (this should not be necessary, since items
+ already in a monster's inventory don't ever get
+ merged into other objects [only vice versa]) */
+ else if (obj->owornmask && mcarried(otmp)) {
+ if (obj == MON_WEP(otmp->ocarry)) {
+ MON_WEP(otmp->ocarry) = otmp;
+ otmp->owornmask = W_WEP;
+ }
+ }
#endif /*0*/
- obfree(obj,otmp); /* free(obj), bill->otmp */
- return(1);
- }
- return 0;
+ obfree(obj,otmp); /* free(obj), bill->otmp */
+ return(1);
+ }
+ return 0;
}
/*
addinv_core1(obj)
struct obj *obj;
{
- if (obj->oclass == COIN_CLASS) {
- context.botl = 1;
- } else if (obj->otyp == AMULET_OF_YENDOR) {
- if (u.uhave.amulet) impossible("already have amulet?");
- u.uhave.amulet = 1;
- } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
- if (u.uhave.menorah) impossible("already have candelabrum?");
- u.uhave.menorah = 1;
- } else if (obj->otyp == BELL_OF_OPENING) {
- if (u.uhave.bell) impossible("already have silver bell?");
- u.uhave.bell = 1;
- } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
- if (u.uhave.book) impossible("already have the book?");
- u.uhave.book = 1;
- } else if (obj->oartifact) {
- if (is_quest_artifact(obj)) {
- if (u.uhave.questart)
- impossible("already have quest artifact?");
- u.uhave.questart = 1;
- artitouch(obj);
- }
- set_artifact_intrinsic(obj, 1, W_ART);
- }
+ if (obj->oclass == COIN_CLASS) {
+ context.botl = 1;
+ } else if (obj->otyp == AMULET_OF_YENDOR) {
+ if (u.uhave.amulet) impossible("already have amulet?");
+ u.uhave.amulet = 1;
+ } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
+ if (u.uhave.menorah) impossible("already have candelabrum?");
+ u.uhave.menorah = 1;
+ } else if (obj->otyp == BELL_OF_OPENING) {
+ if (u.uhave.bell) impossible("already have silver bell?");
+ u.uhave.bell = 1;
+ } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
+ if (u.uhave.book) impossible("already have the book?");
+ u.uhave.book = 1;
+ } else if (obj->oartifact) {
+ if (is_quest_artifact(obj)) {
+ if (u.uhave.questart)
+ impossible("already have quest artifact?");
+ u.uhave.questart = 1;
+ artitouch(obj);
+ }
+ set_artifact_intrinsic(obj, 1, W_ART);
+ }
}
/*
addinv_core2(obj)
struct obj *obj;
{
- if (confers_luck(obj)) {
- /* new luckstone must be in inventory by this point
- * for correct calculation */
- set_moreluck();
- }
+ if (confers_luck(obj)) {
+ /* new luckstone must be in inventory by this point
+ * for correct calculation */
+ set_moreluck();
+ }
}
/*
addinv(obj)
struct obj *obj;
{
- struct obj *otmp, *prev;
-
- if (obj->where != OBJ_FREE)
- panic("addinv: obj not free");
- /* normally addtobill() clears no_charge when items in a shop are
- picked up, but won't do so if the shop has become untended */
- obj->no_charge = 0; /* should not be set in hero's invent */
- if (Has_contents(obj)) picked_container(obj); /* clear no_charge */
- obj->was_thrown = 0; /* not meaningful for invent */
-
- addinv_core1(obj);
-
- /* merge with quiver in preference to any other inventory slot
- in case quiver and wielded weapon are both eligible; adding
- extra to quivered stack is more useful than to wielded one */
- if (uquiver && merged(&uquiver, &obj)) {
- obj = uquiver;
- goto added;
- }
- /* merge if possible; find end of chain in the process */
- for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
- if (merged(&otmp, &obj)) {
- obj = otmp;
- goto added;
- }
- /* didn't merge, so insert into chain */
- if (flags.invlet_constant || !prev) {
- if (flags.invlet_constant) assigninvlet(obj);
- obj->nobj = invent; /* insert at beginning */
- invent = obj;
- if (flags.invlet_constant) reorder_invent();
- } else {
- prev->nobj = obj; /* insert at end */
- obj->nobj = 0;
- }
- obj->where = OBJ_INVENT;
+ struct obj *otmp, *prev;
+
+ if (obj->where != OBJ_FREE)
+ panic("addinv: obj not free");
+ /* normally addtobill() clears no_charge when items in a shop are
+ picked up, but won't do so if the shop has become untended */
+ obj->no_charge = 0; /* should not be set in hero's invent */
+ if (Has_contents(obj)) picked_container(obj); /* clear no_charge */
+ obj->was_thrown = 0; /* not meaningful for invent */
+
+ addinv_core1(obj);
+
+ /* we want globby things to become one big glob whereever possible
+ so we need to trigger this before merged() is called */
+ if (obj->globby && merge_choice(invent, obj)) {
+ for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj) {
+ if (otmp->otyp == obj->otyp) {
+ pline("The %s coalesce.", makeplural(obj_typename(obj->otyp)));
+ obj = obj_meld(&otmp, &obj);
+ goto added;
+ }
+ }
+ }
+
+ /* merge with quiver in preference to any other inventory slot
+ in case quiver and wielded weapon are both eligible; adding
+ extra to quivered stack is more useful than to wielded one */
+ if (uquiver && merged(&uquiver, &obj)) {
+ obj = uquiver;
+ goto added;
+ }
+ /* merge if possible; find end of chain in the process */
+ for (prev = 0, otmp = invent; otmp; prev = otmp, otmp = otmp->nobj)
+ if (merged(&otmp, &obj)) {
+ obj = otmp;
+ goto added;
+ }
+ /* didn't merge, so insert into chain */
+ if (flags.invlet_constant || !prev) {
+ if (flags.invlet_constant) assigninvlet(obj);
+ obj->nobj = invent; /* insert at beginning */
+ invent = obj;
+ if (flags.invlet_constant) reorder_invent();
+ } else {
+ prev->nobj = obj; /* insert at end */
+ obj->nobj = 0;
+ }
+ obj->where = OBJ_INVENT;
added:
- addinv_core2(obj);
- carry_obj_effects(obj); /* carrying affects the obj */
- update_inventory();
- return(obj);
+ addinv_core2(obj);
+ carry_obj_effects(obj); /* carrying affects the obj */
+ update_inventory();
+ return(obj);
}
/*
carry_obj_effects(obj)
struct obj *obj;
{
- /* Cursed figurines can spontaneously transform
- when carried. */
- if (obj->otyp == FIGURINE) {
- if (obj->cursed
- && obj->corpsenm != NON_PM
- && !dead_species(obj->corpsenm,TRUE)) {
- attach_fig_transform_timeout(obj);
- }
- }
+ /* Cursed figurines can spontaneously transform
+ when carried. */
+ if (obj->otyp == FIGURINE) {
+ if (obj->cursed
+ && obj->corpsenm != NON_PM
+ && !dead_species(obj->corpsenm,TRUE)) {
+ attach_fig_transform_timeout(obj);
+ }
+ }
}
/* Add an item to the inventory unless we're fumbling or it refuses to be
struct obj *obj;
const char *drop_fmt, *drop_arg, *hold_msg;
{
- char buf[BUFSZ];
-
- if (!Blind) obj->dknown = 1; /* maximize mergibility */
- if (obj->oartifact) {
- /* place_object may change these */
- boolean crysknife = (obj->otyp == CRYSKNIFE);
- int oerode = obj->oerodeproof;
- boolean wasUpolyd = Upolyd;
-
- /* in case touching this object turns out to be fatal */
- place_object(obj, u.ux, u.uy);
-
- if (!touch_artifact(obj, &youmonst)) {
- obj_extract_self(obj); /* remove it from the floor */
- dropy(obj); /* now put it back again :-) */
- return obj;
- } else if (wasUpolyd && !Upolyd) {
- /* loose your grip if you revert your form */
- if (drop_fmt) pline(drop_fmt, drop_arg);
- obj_extract_self(obj);
- dropy(obj);
- return obj;
- }
- obj_extract_self(obj);
- if (crysknife) {
- obj->otyp = CRYSKNIFE;
- obj->oerodeproof = oerode;
- }
- }
- if (Fumbling) {
- if (drop_fmt) pline(drop_fmt, drop_arg);
- dropy(obj);
- } else {
- long oquan = obj->quan;
- int prev_encumbr = near_capacity(); /* before addinv() */
-
- /* encumbrance only matters if it would now become worse
- than max( current_value, stressed ) */
- if (prev_encumbr < MOD_ENCUMBER) prev_encumbr = MOD_ENCUMBER;
- /* addinv() may redraw the entire inventory, overwriting
- drop_arg when it comes from something like doname() */
- if (drop_arg) drop_arg = strcpy(buf, drop_arg);
-
- obj = addinv(obj);
- if (inv_cnt(FALSE) > 52
- || ((obj->otyp != LOADSTONE || !obj->cursed)
- && near_capacity() > prev_encumbr)) {
- if (drop_fmt) pline(drop_fmt, drop_arg);
- /* undo any merge which took place */
- if (obj->quan > oquan) obj = splitobj(obj, oquan);
- dropx(obj);
- } else {
- if (flags.autoquiver && !uquiver && !obj->owornmask &&
- (is_missile(obj) ||
- ammo_and_launcher(obj, uwep) ||
- ammo_and_launcher(obj, uswapwep)))
- setuqwep(obj);
- if (hold_msg || drop_fmt) prinv(hold_msg, obj, oquan);
- }
- }
- return obj;
+ char buf[BUFSZ];
+
+ if (!Blind) obj->dknown = 1; /* maximize mergibility */
+ if (obj->oartifact) {
+ /* place_object may change these */
+ boolean crysknife = (obj->otyp == CRYSKNIFE);
+ int oerode = obj->oerodeproof;
+ boolean wasUpolyd = Upolyd;
+
+ /* in case touching this object turns out to be fatal */
+ place_object(obj, u.ux, u.uy);
+
+ if (!touch_artifact(obj, &youmonst)) {
+ obj_extract_self(obj); /* remove it from the floor */
+ dropy(obj); /* now put it back again :-) */
+ return obj;
+ } else if (wasUpolyd && !Upolyd) {
+ /* loose your grip if you revert your form */
+ if (drop_fmt) pline(drop_fmt, drop_arg);
+ obj_extract_self(obj);
+ dropy(obj);
+ return obj;
+ }
+ obj_extract_self(obj);
+ if (crysknife) {
+ obj->otyp = CRYSKNIFE;
+ obj->oerodeproof = oerode;
+ }
+ }
+ if (Fumbling) {
+ if (drop_fmt) pline(drop_fmt, drop_arg);
+ dropy(obj);
+ } else {
+ long oquan = obj->quan;
+ int prev_encumbr = near_capacity(); /* before addinv() */
+
+ /* encumbrance only matters if it would now become worse
+ than max( current_value, stressed ) */
+ if (prev_encumbr < MOD_ENCUMBER) prev_encumbr = MOD_ENCUMBER;
+ /* addinv() may redraw the entire inventory, overwriting
+ drop_arg when it comes from something like doname() */
+ if (drop_arg) drop_arg = strcpy(buf, drop_arg);
+
+ obj = addinv(obj);
+ if (inv_cnt(FALSE) > 52
+ || ((obj->otyp != LOADSTONE || !obj->cursed)
+ && near_capacity() > prev_encumbr)) {
+ if (drop_fmt) pline(drop_fmt, drop_arg);
+ /* undo any merge which took place */
+ if (obj->quan > oquan) obj = splitobj(obj, oquan);
+ dropx(obj);
+ } else {
+ if (flags.autoquiver && !uquiver && !obj->owornmask &&
+ (is_missile(obj) ||
+ ammo_and_launcher(obj, uwep) ||
+ ammo_and_launcher(obj, uswapwep)))
+ setuqwep(obj);
+ if (hold_msg || drop_fmt) prinv(hold_msg, obj, oquan);
+ }
+ }
+ return obj;
}
/* useup() all of an item regardless of its quantity */
useupall(obj)
struct obj *obj;
{
- setnotworn(obj);
- freeinv(obj);
- obfree(obj, (struct obj *)0); /* deletes contents also */
+ setnotworn(obj);
+ freeinv(obj);
+ obfree(obj, (struct obj *)0); /* deletes contents also */
}
void
useup(obj)
register struct obj *obj;
{
- /* Note: This works correctly for containers because they */
- /* (containers) don't merge. */
- if (obj->quan > 1L) {
- obj->in_use = FALSE; /* no longer in use */
- obj->quan--;
- obj->owt = weight(obj);
- update_inventory();
- } else {
- useupall(obj);
- }
+ /* Note: This works correctly for containers because they */
+ /* (containers) don't merge. */
+ if (obj->quan > 1L) {
+ obj->in_use = FALSE; /* no longer in use */
+ obj->quan--;
+ obj->owt = weight(obj);
+ update_inventory();
+ } else {
+ useupall(obj);
+ }
}
/* use one charge from an item and possibly incur shop debt for it */
struct obj *obj;
boolean maybe_unpaid; /* false if caller handles shop billing */
{
- if (maybe_unpaid) check_unpaid(obj);
- obj->spe -= 1;
- if (obj->known) update_inventory();
+ if (maybe_unpaid) check_unpaid(obj);
+ obj->spe -= 1;
+ if (obj->known) update_inventory();
}
/*
freeinv_core(obj)
struct obj *obj;
{
- if (obj->oclass == COIN_CLASS) {
- context.botl = 1;
- return;
- } else if (obj->otyp == AMULET_OF_YENDOR) {
- if (!u.uhave.amulet) impossible("don't have amulet?");
- u.uhave.amulet = 0;
- } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
- if (!u.uhave.menorah) impossible("don't have candelabrum?");
- u.uhave.menorah = 0;
- } else if (obj->otyp == BELL_OF_OPENING) {
- if (!u.uhave.bell) impossible("don't have silver bell?");
- u.uhave.bell = 0;
- } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
- if (!u.uhave.book) impossible("don't have the book?");
- u.uhave.book = 0;
- } else if (obj->oartifact) {
- if (is_quest_artifact(obj)) {
- if (!u.uhave.questart)
- impossible("don't have quest artifact?");
- u.uhave.questart = 0;
- }
- set_artifact_intrinsic(obj, 0, W_ART);
- }
-
- if (obj->otyp == LOADSTONE) {
- curse(obj);
- } else if (confers_luck(obj)) {
- set_moreluck();
- context.botl = 1;
- } else if (obj->otyp == FIGURINE && obj->timed) {
- (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj));
- }
+ if (obj->oclass == COIN_CLASS) {
+ context.botl = 1;
+ return;
+ } else if (obj->otyp == AMULET_OF_YENDOR) {
+ if (!u.uhave.amulet) impossible("don't have amulet?");
+ u.uhave.amulet = 0;
+ } else if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
+ if (!u.uhave.menorah) impossible("don't have candelabrum?");
+ u.uhave.menorah = 0;
+ } else if (obj->otyp == BELL_OF_OPENING) {
+ if (!u.uhave.bell) impossible("don't have silver bell?");
+ u.uhave.bell = 0;
+ } else if (obj->otyp == SPE_BOOK_OF_THE_DEAD) {
+ if (!u.uhave.book) impossible("don't have the book?");
+ u.uhave.book = 0;
+ } else if (obj->oartifact) {
+ if (is_quest_artifact(obj)) {
+ if (!u.uhave.questart)
+ impossible("don't have quest artifact?");
+ u.uhave.questart = 0;
+ }
+ set_artifact_intrinsic(obj, 0, W_ART);
+ }
+
+ if (obj->otyp == LOADSTONE) {
+ curse(obj);
+ } else if (confers_luck(obj)) {
+ set_moreluck();
+ context.botl = 1;
+ } else if (obj->otyp == FIGURINE && obj->timed) {
+ (void) stop_timer(FIG_TRANSFORM, obj_to_any(obj));
+ }
}
/* remove an object from the hero's inventory */
freeinv(obj)
register struct obj *obj;
{
- extract_nobj(obj, &invent);
- freeinv_core(obj);
- update_inventory();
+ extract_nobj(obj, &invent);
+ freeinv_core(obj);
+ update_inventory();
}
void
delallobj(x, y)
int x, y;
{
- struct obj *otmp, *otmp2;
+ struct obj *otmp, *otmp2;
- for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
- if (otmp == uball)
- unpunish();
- /* after unpunish(), or might get deallocated chain */
- otmp2 = otmp->nexthere;
- if (otmp == uchain)
- continue;
- delobj(otmp);
- }
+ for (otmp = level.objects[x][y]; otmp; otmp = otmp2) {
+ if (otmp == uball)
+ unpunish();
+ /* after unpunish(), or might get deallocated chain */
+ otmp2 = otmp->nexthere;
+ if (otmp == uchain)
+ continue;
+ delobj(otmp);
+ }
}
/* destroy object in fobj chain (if unpaid, it remains on the bill) */
delobj(obj)
register struct obj *obj;
{
- boolean update_map;
-
- if (obj->otyp == AMULET_OF_YENDOR ||
- obj->otyp == CANDELABRUM_OF_INVOCATION ||
- obj->otyp == BELL_OF_OPENING ||
- obj->otyp == SPE_BOOK_OF_THE_DEAD) {
- /* player might be doing something stupid, but we
- * can't guarantee that. assume special artifacts
- * are indestructible via drawbridges, and exploding
- * chests, and golem creation, and ...
- */
- return;
- }
- update_map = (obj->where == OBJ_FLOOR);
- obj_extract_self(obj);
- if (update_map) newsym(obj->ox, obj->oy);
- obfree(obj, (struct obj *) 0); /* frees contents also */
+ boolean update_map;
+
+ if (obj->otyp == AMULET_OF_YENDOR ||
+ obj->otyp == CANDELABRUM_OF_INVOCATION ||
+ obj->otyp == BELL_OF_OPENING ||
+ obj->otyp == SPE_BOOK_OF_THE_DEAD) {
+ /* player might be doing something stupid, but we
+ * can't guarantee that. assume special artifacts
+ * are indestructible via drawbridges, and exploding
+ * chests, and golem creation, and ...
+ */
+ return;
+ }
+ update_map = (obj->where == OBJ_FLOOR);
+ obj_extract_self(obj);
+ if (update_map) newsym(obj->ox, obj->oy);
+ obfree(obj, (struct obj *) 0); /* frees contents also */
}
/* try to find a particular type of object at designated map location */
int otyp;
int x, y;
{
- register struct obj *otmp;
+ register struct obj *otmp;
- for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
- if (otmp->otyp == otyp) break;
+ for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
+ if (otmp->otyp == otyp) break;
- return otmp;
+ return otmp;
}
/* sobj_at(&c) traversal -- find next object of specified type */
int type;
boolean by_nexthere;
{
- register struct obj *otmp;
+ register struct obj *otmp;
- otmp = obj; /* start with the object after this one */
- do {
- otmp = !by_nexthere ? otmp->nobj : otmp->nexthere;
- if (!otmp) break;
- } while (otmp->otyp != type);
+ otmp = obj; /* start with the object after this one */
+ do {
+ otmp = !by_nexthere ? otmp->nobj : otmp->nexthere;
+ if (!otmp) break;
+ } while (otmp->otyp != type);
- return otmp;
+ return otmp;
}
struct obj *
carrying(type)
register int type;
{
- register struct obj *otmp;
+ register struct obj *otmp;
- for(otmp = invent; otmp; otmp = otmp->nobj)
- if(otmp->otyp == type)
- return(otmp);
- return((struct obj *) 0);
+ for(otmp = invent; otmp; otmp = otmp->nobj)
+ if(otmp->otyp == type)
+ return(otmp);
+ return((struct obj *) 0);
}
const char *
currency(amount)
long amount;
{
- if (amount == 1L) return "zorkmid";
- else return "zorkmids";
+ if (amount == 1L) return "zorkmid";
+ else return "zorkmids";
}
boolean
have_lizard()
{
- register struct obj *otmp;
+ register struct obj *otmp;
- for(otmp = invent; otmp; otmp = otmp->nobj)
- if(otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
- return(TRUE);
- return(FALSE);
+ for(otmp = invent; otmp; otmp = otmp->nobj)
+ if(otmp->otyp == CORPSE && otmp->corpsenm == PM_LIZARD)
+ return(TRUE);
+ return(FALSE);
}
struct obj *
unsigned int id;
register struct obj *objchn;
{
- struct obj *temp;
+ struct obj *temp;
- while(objchn) {
- if(objchn->o_id == id) return(objchn);
- if (Has_contents(objchn) && (temp = o_on(id,objchn->cobj)))
- return temp;
- objchn = objchn->nobj;
- }
- return((struct obj *) 0);
+ while(objchn) {
+ if(objchn->o_id == id) return(objchn);
+ if (Has_contents(objchn) && (temp = o_on(id,objchn->cobj)))
+ return temp;
+ objchn = objchn->nobj;
+ }
+ return((struct obj *) 0);
}
boolean
register struct obj *obj;
int x, y;
{
- register struct obj *otmp;
+ register struct obj *otmp;
- for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
- if(obj == otmp) return(TRUE);
- return(FALSE);
+ for(otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere)
+ if(obj == otmp) return(TRUE);
+ return(FALSE);
}
struct obj *
g_at(x,y)
register int x, y;
{
- register struct obj *obj = level.objects[x][y];
- while(obj) {
- if (obj->oclass == COIN_CLASS) return obj;
- obj = obj->nexthere;
- }
- return((struct obj *)0);
+ register struct obj *obj = level.objects[x][y];
+ while(obj) {
+ if (obj->oclass == COIN_CLASS) return obj;
+ obj = obj->nexthere;
+ }
+ return((struct obj *)0);
}
STATIC_OVL void
register char *buf;
/* compact a string of inventory letters by dashing runs of letters */
{
- register int i1 = 1, i2 = 1;
- register char ilet, ilet1, ilet2;
-
- ilet2 = buf[0];
- ilet1 = buf[1];
- buf[++i2] = buf[++i1];
- ilet = buf[i1];
- while(ilet) {
- if(ilet == ilet1+1) {
- if(ilet1 == ilet2+1)
- buf[i2 - 1] = ilet1 = '-';
- else if(ilet2 == '-') {
- buf[i2 - 1] = ++ilet1;
- buf[i2] = buf[++i1];
- ilet = buf[i1];
- continue;
- }
- } else if (ilet == NOINVSYM) {
- /* compact three or more consecutive '#'
- characters into "#-#" */
- if (i2 >= 2 && buf[i2 - 2] == NOINVSYM &&
- buf[i2 - 1] == NOINVSYM)
- buf[i2 - 1] = '-';
- else if (i2 >= 3 && buf[i2 - 3] == NOINVSYM &&
- buf[i2 - 2] == '-' && buf[i2 - 1] == NOINVSYM)
- --i2;
- }
- ilet2 = ilet1;
- ilet1 = ilet;
- buf[++i2] = buf[++i1];
- ilet = buf[i1];
- }
+ register int i1 = 1, i2 = 1;
+ register char ilet, ilet1, ilet2;
+
+ ilet2 = buf[0];
+ ilet1 = buf[1];
+ buf[++i2] = buf[++i1];
+ ilet = buf[i1];
+ while(ilet) {
+ if(ilet == ilet1+1) {
+ if(ilet1 == ilet2+1)
+ buf[i2 - 1] = ilet1 = '-';
+ else if(ilet2 == '-') {
+ buf[i2 - 1] = ++ilet1;
+ buf[i2] = buf[++i1];
+ ilet = buf[i1];
+ continue;
+ }
+ } else if (ilet == NOINVSYM) {
+ /* compact three or more consecutive '#'
+ characters into "#-#" */
+ if (i2 >= 2 && buf[i2 - 2] == NOINVSYM &&
+ buf[i2 - 1] == NOINVSYM)
+ buf[i2 - 1] = '-';
+ else if (i2 >= 3 && buf[i2 - 3] == NOINVSYM &&
+ buf[i2 - 2] == '-' && buf[i2 - 1] == NOINVSYM)
+ --i2;
+ }
+ ilet2 = ilet1;
+ ilet1 = ilet;
+ buf[++i2] = buf[++i1];
+ ilet = buf[i1];
+ }
}
/* some objects shouldn't be split when count given to getobj or askchain */
struct obj *obj;
{
return !((obj->otyp == LOADSTONE && obj->cursed) ||
- (obj == uwep && welded(uwep)));
+ (obj == uwep && welded(uwep)));
}
/* match the prompt for either 'T' or 'R' command */
getobj(let,word)
register const char *let,*word;
{
- register struct obj *otmp;
- register char ilet;
- char buf[BUFSZ], qbuf[QBUFSZ];
- char lets[BUFSZ], altlets[BUFSZ], *ap;
- register int foo = 0;
- register char *bp = buf;
- xchar allowcnt = 0; /* 0, 1 or 2 */
- struct obj *firstobj = invent;
- boolean usegold = FALSE; /* can't use gold because its illegal */
- boolean allowall = FALSE;
- boolean allownone = FALSE;
- boolean useboulder = FALSE;
- xchar foox = 0;
- long cnt, prevcnt;
- boolean prezero;
- long dummymask;
-
- if(*let == ALLOW_COUNT) let++, allowcnt = 1;
- if(*let == COIN_CLASS) let++, usegold = TRUE;
-
- /* Equivalent of an "ugly check" for gold */
- if (usegold && !strcmp(word, "eat") &&
- (!metallivorous(youmonst.data)
- || youmonst.data == &mons[PM_RUST_MONSTER]))
- usegold = FALSE;
-
- if(*let == ALL_CLASSES) let++, allowall = TRUE;
- if(*let == ALLOW_NONE) let++, allownone = TRUE;
- /* "ugly check" for reading fortune cookies, part 1 */
- /* The normal 'ugly check' keeps the object on the inventory list.
- * We don't want to do that for shirts/cookies, so the check for
- * them is handled a bit differently (and also requires that we set
- * allowall in the caller)
- */
- if(allowall && !strcmp(word, "read")) allowall = FALSE;
-
- /* another ugly check: show boulders (not statues) */
- if(*let == WEAPON_CLASS &&
- !strcmp(word, "throw") && throws_rocks(youmonst.data))
- useboulder = TRUE;
-
- if(allownone) *bp++ = '-';
- if(bp > buf && bp[-1] == '-') *bp++ = ' ';
- ap = altlets;
-
- if (!flags.invlet_constant) reassign();
-
- for (otmp = firstobj; otmp; otmp = otmp->nobj) {
- if (&bp[foo] == &buf[sizeof buf - 1] ||
- ap == &altlets[sizeof altlets - 1]) {
- /* we must have a huge number of NOINVSYM items somehow */
- impossible("getobj: inventory overflow");
- break;
- }
-
- if (!*let || index(let, otmp->oclass)
- || (usegold && otmp->invlet == GOLD_SYM)
- || (useboulder && otmp->otyp == BOULDER)
- ) {
- register int otyp = otmp->otyp;
- bp[foo++] = otmp->invlet;
-
- /* ugly check: remove inappropriate things */
- if ((taking_off(word) &&
- !(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
- || (putting_on(word) &&
- (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
- /* already worn */
+ register struct obj *otmp;
+ register char ilet;
+ char buf[BUFSZ], qbuf[QBUFSZ];
+ char lets[BUFSZ], altlets[BUFSZ], *ap;
+ register int foo = 0;
+ register char *bp = buf;
+ xchar allowcnt = 0; /* 0, 1 or 2 */
+ struct obj *firstobj = invent;
+ boolean usegold = FALSE; /* can't use gold because its illegal */
+ boolean allowall = FALSE;
+ boolean allownone = FALSE;
+ boolean useboulder = FALSE;
+ xchar foox = 0;
+ long cnt, prevcnt;
+ boolean prezero;
+ long dummymask;
+
+ if(*let == ALLOW_COUNT) let++, allowcnt = 1;
+ if(*let == COIN_CLASS) let++, usegold = TRUE;
+
+ /* Equivalent of an "ugly check" for gold */
+ if (usegold && !strcmp(word, "eat") &&
+ (!metallivorous(youmonst.data)
+ || youmonst.data == &mons[PM_RUST_MONSTER]))
+ usegold = FALSE;
+
+ if(*let == ALL_CLASSES) let++, allowall = TRUE;
+ if(*let == ALLOW_NONE) let++, allownone = TRUE;
+ /* "ugly check" for reading fortune cookies, part 1 */
+ /* The normal 'ugly check' keeps the object on the inventory list.
+ * We don't want to do that for shirts/cookies, so the check for
+ * them is handled a bit differently (and also requires that we set
+ * allowall in the caller)
+ */
+ if(allowall && !strcmp(word, "read")) allowall = FALSE;
+
+ /* another ugly check: show boulders (not statues) */
+ if(*let == WEAPON_CLASS &&
+ !strcmp(word, "throw") && throws_rocks(youmonst.data))
+ useboulder = TRUE;
+
+ if(allownone) *bp++ = '-';
+ if(bp > buf && bp[-1] == '-') *bp++ = ' ';
+ ap = altlets;
+
+ if (!flags.invlet_constant) reassign();
+
+ for (otmp = firstobj; otmp; otmp = otmp->nobj) {
+ if (&bp[foo] == &buf[sizeof buf - 1] ||
+ ap == &altlets[sizeof altlets - 1]) {
+ /* we must have a huge number of NOINVSYM items somehow */
+ impossible("getobj: inventory overflow");
+ break;
+ }
+
+ if (!*let || index(let, otmp->oclass)
+ || (usegold && otmp->invlet == GOLD_SYM)
+ || (useboulder && otmp->otyp == BOULDER)
+ ) {
+ register int otyp = otmp->otyp;
+ bp[foo++] = otmp->invlet;
+
+ /* ugly check: remove inappropriate things */
+ if ((taking_off(word) &&
+ !(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
+ || (putting_on(word) &&
+ (otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL)))
+ /* already worn */
#if 0 /* 3.4.1 -- include currently wielded weapon among the choices */
- || (!strcmp(word, "wield") &&
- (otmp->owornmask & W_WEP))
+ || (!strcmp(word, "wield") &&
+ (otmp->owornmask & W_WEP))
#endif
- || (!strcmp(word, "ready") &&
- (otmp == uwep || (otmp == uswapwep && u.twoweap)))
- || ((!strcmp(word, "dip") || !strcmp(word, "grease")) &&
- inaccessible_equipment(otmp, (const char *)0 , FALSE))
- ) {
- foo--;
- foox++;
- }
-
- /* Second ugly check; unlike the first it won't trigger an
- * "else" in "you don't have anything else to ___".
- */
- else if ((putting_on(word) &&
- ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING) ||
- (otmp->oclass == TOOL_CLASS &&
- otyp != BLINDFOLD && otyp != TOWEL && otyp != LENSES)))
- || (!strcmp(word, "wield") &&
- (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
- || (!strcmp(word, "eat") && !is_edible(otmp))
- || (!strcmp(word, "sacrifice") &&
- (otyp != CORPSE &&
- otyp != AMULET_OF_YENDOR && otyp != FAKE_AMULET_OF_YENDOR))
- || (!strcmp(word, "write with") &&
- (otmp->oclass == TOOL_CLASS &&
- otyp != MAGIC_MARKER && otyp != TOWEL))
- || (!strcmp(word, "tin") &&
- (otyp != CORPSE || !tinnable(otmp)))
- || (!strcmp(word, "rub") &&
- ((otmp->oclass == TOOL_CLASS &&
- otyp != OIL_LAMP && otyp != MAGIC_LAMP &&
- otyp != BRASS_LANTERN) ||
- (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
- || ((!strcmp(word, "use or apply") ||
- !strcmp(word, "untrap with")) &&
- /* Picks, axes, pole-weapons, bullwhips */
- ((otmp->oclass == WEAPON_CLASS && !is_pick(otmp) &&
- !is_axe(otmp) && !is_pole(otmp) && otyp != BULLWHIP) ||
- (otmp->oclass == POTION_CLASS &&
- /* only applicable potion is oil, and it will only
- be offered as a choice when already discovered */
- (otyp != POT_OIL || !otmp->dknown ||
- !objects[POT_OIL].oc_name_known)) ||
- (otmp->oclass == FOOD_CLASS &&
- otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF) ||
- (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
- || (!strcmp(word, "invoke") &&
- (!otmp->oartifact && !objects[otyp].oc_unique &&
- (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) &&
- otyp != CRYSTAL_BALL && /* #invoke synonym for apply */
- /* note: presenting the possibility of invoking non-artifact
- mirrors and/or lamps is a simply a cruel deception... */
- otyp != MIRROR && otyp != MAGIC_LAMP &&
- (otyp != OIL_LAMP || /* don't list known oil lamp */
- (otmp->dknown && objects[OIL_LAMP].oc_name_known))))
- || (!strcmp(word, "untrap with") &&
- (otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE))
- || (!strcmp(word, "tip") && !Is_container(otmp) &&
- /* include horn of plenty if sufficiently discovered */
- (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown ||
- !objects[HORN_OF_PLENTY].oc_name_known))
- || (!strcmp(word, "charge") && !is_chargeable(otmp))
- || (!strcmp(word, "call") && !objtyp_is_callable(otyp))
- )
- foo--;
- /* ugly check for unworn armor that can't be worn */
- else if ((putting_on(word) && *let == ARMOR_CLASS &&
- !canwearobj(otmp, &dummymask, FALSE))
- /* or unsuitable items rubbed on known touchstone */
- || (!strncmp(word, "rub on the stone", 16) &&
- *let == GEM_CLASS &&
- otmp->dknown && objects[otyp].oc_name_known)
- /* suppress corpses on astral, amulets elsewhere */
- || (!strcmp(word, "sacrifice") &&
- /* (!astral && amulet) || (astral && !amulet) */
- (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
- /* suppress container being stashed into */
- || (!strcmp(word, "stash") && !ck_bag(otmp))
- /* worn armor or accessory covered by cursed worn armor */
- || (taking_off(word) &&
- inaccessible_equipment(otmp, (const char *)0, TRUE))
- ) {
- /* acceptable but not listed as likely candidate */
- foo--;
- allowall = TRUE;
- *ap++ = otmp->invlet;
- }
- } else {
-
- /* "ugly check" for reading fortune cookies, part 2 */
- if ((!strcmp(word, "read")
+ || (!strcmp(word, "ready") &&
+ (otmp == uwep || (otmp == uswapwep && u.twoweap)))
+ || ((!strcmp(word, "dip") || !strcmp(word, "grease")) &&
+ inaccessible_equipment(otmp, (const char *)0 , FALSE))
+ ) {
+ foo--;
+ foox++;
+ }
+
+ /* Second ugly check; unlike the first it won't trigger an
+ * "else" in "you don't have anything else to ___".
+ */
+ else if ((putting_on(word) &&
+ ((otmp->oclass == FOOD_CLASS && otmp->otyp != MEAT_RING) ||
+ (otmp->oclass == TOOL_CLASS &&
+ otyp != BLINDFOLD && otyp != TOWEL && otyp != LENSES)))
+ || (!strcmp(word, "wield") &&
+ (otmp->oclass == TOOL_CLASS && !is_weptool(otmp)))
+ || (!strcmp(word, "eat") && !is_edible(otmp))
+ || (!strcmp(word, "sacrifice") &&
+ (otyp != CORPSE &&
+ otyp != AMULET_OF_YENDOR && otyp != FAKE_AMULET_OF_YENDOR))
+ || (!strcmp(word, "write with") &&
+ (otmp->oclass == TOOL_CLASS &&
+ otyp != MAGIC_MARKER && otyp != TOWEL))
+ || (!strcmp(word, "tin") &&
+ (otyp != CORPSE || !tinnable(otmp)))
+ || (!strcmp(word, "rub") &&
+ ((otmp->oclass == TOOL_CLASS &&
+ otyp != OIL_LAMP && otyp != MAGIC_LAMP &&
+ otyp != BRASS_LANTERN) ||
+ (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
+ || ((!strcmp(word, "use or apply") ||
+ !strcmp(word, "untrap with")) &&
+ /* Picks, axes, pole-weapons, bullwhips */
+ ((otmp->oclass == WEAPON_CLASS && !is_pick(otmp) &&
+ !is_axe(otmp) && !is_pole(otmp) && otyp != BULLWHIP) ||
+ (otmp->oclass == POTION_CLASS &&
+ /* only applicable potion is oil, and it will only
+ be offered as a choice when already discovered */
+ (otyp != POT_OIL || !otmp->dknown ||
+ !objects[POT_OIL].oc_name_known)) ||
+ (otmp->oclass == FOOD_CLASS &&
+ otyp != CREAM_PIE && otyp != EUCALYPTUS_LEAF) ||
+ (otmp->oclass == GEM_CLASS && !is_graystone(otmp))))
+ || (!strcmp(word, "invoke") &&
+ (!otmp->oartifact && !objects[otyp].oc_unique &&
+ (otyp != FAKE_AMULET_OF_YENDOR || otmp->known) &&
+ otyp != CRYSTAL_BALL && /* #invoke synonym for apply */
+ /* note: presenting the possibility of invoking non-artifact
+ mirrors and/or lamps is a simply a cruel deception... */
+ otyp != MIRROR && otyp != MAGIC_LAMP &&
+ (otyp != OIL_LAMP || /* don't list known oil lamp */
+ (otmp->dknown && objects[OIL_LAMP].oc_name_known))))
+ || (!strcmp(word, "untrap with") &&
+ (otmp->oclass == TOOL_CLASS && otyp != CAN_OF_GREASE))
+ || (!strcmp(word, "tip") && !Is_container(otmp) &&
+ /* include horn of plenty if sufficiently discovered */
+ (otmp->otyp != HORN_OF_PLENTY || !otmp->dknown ||
+ !objects[HORN_OF_PLENTY].oc_name_known))
+ || (!strcmp(word, "charge") && !is_chargeable(otmp))
+ || (!strcmp(word, "call") && !objtyp_is_callable(otyp))
+ )
+ foo--;
+ /* ugly check for unworn armor that can't be worn */
+ else if ((putting_on(word) && *let == ARMOR_CLASS &&
+ !canwearobj(otmp, &dummymask, FALSE))
+ /* or unsuitable items rubbed on known touchstone */
+ || (!strncmp(word, "rub on the stone", 16) &&
+ *let == GEM_CLASS &&
+ otmp->dknown && objects[otyp].oc_name_known)
+ /* suppress corpses on astral, amulets elsewhere */
+ || (!strcmp(word, "sacrifice") &&
+ /* (!astral && amulet) || (astral && !amulet) */
+ (!Is_astralevel(&u.uz) ^ (otmp->oclass != AMULET_CLASS)))
+ /* suppress container being stashed into */
+ || (!strcmp(word, "stash") && !ck_bag(otmp))
+ /* worn armor or accessory covered by cursed worn armor */
+ || (taking_off(word) &&
+ inaccessible_equipment(otmp, (const char *)0, TRUE))
+ ) {
+ /* acceptable but not listed as likely candidate */
+ foo--;
+ allowall = TRUE;
+ *ap++ = otmp->invlet;
+ }
+ } else {
+
+ /* "ugly check" for reading fortune cookies, part 2 */
+ if ((!strcmp(word, "read")
&& (otmp->otyp == FORTUNE_COOKIE || otmp->otyp == T_SHIRT)))
- allowall = TRUE;
- }
- }
- bp[foo] = 0;
- if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
- Strcpy(lets, bp); /* necessary since we destroy buf */
- if(foo > 5) /* compactify string */
- compactify(bp);
- *ap = '\0';
-
- if(!foo && !allowall && !allownone) {
- You("don't have anything %sto %s.",
- foox ? "else " : "", word);
- return((struct obj *)0);
- }
- for(;;) {
- cnt = 0;
- if (allowcnt == 2) allowcnt = 1; /* abort previous count */
- prezero = FALSE;
- if(!buf[0]) {
- Sprintf(qbuf, "What do you want to %s? [*]", word);
- } else {
- Sprintf(qbuf, "What do you want to %s? [%s or ?*]",
- word, buf);
- }
- if (in_doagain)
- ilet = readchar();
- else
- ilet = yn_function(qbuf, (char *)0, '\0');
- if (digit(ilet) && !allowcnt) {
- pline("No count allowed with this command.");
- continue;
- }
- if (ilet == '0') prezero = TRUE;
- while (digit(ilet)) {
- if (ilet != '?' && ilet != '*') savech(ilet);
- /* accumulate unless cnt has overflowed */
- if (allowcnt < 3) {
- prevcnt = cnt;
- cnt = 10L * cnt + (long)(ilet - '0');
- /* signal presence of cnt */
- allowcnt = (cnt >= prevcnt) ? 2 : 3;
- }
- ilet = readchar();
- }
- if (allowcnt == 3) {
- /* overflow detected; force cnt to be invalid */
- cnt = -1L;
- allowcnt = 2;
- }
- if(index(quitchars,ilet)) {
- if(flags.verbose)
- pline1(Never_mind);
- return((struct obj *)0);
- }
- if(ilet == '-') {
- return(allownone ? &zeroobj : (struct obj *) 0);
- }
- if(ilet == def_oc_syms[COIN_CLASS].sym) {
- if (!usegold) {
- You("cannot %s gold.", word);
- return(struct obj *)0;
- }
- /* Historic note: early Nethack had a bug which was
- * first reported for Larn, where trying to drop 2^32-n
- * gold pieces was allowed, and did interesting things
- * to your money supply. The LRS is the tax bureau
- * from Larn.
- */
- if (allowcnt == 2 && cnt <= 0) {
- if (cnt < 0 || !prezero)
- pline_The(
- "LRS would be very interested to know you have that much.");
- return (struct obj *)0;
- }
-
- }
- if(ilet == '?' || ilet == '*') {
- char *allowed_choices = (ilet == '?') ? lets : (char *)0;
- long ctmp = 0;
-
- if (ilet == '?' && !*lets && *altlets)
- allowed_choices = altlets;
- ilet = display_pickinv(allowed_choices, TRUE,
- allowcnt ? &ctmp : (long *)0);
- if(!ilet) continue;
- if (allowcnt && ctmp >= 0) {
- cnt = ctmp;
- if (!cnt) prezero = TRUE;
- allowcnt = 2;
- }
- if(ilet == '\033') {
- if(flags.verbose)
- pline1(Never_mind);
- return((struct obj *)0);
- }
- /* they typed a letter (not a space) at the prompt */
- }
- if(allowcnt == 2 && !strcmp(word,"throw")) {
- /* permit counts for throwing gold, but don't accept
- * counts for other things since the throw code will
- * split off a single item anyway */
- if (ilet != def_oc_syms[COIN_CLASS].sym)
- allowcnt = 1;
- if(cnt == 0 && prezero) return((struct obj *)0);
- if(cnt > 1) {
- You("can only throw one item at a time.");
- continue;
- }
- }
- context.botl = 1; /* May have changed the amount of money */
- savech(ilet);
- for (otmp = invent; otmp; otmp = otmp->nobj)
- if (otmp->invlet == ilet) break;
- if(!otmp) {
- You("don't have that object.");
- if (in_doagain) return((struct obj *) 0);
- continue;
- } else if (cnt < 0 || otmp->quan < cnt) {
- You("don't have that many! You have only %ld.",
- otmp->quan);
- if (in_doagain) return((struct obj *) 0);
- continue;
- }
- break;
- }
- if(!allowall && let && !index(let,otmp->oclass)
- && !(usegold && otmp->oclass == COIN_CLASS)
- ) {
- silly_thing(word, otmp);
- return((struct obj *)0);
- }
- if(allowcnt == 2) { /* cnt given */
- if(cnt == 0) return (struct obj *)0;
- if(cnt != otmp->quan) {
- /* don't split a stack of cursed loadstones */
- if (splittable(otmp))
- otmp = splitobj(otmp, cnt);
- else if (otmp->otyp == LOADSTONE && otmp->cursed)
- /* kludge for canletgo()'s can't-drop-this message */
- otmp->corpsenm = (int) cnt;
- }
- }
- return(otmp);
+ allowall = TRUE;
+ }
+ }
+ bp[foo] = 0;
+ if(foo == 0 && bp > buf && bp[-1] == ' ') *--bp = 0;
+ Strcpy(lets, bp); /* necessary since we destroy buf */
+ if(foo > 5) /* compactify string */
+ compactify(bp);
+ *ap = '\0';
+
+ if(!foo && !allowall && !allownone) {
+ You("don't have anything %sto %s.",
+ foox ? "else " : "", word);
+ return((struct obj *)0);
+ }
+ for(;;) {
+ cnt = 0;
+ if (allowcnt == 2) allowcnt = 1; /* abort previous count */
+ prezero = FALSE;
+ if(!buf[0]) {
+ Sprintf(qbuf, "What do you want to %s? [*]", word);
+ } else {
+ Sprintf(qbuf, "What do you want to %s? [%s or ?*]",
+ word, buf);
+ }
+ if (in_doagain)
+ ilet = readchar();
+ else
+ ilet = yn_function(qbuf, (char *)0, '\0');
+ if (digit(ilet) && !allowcnt) {
+ pline("No count allowed with this command.");
+ continue;
+ }
+ if (ilet == '0') prezero = TRUE;
+ while (digit(ilet)) {
+ if (ilet != '?' && ilet != '*') savech(ilet);
+ /* accumulate unless cnt has overflowed */
+ if (allowcnt < 3) {
+ prevcnt = cnt;
+ cnt = 10L * cnt + (long)(ilet - '0');
+ /* signal presence of cnt */
+ allowcnt = (cnt >= prevcnt) ? 2 : 3;
+ }
+ ilet = readchar();
+ }
+ if (allowcnt == 3) {
+ /* overflow detected; force cnt to be invalid */
+ cnt = -1L;
+ allowcnt = 2;
+ }
+ if(index(quitchars,ilet)) {
+ if(flags.verbose)
+ pline1(Never_mind);
+ return((struct obj *)0);
+ }
+ if(ilet == '-') {
+ return(allownone ? &zeroobj : (struct obj *) 0);
+ }
+ if(ilet == def_oc_syms[COIN_CLASS].sym) {
+ if (!usegold) {
+ You("cannot %s gold.", word);
+ return(struct obj *)0;
+ }
+ /* Historic note: early Nethack had a bug which was
+ * first reported for Larn, where trying to drop 2^32-n
+ * gold pieces was allowed, and did interesting things
+ * to your money supply. The LRS is the tax bureau
+ * from Larn.
+ */
+ if (allowcnt == 2 && cnt <= 0) {
+ if (cnt < 0 || !prezero)
+ pline_The(
+ "LRS would be very interested to know you have that much.");
+ return (struct obj *)0;
+ }
+
+ }
+ if(ilet == '?' || ilet == '*') {
+ char *allowed_choices = (ilet == '?') ? lets : (char *)0;
+ long ctmp = 0;
+
+ if (ilet == '?' && !*lets && *altlets)
+ allowed_choices = altlets;
+ ilet = display_pickinv(allowed_choices, TRUE,
+ allowcnt ? &ctmp : (long *)0);
+ if(!ilet) continue;
+ if (allowcnt && ctmp >= 0) {
+ cnt = ctmp;
+ if (!cnt) prezero = TRUE;
+ allowcnt = 2;
+ }
+ if(ilet == '\033') {
+ if(flags.verbose)
+ pline1(Never_mind);
+ return((struct obj *)0);
+ }
+ /* they typed a letter (not a space) at the prompt */
+ }
+ if(allowcnt == 2 && !strcmp(word,"throw")) {
+ /* permit counts for throwing gold, but don't accept
+ * counts for other things since the throw code will
+ * split off a single item anyway */
+ if (ilet != def_oc_syms[COIN_CLASS].sym)
+ allowcnt = 1;
+ if(cnt == 0 && prezero) return((struct obj *)0);
+ if(cnt > 1) {
+ You("can only throw one item at a time.");
+ continue;
+ }
+ }
+ context.botl = 1; /* May have changed the amount of money */
+ savech(ilet);
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (otmp->invlet == ilet) break;
+ if(!otmp) {
+ You("don't have that object.");
+ if (in_doagain) return((struct obj *) 0);
+ continue;
+ } else if (cnt < 0 || otmp->quan < cnt) {
+ You("don't have that many! You have only %ld.",
+ otmp->quan);
+ if (in_doagain) return((struct obj *) 0);
+ continue;
+ }
+ break;
+ }
+ if(!allowall && let && !index(let,otmp->oclass)
+ && !(usegold && otmp->oclass == COIN_CLASS)
+ ) {
+ silly_thing(word, otmp);
+ return((struct obj *)0);
+ }
+ if(allowcnt == 2) { /* cnt given */
+ if(cnt == 0) return (struct obj *)0;
+ if(cnt != otmp->quan) {
+ /* don't split a stack of cursed loadstones */
+ if (splittable(otmp))
+ otmp = splitobj(otmp, cnt);
+ else if (otmp->otyp == LOADSTONE && otmp->cursed)
+ /* kludge for canletgo()'s can't-drop-this message */
+ otmp->corpsenm = (int) cnt;
+ }
+ }
+ return(otmp);
}
void
const char *word;
struct obj *otmp;
{
- const char *s1, *s2, *s3, *what;
- int ocls = otmp->oclass, otyp = otmp->otyp;
-
- s1 = s2 = s3 = 0;
- /* check for attempted use of accessory commands ('P','R') on armor
- and for corresponding armor commands ('W','T') on accessories */
- if (ocls == ARMOR_CLASS) {
- if (!strcmp(word, "put on"))
- s1 = "W", s2 = "wear", s3 = "";
- else if (!strcmp(word, "remove"))
- s1 = "T", s2 = "take", s3 = " off";
- } else if ((ocls == RING_CLASS || otyp == MEAT_RING) ||
- ocls == AMULET_CLASS ||
- (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
- if (!strcmp(word, "wear"))
- s1 = "P", s2 = "put", s3 = " on";
- else if (!strcmp(word, "take off"))
- s1 = "R", s2 = "remove", s3 = "";
- }
- if (s1) {
- what = "that";
- /* quantity for armor and accessory objects is always 1,
- but some things should be referred to as plural */
- if (otyp == LENSES || is_gloves(otmp) || is_boots(otmp))
- what = "those";
- pline("Use the '%s' command to %s %s%s.", s1, s2, what, s3);
- } else {
- pline(silly_thing_to, word);
- }
+ const char *s1, *s2, *s3, *what;
+ int ocls = otmp->oclass, otyp = otmp->otyp;
+
+ s1 = s2 = s3 = 0;
+ /* check for attempted use of accessory commands ('P','R') on armor
+ and for corresponding armor commands ('W','T') on accessories */
+ if (ocls == ARMOR_CLASS) {
+ if (!strcmp(word, "put on"))
+ s1 = "W", s2 = "wear", s3 = "";
+ else if (!strcmp(word, "remove"))
+ s1 = "T", s2 = "take", s3 = " off";
+ } else if ((ocls == RING_CLASS || otyp == MEAT_RING) ||
+ ocls == AMULET_CLASS ||
+ (otyp == BLINDFOLD || otyp == TOWEL || otyp == LENSES)) {
+ if (!strcmp(word, "wear"))
+ s1 = "P", s2 = "put", s3 = " on";
+ else if (!strcmp(word, "take off"))
+ s1 = "R", s2 = "remove", s3 = "";
+ }
+ if (s1) {
+ what = "that";
+ /* quantity for armor and accessory objects is always 1,
+ but some things should be referred to as plural */
+ if (otyp == LENSES || is_gloves(otmp) || is_boots(otmp))
+ what = "those";
+ pline("Use the '%s' command to %s %s%s.", s1, s2, what, s3);
+ } else {
+ pline(silly_thing_to, word);
+ }
}
STATIC_PTR int
ckvalidcat(otmp)
register struct obj *otmp;
{
- /* use allow_category() from pickup.c */
- return((int)allow_category(otmp));
+ /* use allow_category() from pickup.c */
+ return((int)allow_category(otmp));
}
STATIC_PTR int
ckunpaid(otmp)
register struct obj *otmp;
{
- return (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp)));
+ return (otmp->unpaid || (Has_contents(otmp) && count_unpaid(otmp)));
}
boolean
wearing_armor()
{
- return((boolean)(uarm || uarmc || uarmf || uarmg || uarmh || uarms
- || uarmu));
+ return((boolean)(uarm || uarmc || uarmf || uarmg || uarmh || uarms
+ || uarmu));
}
boolean
register struct obj *otmp;
{
return((boolean)(!!(otmp->owornmask & (W_ARMOR | W_RING | W_AMUL | W_TOOL |
- W_SADDLE | W_WEP | W_SWAPWEP | W_QUIVER))));
+ W_SADDLE | W_WEP | W_SWAPWEP | W_QUIVER))));
}
/* extra xprname() input that askchain() can't pass through safe_qbuf() */
struct obj *obj;
{
return xprname(obj, (char *)0,
- safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
- 0L, 0L);
+ safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
+ 0L, 0L);
}
/* alternate safe_qbuf() -> short_oname() callback */
struct obj *obj;
{
return xprname(obj, ansimpleoname(obj),
- safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
- 0L, 0L);
+ safeq_xprn_ctx.let, safeq_xprn_ctx.dot,
+ 0L, 0L);
}
static NEARDATA const char removeables[] =
- { ARMOR_CLASS, WEAPON_CLASS, RING_CLASS, AMULET_CLASS, TOOL_CLASS, 0 };
+ { ARMOR_CLASS, WEAPON_CLASS, RING_CLASS, AMULET_CLASS, TOOL_CLASS, 0 };
/* interactive version of getobj - used for Drop, Identify and */
/* Takeoff (A). Return the number of times fn was called successfully */
boolean combo; /* combination menu flag */
unsigned *resultflags;
{
- int FDECL((*ckfn),(OBJ_P)) = (int FDECL((*),(OBJ_P))) 0;
- boolean FDECL((*filter),(OBJ_P)) = (boolean FDECL((*),(OBJ_P))) 0;
- boolean takeoff, ident, allflag, m_seen;
- int itemcount;
- int oletct, iletct, unpaid, oc_of_sym;
- char sym, *ip, olets[MAXOCLASSES+5], ilets[MAXOCLASSES+5];
- char extra_removeables[3+1]; /* uwep,uswapwep,uquiver */
- char buf[BUFSZ], qbuf[QBUFSZ];
-
- if (resultflags) *resultflags = 0;
- takeoff = ident = allflag = m_seen = FALSE;
- if(!invent){
- You("have nothing to %s.", word);
- return(0);
- }
- add_valid_menu_class(0); /* reset */
- if (taking_off(word)) {
- takeoff = TRUE;
- filter = is_worn;
- } else if (!strcmp(word, "identify")) {
- ident = TRUE;
- filter = not_fully_identified;
- }
-
- iletct = collect_obj_classes(ilets, invent,
- FALSE,
- filter, &itemcount);
- unpaid = count_unpaid(invent);
-
- if (ident && !iletct) {
- return -1; /* no further identifications */
- } else if (!takeoff && (unpaid || invent)) {
- ilets[iletct++] = ' ';
- if (unpaid) ilets[iletct++] = 'u';
- if (count_buc(invent, BUC_BLESSED)) ilets[iletct++] = 'B';
- if (count_buc(invent, BUC_UNCURSED)) ilets[iletct++] = 'U';
- if (count_buc(invent, BUC_CURSED)) ilets[iletct++] = 'C';
- if (count_buc(invent, BUC_UNKNOWN)) ilets[iletct++] = 'X';
- if (invent) ilets[iletct++] = 'a';
- } else if (takeoff && invent) {
- ilets[iletct++] = ' ';
- }
- ilets[iletct++] = 'i';
- if (!combo)
- ilets[iletct++] = 'm'; /* allow menu presentation on request */
- ilets[iletct] = '\0';
-
- for (;;) {
- Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
- word, ilets);
- getlin(qbuf, buf);
- if (buf[0] == '\033') return(0);
- if (index(buf, 'i')) {
- if (display_inventory((char *)0, TRUE) == '\033') return 0;
- } else
- break;
- }
-
- extra_removeables[0] = '\0';
- if (takeoff) {
- /* arbitrary types of items can be placed in the weapon slots
- [any duplicate entries in extra_removeables[] won't matter] */
- if (uwep) (void)strkitten(extra_removeables, uwep->oclass);
- if (uswapwep) (void)strkitten(extra_removeables, uswapwep->oclass);
- if (uquiver) (void)strkitten(extra_removeables, uquiver->oclass);
- }
-
- ip = buf;
- olets[oletct = 0] = '\0';
- while ((sym = *ip++) != '\0') {
- if (sym == ' ') continue;
- oc_of_sym = def_char_to_objclass(sym);
- if (takeoff && oc_of_sym != MAXOCLASSES) {
- if (index(extra_removeables, oc_of_sym)) {
- ; /* skip rest of takeoff checks */
- } else if (!index(removeables, oc_of_sym)) {
- pline("Not applicable.");
- return 0;
- } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
- noarmor(FALSE);
- return 0;
- } else if (oc_of_sym == WEAPON_CLASS &&
- !uwep && !uswapwep && !uquiver) {
- You("are not wielding anything.");
- return 0;
- } else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
- You("are not wearing rings.");
- return 0;
- } else if (oc_of_sym == AMULET_CLASS && !uamul) {
- You("are not wearing an amulet.");
- return 0;
- } else if (oc_of_sym == TOOL_CLASS && !ublindf) {
- You("are not wearing a blindfold.");
- return 0;
- }
- }
-
- if (oc_of_sym == COIN_CLASS && !combo) {
- context.botl = 1;
- } else if (sym == 'a') {
- allflag = TRUE;
- } else if (sym == 'A') {
- /* same as the default */ ;
- } else if (sym == 'u') {
- add_valid_menu_class('u');
- ckfn = ckunpaid;
- } else if (sym == 'B') {
- add_valid_menu_class('B');
- ckfn = ckvalidcat;
- } else if (sym == 'U') {
- add_valid_menu_class('U');
- ckfn = ckvalidcat;
- } else if (sym == 'C') {
- add_valid_menu_class('C');
- ckfn = ckvalidcat;
- } else if (sym == 'X') {
- add_valid_menu_class('X');
- ckfn = ckvalidcat;
- } else if (sym == 'm') {
- m_seen = TRUE;
- } else if (oc_of_sym == MAXOCLASSES) {
- You("don't have any %c's.", sym);
- } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
- if (!index(olets, oc_of_sym)) {
- add_valid_menu_class(oc_of_sym);
- olets[oletct++] = oc_of_sym;
- olets[oletct] = 0;
- }
- }
- }
-
- if (m_seen)
- return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
- else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag)
- return 0;
- else /*!!!! if (allowgold == 2 && !oletct)
- !!!! return 1; you dropped gold (or at least tried to)
+ int FDECL((*ckfn),(OBJ_P)) = (int FDECL((*),(OBJ_P))) 0;
+ boolean FDECL((*filter),(OBJ_P)) = (boolean FDECL((*),(OBJ_P))) 0;
+ boolean takeoff, ident, allflag, m_seen;
+ int itemcount;
+ int oletct, iletct, unpaid, oc_of_sym;
+ char sym, *ip, olets[MAXOCLASSES+5], ilets[MAXOCLASSES+5];
+ char extra_removeables[3+1]; /* uwep,uswapwep,uquiver */
+ char buf[BUFSZ], qbuf[QBUFSZ];
+
+ if (resultflags) *resultflags = 0;
+ takeoff = ident = allflag = m_seen = FALSE;
+ if(!invent){
+ You("have nothing to %s.", word);
+ return(0);
+ }
+ add_valid_menu_class(0); /* reset */
+ if (taking_off(word)) {
+ takeoff = TRUE;
+ filter = is_worn;
+ } else if (!strcmp(word, "identify")) {
+ ident = TRUE;
+ filter = not_fully_identified;
+ }
+
+ iletct = collect_obj_classes(ilets, invent,
+ FALSE,
+ filter, &itemcount);
+ unpaid = count_unpaid(invent);
+
+ if (ident && !iletct) {
+ return -1; /* no further identifications */
+ } else if (!takeoff && (unpaid || invent)) {
+ ilets[iletct++] = ' ';
+ if (unpaid) ilets[iletct++] = 'u';
+ if (count_buc(invent, BUC_BLESSED)) ilets[iletct++] = 'B';
+ if (count_buc(invent, BUC_UNCURSED)) ilets[iletct++] = 'U';
+ if (count_buc(invent, BUC_CURSED)) ilets[iletct++] = 'C';
+ if (count_buc(invent, BUC_UNKNOWN)) ilets[iletct++] = 'X';
+ if (invent) ilets[iletct++] = 'a';
+ } else if (takeoff && invent) {
+ ilets[iletct++] = ' ';
+ }
+ ilets[iletct++] = 'i';
+ if (!combo)
+ ilets[iletct++] = 'm'; /* allow menu presentation on request */
+ ilets[iletct] = '\0';
+
+ for (;;) {
+ Sprintf(qbuf,"What kinds of thing do you want to %s? [%s]",
+ word, ilets);
+ getlin(qbuf, buf);
+ if (buf[0] == '\033') return(0);
+ if (index(buf, 'i')) {
+ if (display_inventory((char *)0, TRUE) == '\033') return 0;
+ } else
+ break;
+ }
+
+ extra_removeables[0] = '\0';
+ if (takeoff) {
+ /* arbitrary types of items can be placed in the weapon slots
+ [any duplicate entries in extra_removeables[] won't matter] */
+ if (uwep) (void)strkitten(extra_removeables, uwep->oclass);
+ if (uswapwep) (void)strkitten(extra_removeables, uswapwep->oclass);
+ if (uquiver) (void)strkitten(extra_removeables, uquiver->oclass);
+ }
+
+ ip = buf;
+ olets[oletct = 0] = '\0';
+ while ((sym = *ip++) != '\0') {
+ if (sym == ' ') continue;
+ oc_of_sym = def_char_to_objclass(sym);
+ if (takeoff && oc_of_sym != MAXOCLASSES) {
+ if (index(extra_removeables, oc_of_sym)) {
+ ; /* skip rest of takeoff checks */
+ } else if (!index(removeables, oc_of_sym)) {
+ pline("Not applicable.");
+ return 0;
+ } else if (oc_of_sym == ARMOR_CLASS && !wearing_armor()) {
+ noarmor(FALSE);
+ return 0;
+ } else if (oc_of_sym == WEAPON_CLASS &&
+ !uwep && !uswapwep && !uquiver) {
+ You("are not wielding anything.");
+ return 0;
+ } else if (oc_of_sym == RING_CLASS && !uright && !uleft) {
+ You("are not wearing rings.");
+ return 0;
+ } else if (oc_of_sym == AMULET_CLASS && !uamul) {
+ You("are not wearing an amulet.");
+ return 0;
+ } else if (oc_of_sym == TOOL_CLASS && !ublindf) {
+ You("are not wearing a blindfold.");
+ return 0;
+ }
+ }
+
+ if (oc_of_sym == COIN_CLASS && !combo) {
+ context.botl = 1;
+ } else if (sym == 'a') {
+ allflag = TRUE;
+ } else if (sym == 'A') {
+ /* same as the default */ ;
+ } else if (sym == 'u') {
+ add_valid_menu_class('u');
+ ckfn = ckunpaid;
+ } else if (sym == 'B') {
+ add_valid_menu_class('B');
+ ckfn = ckvalidcat;
+ } else if (sym == 'U') {
+ add_valid_menu_class('U');
+ ckfn = ckvalidcat;
+ } else if (sym == 'C') {
+ add_valid_menu_class('C');
+ ckfn = ckvalidcat;
+ } else if (sym == 'X') {
+ add_valid_menu_class('X');
+ ckfn = ckvalidcat;
+ } else if (sym == 'm') {
+ m_seen = TRUE;
+ } else if (oc_of_sym == MAXOCLASSES) {
+ You("don't have any %c's.", sym);
+ } else if (oc_of_sym != VENOM_CLASS) { /* suppress venom */
+ if (!index(olets, oc_of_sym)) {
+ add_valid_menu_class(oc_of_sym);
+ olets[oletct++] = oc_of_sym;
+ olets[oletct] = 0;
+ }
+ }
+ }
+
+ if (m_seen)
+ return (allflag || (!oletct && ckfn != ckunpaid)) ? -2 : -3;
+ else if (flags.menu_style != MENU_TRADITIONAL && combo && !allflag)
+ return 0;
+ else /*!!!! if (allowgold == 2 && !oletct)
+ !!!! return 1; you dropped gold (or at least tried to)
!!!! test gold dropping
- else*/ {
- int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
- /*
- * askchain() has already finished the job in this case
- * so set a special flag to convey that back to the caller
- * so that it won't continue processing.
- * Fix for bug C331-1 reported by Irina Rempt-Drijfhout.
- */
- if (combo && allflag && resultflags)
- *resultflags |= ALL_FINISHED;
- return cnt;
- }
+ else*/ {
+ int cnt = askchain(&invent, olets, allflag, fn, ckfn, mx, word);
+ /*
+ * askchain() has already finished the job in this case
+ * so set a special flag to convey that back to the caller
+ * so that it won't continue processing.
+ * Fix for bug C331-1 reported by Irina Rempt-Drijfhout.
+ */
+ if (combo && allflag && resultflags)
+ *resultflags |= ALL_FINISHED;
+ return cnt;
+ }
}
/*
register const char *olets, *word; /* olets is an Obj Class char array */
register int FDECL((*fn),(OBJ_P)), FDECL((*ckfn),(OBJ_P));
{
- struct obj *otmp, *otmpo;
- register char sym, ilet;
- register int cnt = 0, dud = 0, tmp;
- boolean takeoff, nodot, ident, take_out, put_in, first, ininv;
- char qbuf[QBUFSZ], qpfx[QBUFSZ];
-
- takeoff = taking_off(word);
- ident = !strcmp(word, "identify");
- take_out = !strcmp(word, "take out");
- put_in = !strcmp(word, "put in");
- nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") ||
- ident || takeoff || take_out || put_in);
- ininv = (*objchn == invent);
- first = TRUE;
- /* Changed so the askchain is interrogated in the order specified.
- * For example, if a person specifies =/ then first all rings will be
- * asked about followed by all wands -dgk
- */
+ struct obj *otmp, *otmpo;
+ register char sym, ilet;
+ register int cnt = 0, dud = 0, tmp;
+ boolean takeoff, nodot, ident, take_out, put_in, first, ininv;
+ char qbuf[QBUFSZ], qpfx[QBUFSZ];
+
+ takeoff = taking_off(word);
+ ident = !strcmp(word, "identify");
+ take_out = !strcmp(word, "take out");
+ put_in = !strcmp(word, "put in");
+ nodot = (!strcmp(word, "nodot") || !strcmp(word, "drop") ||
+ ident || takeoff || take_out || put_in);
+ ininv = (*objchn == invent);
+ first = TRUE;
+ /* Changed so the askchain is interrogated in the order specified.
+ * For example, if a person specifies =/ then first all rings will be
+ * asked about followed by all wands -dgk
+ */
nextclass:
- ilet = 'a'-1;
- if (*objchn && (*objchn)->oclass == COIN_CLASS)
- ilet--; /* extra iteration */
- /*
- * Multiple Drop can change the invent chain while it operates
- * (dropping a burning potion of oil while levitating creates
- * an explosion which can destroy inventory items), so simple
- * list traversal
- * for (otmp = *objchn; otmp; otmp = otmp2) {
- * otmp2 = otmp->nobj;
- * ...
- * }
- * is inadeqate here. Use each object's bypass bit to keep
- * track of which list elements have already been processed.
- */
- bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
- while ((otmp = nxt_unbypassed_obj(*objchn)) != 0) {
- if (ilet == 'z') ilet = 'A'; else ilet++;
- if (olets && *olets && otmp->oclass != *olets) continue;
- if (takeoff && !is_worn(otmp)) continue;
- if (ident && !not_fully_identified(otmp)) continue;
- if (ckfn && !(*ckfn)(otmp)) continue;
- if (!allflag) {
- safeq_xprn_ctx.let = ilet;
- safeq_xprn_ctx.dot = !nodot;
- *qpfx = '\0';
- if (first) {
- /* traditional_loot() skips prompting when only one
- class of objects is involved, so prefix the first
- object being queried here with an explanation why */
- if (take_out || put_in)
- Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
- first = FALSE;
- }
- (void)safe_qbuf(qbuf, qpfx, "?",
- otmp, ininv ? safeq_xprname : doname,
- ininv ? safeq_shortxprname : ansimpleoname,
- "item");
- sym = (takeoff || ident || otmp->quan < 2L) ?
- nyaq(qbuf) : nyNaq(qbuf);
- } else
- sym = 'y';
-
- otmpo = otmp;
- if (sym == '#') {
- /* Number was entered; split the object unless it corresponds
- to 'none' or 'all'. 2 special cases: cursed loadstones and
- welded weapons (eg, multiple daggers) will remain as merged
- unit; done to avoid splitting an object that won't be
- droppable (even if we're picking up rather than dropping).
- */
- if (!yn_number)
- sym = 'n';
- else {
- sym = 'y';
- if (yn_number < otmp->quan && splittable(otmp))
- otmp = splitobj(otmp, yn_number);
- }
- }
- switch(sym){
- case 'a':
- allflag = 1;
- case 'y':
- tmp = (*fn)(otmp);
- if(tmp < 0) {
- if (container_gone(fn)) {
- /* otmp caused magic bag to explode;
- both are now gone */
- otmp = 0; /* and return */
- } else if (otmp && otmp != otmpo) {
- /* split occurred, merge again */
- (void) merged(&otmpo, &otmp);
- }
- goto ret;
- }
- cnt += tmp;
- if(--mx == 0) goto ret;
- case 'n':
- if(nodot) dud++;
- default:
- break;
- case 'q':
- /* special case for seffects() */
- if (ident) cnt = -1;
- goto ret;
- }
- }
- if (olets && *olets && *++olets)
- goto nextclass;
- if(!takeoff && (dud || cnt)) pline("That was all.");
- else if(!dud && !cnt) pline("No applicable objects.");
+ ilet = 'a'-1;
+ if (*objchn && (*objchn)->oclass == COIN_CLASS)
+ ilet--; /* extra iteration */
+ /*
+ * Multiple Drop can change the invent chain while it operates
+ * (dropping a burning potion of oil while levitating creates
+ * an explosion which can destroy inventory items), so simple
+ * list traversal
+ * for (otmp = *objchn; otmp; otmp = otmp2) {
+ * otmp2 = otmp->nobj;
+ * ...
+ * }
+ * is inadeqate here. Use each object's bypass bit to keep
+ * track of which list elements have already been processed.
+ */
+ bypass_objlist(*objchn, FALSE); /* clear chain's bypass bits */
+ while ((otmp = nxt_unbypassed_obj(*objchn)) != 0) {
+ if (ilet == 'z') ilet = 'A'; else ilet++;
+ if (olets && *olets && otmp->oclass != *olets) continue;
+ if (takeoff && !is_worn(otmp)) continue;
+ if (ident && !not_fully_identified(otmp)) continue;
+ if (ckfn && !(*ckfn)(otmp)) continue;
+ if (!allflag) {
+ safeq_xprn_ctx.let = ilet;
+ safeq_xprn_ctx.dot = !nodot;
+ *qpfx = '\0';
+ if (first) {
+ /* traditional_loot() skips prompting when only one
+ class of objects is involved, so prefix the first
+ object being queried here with an explanation why */
+ if (take_out || put_in)
+ Sprintf(qpfx, "%s: ", word), *qpfx = highc(*qpfx);
+ first = FALSE;
+ }
+ (void)safe_qbuf(qbuf, qpfx, "?",
+ otmp, ininv ? safeq_xprname : doname,
+ ininv ? safeq_shortxprname : ansimpleoname,
+ "item");
+ sym = (takeoff || ident || otmp->quan < 2L) ?
+ nyaq(qbuf) : nyNaq(qbuf);
+ } else
+ sym = 'y';
+
+ otmpo = otmp;
+ if (sym == '#') {
+ /* Number was entered; split the object unless it corresponds
+ to 'none' or 'all'. 2 special cases: cursed loadstones and
+ welded weapons (eg, multiple daggers) will remain as merged
+ unit; done to avoid splitting an object that won't be
+ droppable (even if we're picking up rather than dropping).
+ */
+ if (!yn_number)
+ sym = 'n';
+ else {
+ sym = 'y';
+ if (yn_number < otmp->quan && splittable(otmp))
+ otmp = splitobj(otmp, yn_number);
+ }
+ }
+ switch(sym){
+ case 'a':
+ allflag = 1;
+ case 'y':
+ tmp = (*fn)(otmp);
+ if(tmp < 0) {
+ if (container_gone(fn)) {
+ /* otmp caused magic bag to explode;
+ both are now gone */
+ otmp = 0; /* and return */
+ } else if (otmp && otmp != otmpo) {
+ /* split occurred, merge again */
+ (void) merged(&otmpo, &otmp);
+ }
+ goto ret;
+ }
+ cnt += tmp;
+ if(--mx == 0) goto ret;
+ case 'n':
+ if(nodot) dud++;
+ default:
+ break;
+ case 'q':
+ /* special case for seffects() */
+ if (ident) cnt = -1;
+ goto ret;
+ }
+ }
+ if (olets && *olets && *++olets)
+ goto nextclass;
+ if(!takeoff && (dud || cnt)) pline("That was all.");
+ else if(!dud && !cnt) pline("No applicable objects.");
ret:
- bypass_objlist(*objchn, FALSE);
- return(cnt);
+ bypass_objlist(*objchn, FALSE);
+ return(cnt);
}
if (otmp->oartifact) discover_artifact((xchar)otmp->oartifact);
otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1;
if (Is_container(otmp) || otmp->otyp == STATUE)
- otmp->cknown = otmp->lknown = 1;
+ otmp->cknown = otmp->lknown = 1;
if (otmp->otyp == EGG && otmp->corpsenm != NON_PM)
- learn_egg_type(otmp->corpsenm);
+ learn_egg_type(otmp->corpsenm);
}
/* ggetobj callback routine; identify an object and give immediate feedback */
/* assumptions: id_limit > 0 and at least one unID'd item is present */
while (id_limit) {
- Sprintf(buf, "What would you like to identify %s?",
- first ? "first" : "next");
- n = query_objlist(buf, invent,
- SIGNAL_NOMENU|SIGNAL_ESCAPE|USE_INVLET|INVORDER_SORT,
- &pick_list, PICK_ANY, not_fully_identified);
-
- if (n > 0) {
- if (n > id_limit) n = id_limit;
- for (i = 0; i < n; i++, id_limit--)
- (void) identify(pick_list[i].item.a_obj);
- free((genericptr_t) pick_list);
- mark_synch(); /* Before we loop to pop open another menu */
- first = 0;
- } else if (n == -2) { /* player used ESC to quit menu */
- break;
- } else if (n == -1) { /* no eligible items found */
- pline("That was all.");
- break;
- } else if (!--tryct) { /* stop re-prompting */
- pline1(thats_enough_tries);
- break;
- } else { /* try again */
- pline("Choose an item; use ESC to decline.");
- }
+ Sprintf(buf, "What would you like to identify %s?",
+ first ? "first" : "next");
+ n = query_objlist(buf, invent,
+ SIGNAL_NOMENU|SIGNAL_ESCAPE|USE_INVLET|INVORDER_SORT,
+ &pick_list, PICK_ANY, not_fully_identified);
+
+ if (n > 0) {
+ if (n > id_limit) n = id_limit;
+ for (i = 0; i < n; i++, id_limit--)
+ (void) identify(pick_list[i].item.a_obj);
+ free((genericptr_t) pick_list);
+ mark_synch(); /* Before we loop to pop open another menu */
+ first = 0;
+ } else if (n == -2) { /* player used ESC to quit menu */
+ break;
+ } else if (n == -1) { /* no eligible items found */
+ pline("That was all.");
+ break;
+ } else if (!--tryct) { /* stop re-prompting */
+ pline1(thats_enough_tries);
+ break;
+ } else { /* try again */
+ pline("Choose an item; use ESC to decline.");
+ }
}
}
unid_cnt = 0;
the_obj = 0; /* if unid_cnt ends up 1, this will be it */
for (obj = invent; obj; obj = obj->nobj)
- if (not_fully_identified(obj)) ++unid_cnt, the_obj = obj;
+ if (not_fully_identified(obj)) ++unid_cnt, the_obj = obj;
if (!unid_cnt) {
- You("have already identified all %sof your possessions.",
- learning_id ? "the rest " : "");
+ You("have already identified all %sof your possessions.",
+ learning_id ? "the rest " : "");
} else if (!id_limit || id_limit >= unid_cnt) {
- /* identify everything */
- if (unid_cnt == 1) {
- (void) identify(the_obj);
- } else {
+ /* identify everything */
+ if (unid_cnt == 1) {
+ (void) identify(the_obj);
+ } else {
- /* TODO: use fully_identify_obj and cornline/menu/whatever here */
- for (obj = invent; obj; obj = obj->nobj)
- if (not_fully_identified(obj)) (void) identify(obj);
+ /* TODO: use fully_identify_obj and cornline/menu/whatever here */
+ for (obj = invent; obj; obj = obj->nobj)
+ if (not_fully_identified(obj)) (void) identify(obj);
- }
+ }
} else {
- /* identify up to `id_limit' items */
- n = 0;
- if (flags.menu_style == MENU_TRADITIONAL)
- do {
- n = ggetobj("identify", identify, id_limit, FALSE, (unsigned *)0);
- if (n < 0) break; /* quit or no eligible items */
- } while ((id_limit -= n) > 0);
- if (n == 0 || n < -1)
- menu_identify(id_limit);
+ /* identify up to `id_limit' items */
+ n = 0;
+ if (flags.menu_style == MENU_TRADITIONAL)
+ do {
+ n = ggetobj("identify", identify, id_limit, FALSE, (unsigned *)0);
+ if (n < 0) break; /* quit or no eligible items */
+ } while ((id_limit -= n) > 0);
+ if (n == 0 || n < -1)
+ menu_identify(id_limit);
}
update_inventory();
}
if (Blind) return; /* sanity check */
for (otmp = invent; otmp; otmp = otmp->nobj) {
- if (otmp->dknown) continue; /* already seen */
- /* set dknown, perhaps bknown (for priest[ess]) */
- (void) xname(otmp);
- /*
- * If object->eknown gets implemented (see learnwand(zap.c)),
- * handle deferred discovery here.
- */
+ if (otmp->dknown) continue; /* already seen */
+ /* set dknown, perhaps bknown (for priest[ess]) */
+ (void) xname(otmp);
+ /*
+ * If object->eknown gets implemented (see learnwand(zap.c)),
+ * handle deferred discovery here.
+ */
}
update_inventory();
}
obj_to_let(obj) /* should of course only be called for things in invent */
register struct obj *obj;
{
- if (!flags.invlet_constant) {
- obj->invlet = NOINVSYM;
- reassign();
- }
- return obj->invlet;
+ if (!flags.invlet_constant) {
+ obj->invlet = NOINVSYM;
+ reassign();
+ }
+ return obj->invlet;
}
/*
register struct obj *obj;
long quan;
{
- if (!prefix) prefix = "";
- pline("%s%s%s",
- prefix, *prefix ? " " : "",
- xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L, quan));
+ if (!prefix) prefix = "";
+ pline("%s%s%s",
+ prefix, *prefix ? " " : "",
+ xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L, quan));
}
char *
long savequan = 0;
if (quan && obj) {
- savequan = obj->quan;
- obj->quan = quan;
+ savequan = obj->quan;
+ obj->quan = quan;
}
/*
* > Then the object is contained and doesn't have an inventory letter.
*/
if (cost != 0 || let == '*') {
- /* if dot is true, we're doing Iu, otherwise Ix */
- Sprintf(li, "%c - %-45s %6ld %s",
- (dot && use_invlet ? obj->invlet : let),
- (txt ? txt : doname(obj)), cost, currency(cost));
+ /* if dot is true, we're doing Iu, otherwise Ix */
+ Sprintf(li, "%c - %-45s %6ld %s",
+ (dot && use_invlet ? obj->invlet : let),
+ (txt ? txt : doname(obj)), cost, currency(cost));
} else {
- /* ordinary inventory display or pickup message */
- Sprintf(li, "%c - %s%s",
- (use_invlet ? obj->invlet : let),
- (txt ? txt : doname(obj)), (dot ? "." : ""));
+ /* ordinary inventory display or pickup message */
+ Sprintf(li, "%c - %s%s",
+ (use_invlet ? obj->invlet : let),
+ (txt ? txt : doname(obj)), (dot ? "." : ""));
}
if (savequan) obj->quan = savequan;
int
ddoinv()
{
- (void) display_inventory((char *)0, FALSE);
- return 0;
+ (void) display_inventory((char *)0, FALSE);
+ return 0;
}
/*
struct obj *obj;
while (list) {
- if (list->unpaid) {
- if (*last_found) {
- /* still looking for previous unpaid object */
- if (list == *last_found)
- *last_found = (struct obj *) 0;
- } else
- return (*last_found = list);
- }
- if (Has_contents(list)) {
- if ((obj = find_unpaid(list->cobj, last_found)) != 0)
- return obj;
- }
- list = list->nobj;
+ if (list->unpaid) {
+ if (*last_found) {
+ /* still looking for previous unpaid object */
+ if (list == *last_found)
+ *last_found = (struct obj *) 0;
+ } else
+ return (*last_found = list);
+ }
+ if (Has_contents(list)) {
+ if ((obj = find_unpaid(list->cobj, last_found)) != 0)
+ return obj;
+ }
+ list = list->nobj;
}
return (struct obj *) 0;
}
boolean want_reply;
long* out_cnt;
{
- struct obj *otmp;
- char ilet, ret;
- char *invlet = flags.inv_order;
- int n, classcount;
- winid win; /* windows being used */
- static winid local_win = WIN_ERR; /* window for partial menus */
- anything any;
- menu_item *selected;
-
- /* overriden by global flag */
- if (flags.perm_invent) {
- win = (lets && *lets) ? local_win : WIN_INVEN;
- /* create the first time used */
- if (win == WIN_ERR)
- win = local_win = create_nhwindow(NHW_MENU);
- } else
- win = WIN_INVEN;
-
- /*
- Exit early if no inventory -- but keep going if we are doing
- a permanent inventory update. We need to keep going so the
- permanent inventory window updates itself to remove the last
- item(s) dropped. One down side: the addition of the exception
- for permanent inventory window updates _can_ pop the window
- up when it's not displayed -- even if it's empty -- because we
- don't know at this level if its up or not. This may not be
- an issue if empty checks are done before hand and the call
- to here is short circuited away.
- */
- if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
- pline("Not carrying anything.");
- return 0;
- }
-
- /* oxymoron? temporarily assign permanent inventory letters */
- if (!flags.invlet_constant) reassign();
-
- if (lets && strlen(lets) == 1 && !iflags.override_ID) {
- /* when only one item of interest, use pline instead of menus;
- we actually use a fake message-line menu in order to allow
- the user to perform selection at the --More-- prompt for tty */
- ret = '\0';
- for (otmp = invent; otmp; otmp = otmp->nobj) {
- if (otmp->invlet == lets[0]) {
- ret = message_menu(lets[0],
- want_reply ? PICK_ONE : PICK_NONE,
- xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L));
- if (out_cnt) *out_cnt = -1L; /* select all */
- break;
- }
- }
- return ret;
- }
-
- start_menu(win);
- if (wizard && iflags.override_ID) {
- char prompt[BUFSZ];
- any.a_char = -1;
- /* wiz_identify stuffed the wiz_identify cmd character
- into iflags.override_ID */
- Sprintf(prompt, "Debug Identify (%s to permanently identify)",
- visctrl(iflags.override_ID));
- add_menu(win, NO_GLYPH, &any,' ', iflags.override_ID, ATR_NONE,
- prompt, MENU_UNSELECTED);
- }
+ struct obj *otmp;
+ char ilet, ret;
+ char *invlet = flags.inv_order;
+ int n, classcount;
+ winid win; /* windows being used */
+ static winid local_win = WIN_ERR; /* window for partial menus */
+ anything any;
+ menu_item *selected;
+
+ /* overriden by global flag */
+ if (flags.perm_invent) {
+ win = (lets && *lets) ? local_win : WIN_INVEN;
+ /* create the first time used */
+ if (win == WIN_ERR)
+ win = local_win = create_nhwindow(NHW_MENU);
+ } else
+ win = WIN_INVEN;
+
+ /*
+ Exit early if no inventory -- but keep going if we are doing
+ a permanent inventory update. We need to keep going so the
+ permanent inventory window updates itself to remove the last
+ item(s) dropped. One down side: the addition of the exception
+ for permanent inventory window updates _can_ pop the window
+ up when it's not displayed -- even if it's empty -- because we
+ don't know at this level if its up or not. This may not be
+ an issue if empty checks are done before hand and the call
+ to here is short circuited away.
+ */
+ if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
+ pline("Not carrying anything.");
+ return 0;
+ }
+
+ /* oxymoron? temporarily assign permanent inventory letters */
+ if (!flags.invlet_constant) reassign();
+
+ if (lets && strlen(lets) == 1 && !iflags.override_ID) {
+ /* when only one item of interest, use pline instead of menus;
+ we actually use a fake message-line menu in order to allow
+ the user to perform selection at the --More-- prompt for tty */
+ ret = '\0';
+ for (otmp = invent; otmp; otmp = otmp->nobj) {
+ if (otmp->invlet == lets[0]) {
+ ret = message_menu(lets[0],
+ want_reply ? PICK_ONE : PICK_NONE,
+ xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L));
+ if (out_cnt) *out_cnt = -1L; /* select all */
+ break;
+ }
+ }
+ return ret;
+ }
+
+ start_menu(win);
+ if (wizard && iflags.override_ID) {
+ char prompt[BUFSZ];
+ any.a_char = -1;
+ /* wiz_identify stuffed the wiz_identify cmd character
+ into iflags.override_ID */
+ Sprintf(prompt, "Debug Identify (%s to permanently identify)",
+ visctrl(iflags.override_ID));
+ add_menu(win, NO_GLYPH, &any,' ', iflags.override_ID, ATR_NONE,
+ prompt, MENU_UNSELECTED);
+ }
nextclass:
- classcount = 0;
- any = zeroany; /* set all bits to zero */
- for(otmp = invent; otmp; otmp = otmp->nobj) {
- ilet = otmp->invlet;
- if(!lets || !*lets || index(lets, ilet)) {
- any = zeroany; /* zero */
- if (!flags.sortpack || otmp->oclass == *invlet) {
- if (flags.sortpack && !classcount) {
- add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
- let_to_name(*invlet, FALSE), MENU_UNSELECTED);
- classcount++;
- }
- any.a_char = ilet;
- add_menu(win, obj_to_glyph(otmp),
- &any, ilet, 0, ATR_NONE, doname(otmp),
- MENU_UNSELECTED);
- }
- }
- }
- if (flags.sortpack) {
- if (*++invlet) goto nextclass;
- if (--invlet != venom_inv) {
- invlet = venom_inv;
- goto nextclass;
- }
- }
- end_menu(win, (char *) 0);
-
- n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
- if (n > 0) {
- ret = selected[0].item.a_char;
- if (out_cnt) *out_cnt = selected[0].count;
- free((genericptr_t)selected);
- } else
- ret = !n ? '\0' : '\033'; /* cancelled */
-
- return ret;
+ classcount = 0;
+ any = zeroany; /* set all bits to zero */
+ for(otmp = invent; otmp; otmp = otmp->nobj) {
+ ilet = otmp->invlet;
+ if(!lets || !*lets || index(lets, ilet)) {
+ any = zeroany; /* zero */
+ if (!flags.sortpack || otmp->oclass == *invlet) {
+ if (flags.sortpack && !classcount) {
+ add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+ let_to_name(*invlet, FALSE), MENU_UNSELECTED);
+ classcount++;
+ }
+ any.a_char = ilet;
+ add_menu(win, obj_to_glyph(otmp),
+ &any, ilet, 0, ATR_NONE, doname(otmp),
+ MENU_UNSELECTED);
+ }
+ }
+ }
+ if (flags.sortpack) {
+ if (*++invlet) goto nextclass;
+ if (--invlet != venom_inv) {
+ invlet = venom_inv;
+ goto nextclass;
+ }
+ }
+ end_menu(win, (char *) 0);
+
+ n = select_menu(win, want_reply ? PICK_ONE : PICK_NONE, &selected);
+ if (n > 0) {
+ ret = selected[0].item.a_char;
+ if (out_cnt) *out_cnt = selected[0].count;
+ free((genericptr_t)selected);
+ } else
+ ret = !n ? '\0' : '\033'; /* cancelled */
+
+ return ret;
}
/*
register const char *lets;
boolean want_reply;
{
- return display_pickinv(lets, want_reply, (long *)0);
+ return display_pickinv(lets, want_reply, (long *)0);
}
/*
display_used_invlets(avoidlet)
char avoidlet;
{
- struct obj *otmp;
- char ilet, ret = 0;
- char *invlet = flags.inv_order;
- int n, classcount, invdone = 0;
- winid win;
- anything any;
- menu_item *selected;
-
- if (invent) {
- win = create_nhwindow(NHW_MENU);
- start_menu(win);
- while (!invdone) {
- any = zeroany; /* set all bits to zero */
- classcount = 0;
- for(otmp = invent; otmp; otmp = otmp->nobj) {
- ilet = otmp->invlet;
- if (ilet == avoidlet) continue;
- if (!flags.sortpack || otmp->oclass == *invlet) {
- if (flags.sortpack && !classcount) {
- any = zeroany; /* zero */
- add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
- let_to_name(*invlet, FALSE), MENU_UNSELECTED);
- classcount++;
- }
- any.a_char = ilet;
- add_menu(win, obj_to_glyph(otmp),
- &any, ilet, 0, ATR_NONE, doname(otmp),
- MENU_UNSELECTED);
- }
- }
- if (flags.sortpack && *++invlet) continue;
- invdone = 1;
- }
- end_menu(win, "Inventory letters used:");
-
- n = select_menu(win, PICK_NONE, &selected);
- if (n > 0) {
- ret = selected[0].item.a_char;
- free((genericptr_t)selected);
- } else
- ret = !n ? '\0' : '\033'; /* cancelled */
- }
- return ret;
+ struct obj *otmp;
+ char ilet, ret = 0;
+ char *invlet = flags.inv_order;
+ int n, classcount, invdone = 0;
+ winid win;
+ anything any;
+ menu_item *selected;
+
+ if (invent) {
+ win = create_nhwindow(NHW_MENU);
+ start_menu(win);
+ while (!invdone) {
+ any = zeroany; /* set all bits to zero */
+ classcount = 0;
+ for(otmp = invent; otmp; otmp = otmp->nobj) {
+ ilet = otmp->invlet;
+ if (ilet == avoidlet) continue;
+ if (!flags.sortpack || otmp->oclass == *invlet) {
+ if (flags.sortpack && !classcount) {
+ any = zeroany; /* zero */
+ add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
+ let_to_name(*invlet, FALSE), MENU_UNSELECTED);
+ classcount++;
+ }
+ any.a_char = ilet;
+ add_menu(win, obj_to_glyph(otmp),
+ &any, ilet, 0, ATR_NONE, doname(otmp),
+ MENU_UNSELECTED);
+ }
+ }
+ if (flags.sortpack && *++invlet) continue;
+ invdone = 1;
+ }
+ end_menu(win, "Inventory letters used:");
+
+ n = select_menu(win, PICK_NONE, &selected);
+ if (n > 0) {
+ ret = selected[0].item.a_char;
+ free((genericptr_t)selected);
+ } else
+ ret = !n ? '\0' : '\033'; /* cancelled */
+ }
+ return ret;
}
/*
int count = 0;
while (list) {
- if (list->unpaid) count++;
- if (Has_contents(list))
- count += count_unpaid(list->cobj);
- list = list->nobj;
+ if (list->unpaid) count++;
+ if (Has_contents(list))
+ count += count_unpaid(list->cobj);
+ list = list->nobj;
}
return count;
}
int count = 0;
for ( ; list; list = list->nobj) {
- /* coins are "none of the above" as far as BUCX filtering goes */
- if (list->oclass == COIN_CLASS) continue;
- /* priests always know bless/curse state */
- if (Role_if(PM_PRIEST)) list->bknown = 1;
-
- /* check whether this object matches the requested type */
- if (!list->bknown ? (type == BUC_UNKNOWN) :
- list->blessed ? (type == BUC_BLESSED) :
- list->cursed ? (type == BUC_CURSED) :
- (type == BUC_UNCURSED))
- ++count;
+ /* coins are "none of the above" as far as BUCX filtering goes */
+ if (list->oclass == COIN_CLASS) continue;
+ /* priests always know bless/curse state */
+ if (Role_if(PM_PRIEST)) list->bknown = 1;
+
+ /* check whether this object matches the requested type */
+ if (!list->bknown ? (type == BUC_UNKNOWN) :
+ list->blessed ? (type == BUC_BLESSED) :
+ list->cursed ? (type == BUC_CURSED) :
+ (type == BUC_UNCURSED))
+ ++count;
}
return count;
}
count_contents(container, nested, quantity, everything)
struct obj *container;
boolean nested, /* include contents of any nested containers */
- quantity, /* count all vs count separate stacks */
- everything; /* all objects vs only unpaid objects */
+ quantity, /* count all vs count separate stacks */
+ everything; /* all objects vs only unpaid objects */
{
struct obj *otmp;
long count = 0L;
for (otmp = container->cobj; otmp; otmp = otmp->nobj) {
- if (nested && Has_contents(otmp))
- count += count_contents(otmp, nested, quantity, everything);
- if (everything || otmp->unpaid)
- count += quantity ? otmp->quan : 1L;
+ if (nested && Has_contents(otmp))
+ count += count_contents(otmp, nested, quantity, everything);
+ if (everything || otmp->unpaid)
+ count += quantity ? otmp->quan : 1L;
}
return count;
}
count = count_unpaid(invent);
if (count == 1) {
- marker = (struct obj *) 0;
- otmp = find_unpaid(invent, &marker);
- cost = unpaid_cost(otmp, FALSE);
- iflags.suppress_price++; /* suppress "(unpaid)" suffix */
- pline1(xprname(otmp, distant_name(otmp, doname),
- carried(otmp) ? otmp->invlet : CONTAINED_SYM,
- TRUE, cost, 0L));
- iflags.suppress_price--;
- return;
+ marker = (struct obj *) 0;
+ otmp = find_unpaid(invent, &marker);
+ cost = unpaid_cost(otmp, FALSE);
+ iflags.suppress_price++; /* suppress "(unpaid)" suffix */
+ pline1(xprname(otmp, distant_name(otmp, doname),
+ carried(otmp) ? otmp->invlet : CONTAINED_SYM,
+ TRUE, cost, 0L));
+ iflags.suppress_price--;
+ return;
}
win = create_nhwindow(NHW_MENU);
if (!flags.invlet_constant) reassign();
do {
- classcount = 0;
- for (otmp = invent; otmp; otmp = otmp->nobj) {
- ilet = otmp->invlet;
- if (otmp->unpaid) {
- if (!flags.sortpack || otmp->oclass == *invlet) {
- if (flags.sortpack && !classcount) {
- putstr(win, 0, let_to_name(*invlet, TRUE));
- classcount++;
- }
-
- totcost += cost = unpaid_cost(otmp, FALSE);
- iflags.suppress_price++; /* suppress "(unpaid)" suffix */
- putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
- ilet, TRUE, cost, 0L));
- iflags.suppress_price--;
- num_so_far++;
- }
- }
- }
+ classcount = 0;
+ for (otmp = invent; otmp; otmp = otmp->nobj) {
+ ilet = otmp->invlet;
+ if (otmp->unpaid) {
+ if (!flags.sortpack || otmp->oclass == *invlet) {
+ if (flags.sortpack && !classcount) {
+ putstr(win, 0, let_to_name(*invlet, TRUE));
+ classcount++;
+ }
+
+ totcost += cost = unpaid_cost(otmp, FALSE);
+ iflags.suppress_price++; /* suppress "(unpaid)" suffix */
+ putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
+ ilet, TRUE, cost, 0L));
+ iflags.suppress_price--;
+ num_so_far++;
+ }
+ }
+ }
} while (flags.sortpack && (*++invlet));
if (count > num_so_far) {
- /* something unpaid is contained */
- if (flags.sortpack)
- putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE));
- /*
- * Search through the container objects in the inventory for
- * unpaid items. The top level inventory items have already
- * been listed.
- */
- for (otmp = invent; otmp; otmp = otmp->nobj) {
- if (Has_contents(otmp)) {
- long contcost = 0L;
-
- marker = (struct obj *) 0; /* haven't found any */
- while (find_unpaid(otmp->cobj, &marker)) {
- totcost += cost = unpaid_cost(marker, FALSE);
- contcost += cost;
- if (otmp->cknown) {
- iflags.suppress_price++; /* suppress "(unpaid)" sfx */
- putstr(win, 0,
- xprname(marker, distant_name(marker, doname),
- CONTAINED_SYM, TRUE, cost, 0L));
- iflags.suppress_price--;
- }
- }
- if (!otmp->cknown) {
- char contbuf[BUFSZ];
-
- /* Shopkeeper knows what to charge for contents */
- Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
- putstr(win, 0,
- xprname((struct obj *)0, contbuf,
- CONTAINED_SYM, TRUE, contcost, 0L));
- }
- }
- }
+ /* something unpaid is contained */
+ if (flags.sortpack)
+ putstr(win, 0, let_to_name(CONTAINED_SYM, TRUE));
+ /*
+ * Search through the container objects in the inventory for
+ * unpaid items. The top level inventory items have already
+ * been listed.
+ */
+ for (otmp = invent; otmp; otmp = otmp->nobj) {
+ if (Has_contents(otmp)) {
+ long contcost = 0L;
+
+ marker = (struct obj *) 0; /* haven't found any */
+ while (find_unpaid(otmp->cobj, &marker)) {
+ totcost += cost = unpaid_cost(marker, FALSE);
+ contcost += cost;
+ if (otmp->cknown) {
+ iflags.suppress_price++; /* suppress "(unpaid)" sfx */
+ putstr(win, 0,
+ xprname(marker, distant_name(marker, doname),
+ CONTAINED_SYM, TRUE, cost, 0L));
+ iflags.suppress_price--;
+ }
+ }
+ if (!otmp->cknown) {
+ char contbuf[BUFSZ];
+
+ /* Shopkeeper knows what to charge for contents */
+ Sprintf(contbuf, "%s contents", s_suffix(xname(otmp)));
+ putstr(win, 0,
+ xprname((struct obj *)0, contbuf,
+ CONTAINED_SYM, TRUE, contcost, 0L));
+ }
+ }
+ }
}
putstr(win, 0, "");
int
dotypeinv()
{
- char c = '\0';
- int n, i = 0;
- char *extra_types, types[BUFSZ];
- int class_count, oclass, unpaid_count, itemcount;
- boolean billx = *u.ushops && doinvbill(0);
- menu_item *pick_list;
- boolean traditional = TRUE;
- const char *prompt = "What type of object do you want an inventory of?";
-
- if (!invent && !billx) {
- You("aren't carrying anything.");
- return 0;
- }
- unpaid_count = count_unpaid(invent);
- if (flags.menu_style != MENU_TRADITIONAL) {
- if (flags.menu_style == MENU_FULL ||
- flags.menu_style == MENU_PARTIAL) {
- traditional = FALSE;
- i = UNPAID_TYPES;
- if (billx) i |= BILLED_TYPES;
- n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
- if (!n) return 0;
- this_type = c = pick_list[0].item.a_int;
- free((genericptr_t) pick_list);
- }
- }
- if (traditional) {
- /* collect a list of classes of objects carried, for use as a prompt */
- types[0] = 0;
- class_count = collect_obj_classes(types, invent,
- FALSE,
- (boolean FDECL((*),(OBJ_P))) 0, &itemcount);
- if (unpaid_count) {
- Strcat(types, "u");
- class_count++;
- }
- if (billx) {
- Strcat(types, "x");
- class_count++;
- }
- /* add everything not already included; user won't see these */
- extra_types = eos(types);
- *extra_types++ = '\033';
- if (!unpaid_count) *extra_types++ = 'u';
- if (!billx) *extra_types++ = 'x';
- *extra_types = '\0'; /* for index() */
- for (i = 0; i < MAXOCLASSES; i++)
- if (!index(types, def_oc_syms[i].sym)) {
- *extra_types++ = def_oc_syms[i].sym;
- *extra_types = '\0';
- }
-
- if(class_count > 1) {
- c = yn_function(prompt, types, '\0');
- savech(c);
- if(c == '\0') {
- clear_nhwindow(WIN_MESSAGE);
- return 0;
- }
- } else {
- /* only one thing to itemize */
- if (unpaid_count)
- c = 'u';
- else if (billx)
- c = 'x';
- else
- c = types[0];
- }
- }
- if (c == 'x') {
- if (billx)
- (void) doinvbill(1);
- else
- pline("No used-up objects on your shopping bill.");
- return 0;
- }
- if (c == 'u') {
- if (unpaid_count)
- dounpaid();
- else
- You("are not carrying any unpaid objects.");
- return 0;
- }
- if (traditional) {
- oclass = def_char_to_objclass(c); /* change to object class */
- if (oclass == COIN_CLASS) {
- return doprgold();
- } else if (index(types, c) > index(types, '\033')) {
- You("have no such objects.");
- return 0;
- }
- this_type = oclass;
- }
- if (query_objlist((char *) 0, invent,
- (flags.invlet_constant ? USE_INVLET : 0)|INVORDER_SORT,
- &pick_list, PICK_NONE, this_type_only) > 0)
- free((genericptr_t)pick_list);
- return 0;
+ char c = '\0';
+ int n, i = 0;
+ char *extra_types, types[BUFSZ];
+ int class_count, oclass, unpaid_count, itemcount;
+ boolean billx = *u.ushops && doinvbill(0);
+ menu_item *pick_list;
+ boolean traditional = TRUE;
+ const char *prompt = "What type of object do you want an inventory of?";
+
+ if (!invent && !billx) {
+ You("aren't carrying anything.");
+ return 0;
+ }
+ unpaid_count = count_unpaid(invent);
+ if (flags.menu_style != MENU_TRADITIONAL) {
+ if (flags.menu_style == MENU_FULL ||
+ flags.menu_style == MENU_PARTIAL) {
+ traditional = FALSE;
+ i = UNPAID_TYPES;
+ if (billx) i |= BILLED_TYPES;
+ n = query_category(prompt, invent, i, &pick_list, PICK_ONE);
+ if (!n) return 0;
+ this_type = c = pick_list[0].item.a_int;
+ free((genericptr_t) pick_list);
+ }
+ }
+ if (traditional) {
+ /* collect a list of classes of objects carried, for use as a prompt */
+ types[0] = 0;
+ class_count = collect_obj_classes(types, invent,
+ FALSE,
+ (boolean FDECL((*),(OBJ_P))) 0, &itemcount);
+ if (unpaid_count) {
+ Strcat(types, "u");
+ class_count++;
+ }
+ if (billx) {
+ Strcat(types, "x");
+ class_count++;
+ }
+ /* add everything not already included; user won't see these */
+ extra_types = eos(types);
+ *extra_types++ = '\033';
+ if (!unpaid_count) *extra_types++ = 'u';
+ if (!billx) *extra_types++ = 'x';
+ *extra_types = '\0'; /* for index() */
+ for (i = 0; i < MAXOCLASSES; i++)
+ if (!index(types, def_oc_syms[i].sym)) {
+ *extra_types++ = def_oc_syms[i].sym;
+ *extra_types = '\0';
+ }
+
+ if(class_count > 1) {
+ c = yn_function(prompt, types, '\0');
+ savech(c);
+ if(c == '\0') {
+ clear_nhwindow(WIN_MESSAGE);
+ return 0;
+ }
+ } else {
+ /* only one thing to itemize */
+ if (unpaid_count)
+ c = 'u';
+ else if (billx)
+ c = 'x';
+ else
+ c = types[0];
+ }
+ }
+ if (c == 'x') {
+ if (billx)
+ (void) doinvbill(1);
+ else
+ pline("No used-up objects on your shopping bill.");
+ return 0;
+ }
+ if (c == 'u') {
+ if (unpaid_count)
+ dounpaid();
+ else
+ You("are not carrying any unpaid objects.");
+ return 0;
+ }
+ if (traditional) {
+ oclass = def_char_to_objclass(c); /* change to object class */
+ if (oclass == COIN_CLASS) {
+ return doprgold();
+ } else if (index(types, c) > index(types, '\033')) {
+ You("have no such objects.");
+ return 0;
+ }
+ this_type = oclass;
+ }
+ if (query_objlist((char *) 0, invent,
+ (flags.invlet_constant ? USE_INVLET : 0)|INVORDER_SORT,
+ &pick_list, PICK_NONE, this_type_only) > 0)
+ free((genericptr_t)pick_list);
+ return 0;
}
/* return a string describing the dungeon feature at <x,y> if there
int x, y;
char *buf;
{
- struct rm *lev = &levl[x][y];
- int ltyp = lev->typ, cmap = -1;
- const char *dfeature = 0;
- static char altbuf[BUFSZ];
-
- if (IS_DOOR(ltyp)) {
- switch (lev->doormask) {
- case D_NODOOR: cmap = S_ndoor; break; /* "doorway" */
- case D_ISOPEN: cmap = S_vodoor; break; /* "open door" */
- case D_BROKEN: dfeature = "broken door"; break;
- default: cmap = S_vcdoor; break; /* "closed door" */
- }
- /* override door description for open drawbridge */
- if (is_drawbridge_wall(x, y) >= 0)
- dfeature = "open drawbridge portcullis", cmap = -1;
- } else if (IS_FOUNTAIN(ltyp))
- cmap = S_fountain; /* "fountain" */
- else if (IS_THRONE(ltyp))
- cmap = S_throne; /* "opulent throne" */
- else if (is_lava(x,y))
- cmap = S_lava; /* "molten lava" */
- else if (is_ice(x,y))
- cmap = S_ice; /* "ice" */
- else if (is_pool(x,y))
- dfeature = "pool of water";
- else if (IS_SINK(ltyp))
- cmap = S_sink; /* "sink" */
- else if (IS_ALTAR(ltyp)) {
- Sprintf(altbuf, "%saltar to %s (%s)",
- ((lev->altarmask & AM_SHRINE) &&
- (Is_astralevel(&u.uz) || Is_sanctum(&u.uz))) ?
- "high " : "",
- a_gname(),
- align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
- dfeature = altbuf;
- } else if ((x == xupstair && y == yupstair) ||
- (x == sstairs.sx && y == sstairs.sy && sstairs.up))
- cmap = S_upstair; /* "staircase up" */
- else if ((x == xdnstair && y == ydnstair) ||
- (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
- cmap = S_dnstair; /* "staircase down" */
- else if (x == xupladder && y == yupladder)
- cmap = S_upladder; /* "ladder up" */
- else if (x == xdnladder && y == ydnladder)
- cmap = S_dnladder; /* "ladder down" */
- else if (ltyp == DRAWBRIDGE_DOWN)
- cmap = S_vodbridge; /* "lowered drawbridge" */
- else if (ltyp == DBWALL)
- cmap = S_vcdbridge; /* "raised drawbridge" */
- else if (IS_GRAVE(ltyp))
- cmap = S_grave; /* "grave" */
- else if (ltyp == TREE)
- cmap = S_tree; /* "tree" */
- else if (ltyp == IRONBARS)
- dfeature = "set of iron bars";
-
- if (cmap >= 0) dfeature = defsyms[cmap].explanation;
- if (dfeature) Strcpy(buf, dfeature);
- return dfeature;
+ struct rm *lev = &levl[x][y];
+ int ltyp = lev->typ, cmap = -1;
+ const char *dfeature = 0;
+ static char altbuf[BUFSZ];
+
+ if (IS_DOOR(ltyp)) {
+ switch (lev->doormask) {
+ case D_NODOOR: cmap = S_ndoor; break; /* "doorway" */
+ case D_ISOPEN: cmap = S_vodoor; break; /* "open door" */
+ case D_BROKEN: dfeature = "broken door"; break;
+ default: cmap = S_vcdoor; break; /* "closed door" */
+ }
+ /* override door description for open drawbridge */
+ if (is_drawbridge_wall(x, y) >= 0)
+ dfeature = "open drawbridge portcullis", cmap = -1;
+ } else if (IS_FOUNTAIN(ltyp))
+ cmap = S_fountain; /* "fountain" */
+ else if (IS_THRONE(ltyp))
+ cmap = S_throne; /* "opulent throne" */
+ else if (is_lava(x,y))
+ cmap = S_lava; /* "molten lava" */
+ else if (is_ice(x,y))
+ cmap = S_ice; /* "ice" */
+ else if (is_pool(x,y))
+ dfeature = "pool of water";
+ else if (IS_SINK(ltyp))
+ cmap = S_sink; /* "sink" */
+ else if (IS_ALTAR(ltyp)) {
+ Sprintf(altbuf, "%saltar to %s (%s)",
+ ((lev->altarmask & AM_SHRINE) &&
+ (Is_astralevel(&u.uz) || Is_sanctum(&u.uz))) ?
+ "high " : "",
+ a_gname(),
+ align_str(Amask2align(lev->altarmask & ~AM_SHRINE)));
+ dfeature = altbuf;
+ } else if ((x == xupstair && y == yupstair) ||
+ (x == sstairs.sx && y == sstairs.sy && sstairs.up))
+ cmap = S_upstair; /* "staircase up" */
+ else if ((x == xdnstair && y == ydnstair) ||
+ (x == sstairs.sx && y == sstairs.sy && !sstairs.up))
+ cmap = S_dnstair; /* "staircase down" */
+ else if (x == xupladder && y == yupladder)
+ cmap = S_upladder; /* "ladder up" */
+ else if (x == xdnladder && y == ydnladder)
+ cmap = S_dnladder; /* "ladder down" */
+ else if (ltyp == DRAWBRIDGE_DOWN)
+ cmap = S_vodbridge; /* "lowered drawbridge" */
+ else if (ltyp == DBWALL)
+ cmap = S_vcdbridge; /* "raised drawbridge" */
+ else if (IS_GRAVE(ltyp))
+ cmap = S_grave; /* "grave" */
+ else if (ltyp == TREE)
+ cmap = S_tree; /* "tree" */
+ else if (ltyp == IRONBARS)
+ dfeature = "set of iron bars";
+
+ if (cmap >= 0) dfeature = defsyms[cmap].explanation;
+ if (dfeature) Strcpy(buf, dfeature);
+ return dfeature;
}
/* look at what is here; if there are many objects (pile_limit or more),
int obj_cnt; /* obj_cnt > 0 implies that autopickup is in progess */
boolean picked_some;
{
- struct obj *otmp;
- struct trap *trap;
- const char *verb = Blind ? "feel" : "see";
- const char *dfeature = (char *)0;
- char fbuf[BUFSZ], fbuf2[BUFSZ];
- winid tmpwin;
- boolean skip_objects, felt_cockatrice = FALSE;
-
- /* default pile_limit is 5; a value of 0 means "never skip"
- (and 1 effectively forces "always skip") */
- skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
- if (u.uswallow && u.ustuck) {
- struct monst *mtmp = u.ustuck;
- Sprintf(fbuf, "Contents of %s %s",
- s_suffix(mon_nam(mtmp)), mbodypart(mtmp, STOMACH));
- /* Skip "Contents of " by using fbuf index 12 */
- You("%s to %s what is lying in %s.",
- Blind ? "try" : "look around", verb, &fbuf[12]);
- otmp = mtmp->minvent;
- if (otmp) {
- for ( ; otmp; otmp = otmp->nobj) {
- /* If swallower is an animal, it should have become stone but... */
- if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE);
- }
- if (Blind) Strcpy(fbuf, "You feel");
- Strcat(fbuf,":");
- (void) display_minventory(mtmp, MINV_ALL, fbuf);
- } else {
- You("%s no objects here.", verb);
- }
- return(!!Blind);
- }
- if (!skip_objects && (trap = t_at(u.ux,u.uy)) && trap->tseen)
- There("is %s here.",
- an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
-
- otmp = level.objects[u.ux][u.uy];
- dfeature = dfeature_at(u.ux, u.uy, fbuf2);
- if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
- dfeature = 0;
-
- if (Blind) {
- boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
-
- if (dfeature && !strncmp(dfeature, "altar ", 6)) {
- /* don't say "altar" twice, dfeature has more info */
- You("try to feel what is here.");
- } else {
- const char *where = (Blind && !can_reach_floor(TRUE)) ?
- "lying beneath you" : "lying here on the ",
- *onwhat = (Blind && !can_reach_floor(TRUE)) ?
- "" : surface(u.ux,u.uy);
-
- You("try to feel what is %s%s.",
- drift ? "floating here" : where,
- drift ? "" : onwhat);
- }
- if (dfeature && !drift && !strcmp(dfeature, surface(u.ux,u.uy)))
- dfeature = 0; /* ice already identifed */
- if (!can_reach_floor(TRUE)) {
- pline("But you can't reach it!");
- return(0);
- }
- }
-
- if (dfeature)
- Sprintf(fbuf, "There is %s here.", an(dfeature));
-
- if (!otmp || is_lava(u.ux,u.uy) || (is_pool(u.ux,u.uy) && !Underwater)) {
- if (dfeature) pline1(fbuf);
- read_engr_at(u.ux, u.uy); /* Eric Backus */
- if (!skip_objects && (Blind || !dfeature))
- You("%s no objects here.", verb);
- return(!!Blind);
- }
- /* we know there is something here */
-
- if (skip_objects) {
- if (dfeature) pline1(fbuf);
- read_engr_at(u.ux, u.uy); /* Eric Backus */
- if (obj_cnt == 1 && otmp->quan == 1L)
- There("is %s object here.", picked_some ? "another" : "an");
- else
- There("are %s%s objects here.",
- (obj_cnt < 5) ? "a few" :
- (obj_cnt < 10) ? "several" : "many",
- picked_some ? " more" : "");
- for ( ; otmp; otmp = otmp->nexthere)
- if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
- pline("%s %s%s.",
- (obj_cnt > 1) ? "Including" :
- (otmp->quan > 1L) ? "They're" : "It's",
- corpse_xname(otmp, (const char *)0, CXN_ARTICLE),
- poly_when_stoned(youmonst.data) ? "" :
- ", unfortunately");
- feel_cockatrice(otmp, FALSE);
- break;
- }
- } else if (!otmp->nexthere) {
- /* only one object */
- if (dfeature) pline1(fbuf);
- read_engr_at(u.ux, u.uy); /* Eric Backus */
- You("%s here %s.", verb, doname(otmp));
- iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
- if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE);
- } else {
- char buf[BUFSZ];
-
- display_nhwindow(WIN_MESSAGE, FALSE);
- tmpwin = create_nhwindow(NHW_MENU);
- if(dfeature) {
- putstr(tmpwin, 0, fbuf);
- putstr(tmpwin, 0, "");
- }
- Sprintf(buf, "%s that %s here:",
- picked_some ? "Other things" : "Things",
- Blind ? "you feel" : "are");
- putstr(tmpwin, 0, buf);
- for ( ; otmp; otmp = otmp->nexthere) {
- if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
- felt_cockatrice = TRUE;
- Sprintf(buf, "%s...", doname(otmp));
- putstr(tmpwin, 0, buf);
- break;
- }
- putstr(tmpwin, 0, doname(otmp));
- }
- display_nhwindow(tmpwin, TRUE);
- destroy_nhwindow(tmpwin);
- if (felt_cockatrice) feel_cockatrice(otmp, FALSE);
- read_engr_at(u.ux, u.uy); /* Eric Backus */
- }
- return(!!Blind);
+ struct obj *otmp;
+ struct trap *trap;
+ const char *verb = Blind ? "feel" : "see";
+ const char *dfeature = (char *)0;
+ char fbuf[BUFSZ], fbuf2[BUFSZ];
+ winid tmpwin;
+ boolean skip_objects, felt_cockatrice = FALSE;
+
+ /* default pile_limit is 5; a value of 0 means "never skip"
+ (and 1 effectively forces "always skip") */
+ skip_objects = (flags.pile_limit > 0 && obj_cnt >= flags.pile_limit);
+ if (u.uswallow && u.ustuck) {
+ struct monst *mtmp = u.ustuck;
+ Sprintf(fbuf, "Contents of %s %s",
+ s_suffix(mon_nam(mtmp)), mbodypart(mtmp, STOMACH));
+ /* Skip "Contents of " by using fbuf index 12 */
+ You("%s to %s what is lying in %s.",
+ Blind ? "try" : "look around", verb, &fbuf[12]);
+ otmp = mtmp->minvent;
+ if (otmp) {
+ for ( ; otmp; otmp = otmp->nobj) {
+ /* If swallower is an animal, it should have become stone but... */
+ if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE);
+ }
+ if (Blind) Strcpy(fbuf, "You feel");
+ Strcat(fbuf,":");
+ (void) display_minventory(mtmp, MINV_ALL, fbuf);
+ } else {
+ You("%s no objects here.", verb);
+ }
+ return(!!Blind);
+ }
+ if (!skip_objects && (trap = t_at(u.ux,u.uy)) && trap->tseen)
+ There("is %s here.",
+ an(defsyms[trap_to_defsym(trap->ttyp)].explanation));
+
+ otmp = level.objects[u.ux][u.uy];
+ dfeature = dfeature_at(u.ux, u.uy, fbuf2);
+ if (dfeature && !strcmp(dfeature, "pool of water") && Underwater)
+ dfeature = 0;
+
+ if (Blind) {
+ boolean drift = Is_airlevel(&u.uz) || Is_waterlevel(&u.uz);
+
+ if (dfeature && !strncmp(dfeature, "altar ", 6)) {
+ /* don't say "altar" twice, dfeature has more info */
+ You("try to feel what is here.");
+ } else {
+ const char *where = (Blind && !can_reach_floor(TRUE)) ?
+ "lying beneath you" : "lying here on the ",
+ *onwhat = (Blind && !can_reach_floor(TRUE)) ?
+ "" : surface(u.ux,u.uy);
+
+ You("try to feel what is %s%s.",
+ drift ? "floating here" : where,
+ drift ? "" : onwhat);
+ }
+ if (dfeature && !drift && !strcmp(dfeature, surface(u.ux,u.uy)))
+ dfeature = 0; /* ice already identifed */
+ if (!can_reach_floor(TRUE)) {
+ pline("But you can't reach it!");
+ return(0);
+ }
+ }
+
+ if (dfeature)
+ Sprintf(fbuf, "There is %s here.", an(dfeature));
+
+ if (!otmp || is_lava(u.ux,u.uy) || (is_pool(u.ux,u.uy) && !Underwater)) {
+ if (dfeature) pline1(fbuf);
+ read_engr_at(u.ux, u.uy); /* Eric Backus */
+ if (!skip_objects && (Blind || !dfeature))
+ You("%s no objects here.", verb);
+ return(!!Blind);
+ }
+ /* we know there is something here */
+
+ if (skip_objects) {
+ if (dfeature) pline1(fbuf);
+ read_engr_at(u.ux, u.uy); /* Eric Backus */
+ if (obj_cnt == 1 && otmp->quan == 1L)
+ There("is %s object here.", picked_some ? "another" : "an");
+ else
+ There("are %s%s objects here.",
+ (obj_cnt < 5) ? "a few" :
+ (obj_cnt < 10) ? "several" : "many",
+ picked_some ? " more" : "");
+ for ( ; otmp; otmp = otmp->nexthere)
+ if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
+ pline("%s %s%s.",
+ (obj_cnt > 1) ? "Including" :
+ (otmp->quan > 1L) ? "They're" : "It's",
+ corpse_xname(otmp, (const char *)0, CXN_ARTICLE),
+ poly_when_stoned(youmonst.data) ? "" :
+ ", unfortunately");
+ feel_cockatrice(otmp, FALSE);
+ break;
+ }
+ } else if (!otmp->nexthere) {
+ /* only one object */
+ if (dfeature) pline1(fbuf);
+ read_engr_at(u.ux, u.uy); /* Eric Backus */
+ You("%s here %s.", verb, doname(otmp));
+ iflags.last_msg = PLNMSG_ONE_ITEM_HERE;
+ if (otmp->otyp == CORPSE) feel_cockatrice(otmp, FALSE);
+ } else {
+ char buf[BUFSZ];
+
+ display_nhwindow(WIN_MESSAGE, FALSE);
+ tmpwin = create_nhwindow(NHW_MENU);
+ if(dfeature) {
+ putstr(tmpwin, 0, fbuf);
+ putstr(tmpwin, 0, "");
+ }
+ Sprintf(buf, "%s that %s here:",
+ picked_some ? "Other things" : "Things",
+ Blind ? "you feel" : "are");
+ putstr(tmpwin, 0, buf);
+ for ( ; otmp; otmp = otmp->nexthere) {
+ if (otmp->otyp == CORPSE && will_feel_cockatrice(otmp, FALSE)) {
+ felt_cockatrice = TRUE;
+ Sprintf(buf, "%s...", doname(otmp));
+ putstr(tmpwin, 0, buf);
+ break;
+ }
+ putstr(tmpwin, 0, doname(otmp));
+ }
+ display_nhwindow(tmpwin, TRUE);
+ destroy_nhwindow(tmpwin);
+ if (felt_cockatrice) feel_cockatrice(otmp, FALSE);
+ read_engr_at(u.ux, u.uy); /* Eric Backus */
+ }
+ return(!!Blind);
}
/* explicilty look at what is here, including all objects */
int
dolook()
{
- return look_here(0, FALSE);
+ return look_here(0, FALSE);
}
boolean
struct obj *otmp;
boolean force_touch;
{
- if ((Blind || force_touch) && !uarmg && !Stone_resistance &&
- (otmp->otyp == CORPSE &&
- touch_petrifies(&mons[otmp->corpsenm])))
- return TRUE;
- return FALSE;
+ if ((Blind || force_touch) && !uarmg && !Stone_resistance &&
+ (otmp->otyp == CORPSE &&
+ touch_petrifies(&mons[otmp->corpsenm])))
+ return TRUE;
+ return FALSE;
}
void
struct obj *otmp;
boolean force_touch;
{
- char kbuf[BUFSZ];
-
- if (will_feel_cockatrice(otmp, force_touch)) {
- /* "the <cockatrice> corpse" */
- Strcpy(kbuf, corpse_xname(otmp, (const char *)0, CXN_PFX_THE));
-
- if (poly_when_stoned(youmonst.data))
- You("touched %s with your bare %s.",
- kbuf, makeplural(body_part(HAND)));
- else
- pline("Touching %s is a fatal mistake...", kbuf);
- /* normalize body shape here; hand, not body_part(HAND) */
- Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
- /* will call polymon() for the poly_when_stoned() case */
- instapetrify(kbuf);
- }
+ char kbuf[BUFSZ];
+
+ if (will_feel_cockatrice(otmp, force_touch)) {
+ /* "the <cockatrice> corpse" */
+ Strcpy(kbuf, corpse_xname(otmp, (const char *)0, CXN_PFX_THE));
+
+ if (poly_when_stoned(youmonst.data))
+ You("touched %s with your bare %s.",
+ kbuf, makeplural(body_part(HAND)));
+ else
+ pline("Touching %s is a fatal mistake...", kbuf);
+ /* normalize body shape here; hand, not body_part(HAND) */
+ Sprintf(kbuf, "touching %s bare-handed", killer_xname(otmp));
+ /* will call polymon() for the poly_when_stoned() case */
+ instapetrify(kbuf);
+ }
}
void
stackobj(obj)
struct obj *obj;
{
- struct obj *otmp;
+ struct obj *otmp;
- for(otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
- if(otmp != obj && merged(&obj,&otmp))
- break;
- return;
+ for(otmp = level.objects[obj->ox][obj->oy]; otmp; otmp = otmp->nexthere)
+ if(otmp != obj && merged(&obj,&otmp))
+ break;
+ return;
}
STATIC_OVL boolean
mergable(otmp, obj) /* returns TRUE if obj & otmp can be merged */
- register struct obj *otmp, *obj;
-{
- int objnamelth = 0, otmpnamelth = 0;
- if (obj->otyp != otmp->otyp) return FALSE;
- /* coins of the same kind will always merge */
- if (obj->oclass == COIN_CLASS) return TRUE;
- if (obj->unpaid != otmp->unpaid ||
- obj->spe != otmp->spe || obj->dknown != otmp->dknown ||
- (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST)) ||
- obj->cursed != otmp->cursed || obj->blessed != otmp->blessed ||
- obj->no_charge != otmp->no_charge ||
- obj->obroken != otmp->obroken ||
- obj->otrapped != otmp->otrapped ||
- obj->lamplit != otmp->lamplit ||
- obj->greased != otmp->greased ||
- obj->oeroded != otmp->oeroded ||
- obj->oeroded2 != otmp->oeroded2 ||
- obj->bypass != otmp->bypass)
- return(FALSE);
-
- if (obj->nomerge) /* explicitly marked to prevent merge */
- return FALSE;
-
- if ((obj->oclass==WEAPON_CLASS || obj->oclass==ARMOR_CLASS) &&
- (obj->oerodeproof!=otmp->oerodeproof || obj->rknown!=otmp->rknown))
- return FALSE;
-
- if (obj->oclass == FOOD_CLASS && (obj->oeaten != otmp->oeaten ||
- obj->orotten != otmp->orotten))
- return(FALSE);
-
- if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
- if (obj->corpsenm != otmp->corpsenm)
- return FALSE;
- }
-
- /* hatching eggs don't merge; ditto for revivable corpses */
- if ((obj->otyp == EGG && (obj->timed || otmp->timed)) ||
- (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM &&
- is_reviver(&mons[otmp->corpsenm])))
- return FALSE;
-
- /* allow candle merging only if their ages are close */
- /* see begin_burn() for a reference for the magic "25" */
- if (Is_candle(obj) && obj->age/25 != otmp->age/25)
- return(FALSE);
-
- /* burning potions of oil never merge */
- if (obj->otyp == POT_OIL && obj->lamplit)
- return FALSE;
-
- /* don't merge surcharged item with base-cost item */
- if (obj->unpaid && !same_price(obj, otmp))
- return FALSE;
-
- /* if they have names, make sure they're the same */
- objnamelth = strlen(safe_oname(obj));
- otmpnamelth = strlen(safe_oname(otmp));
- if ( (objnamelth != otmpnamelth &&
- ((objnamelth && otmpnamelth) || obj->otyp == CORPSE)
- ) ||
- (objnamelth && otmpnamelth &&
- strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
- return FALSE;
-
- /* for the moment, any additional information is incompatible */
- if (has_omonst(obj) || has_omid(obj) || has_olong(obj) ||
- has_omonst(otmp) || has_omid(otmp) || has_olong(otmp))
- return FALSE;
-
- if(obj->oartifact != otmp->oartifact) return FALSE;
-
- if(obj->known == otmp->known ||
- !objects[otmp->otyp].oc_uses_known) {
- return((boolean)(objects[obj->otyp].oc_merge));
- } else return(FALSE);
+ register struct obj *otmp, *obj;
+{
+ int objnamelth = 0, otmpnamelth = 0;
+ if (obj->otyp != otmp->otyp) return FALSE;
+ /* coins of the same kind will always merge */
+ if (obj->oclass == COIN_CLASS) return TRUE;
+ if (obj->unpaid != otmp->unpaid ||
+ obj->spe != otmp->spe || obj->dknown != otmp->dknown ||
+ (obj->bknown != otmp->bknown && !Role_if(PM_PRIEST)) ||
+ obj->cursed != otmp->cursed || obj->blessed != otmp->blessed ||
+ obj->no_charge != otmp->no_charge ||
+ obj->obroken != otmp->obroken ||
+ obj->otrapped != otmp->otrapped ||
+ obj->lamplit != otmp->lamplit ||
+ obj->greased != otmp->greased ||
+ obj->oeroded != otmp->oeroded ||
+ obj->oeroded2 != otmp->oeroded2 ||
+ obj->bypass != otmp->bypass)
+ return(FALSE);
+
+ if (obj->nomerge) /* explicitly marked to prevent merge */
+ return FALSE;
+
+ if ((obj->oclass==WEAPON_CLASS || obj->oclass==ARMOR_CLASS) &&
+ (obj->oerodeproof!=otmp->oerodeproof || obj->rknown!=otmp->rknown))
+ return FALSE;
+
+ if (obj->oclass == FOOD_CLASS && (obj->oeaten != otmp->oeaten ||
+ obj->orotten != otmp->orotten))
+ return(FALSE);
+
+ if (obj->otyp == CORPSE || obj->otyp == EGG || obj->otyp == TIN) {
+ if (obj->corpsenm != otmp->corpsenm)
+ return FALSE;
+ }
+
+ /* hatching eggs don't merge; ditto for revivable corpses */
+ if ((obj->otyp == EGG && (obj->timed || otmp->timed)) ||
+ (obj->otyp == CORPSE && otmp->corpsenm >= LOW_PM &&
+ is_reviver(&mons[otmp->corpsenm])))
+ return FALSE;
+
+ /* allow candle merging only if their ages are close */
+ /* see begin_burn() for a reference for the magic "25" */
+ if (Is_candle(obj) && obj->age/25 != otmp->age/25)
+ return(FALSE);
+
+ /* burning potions of oil never merge */
+ if (obj->otyp == POT_OIL && obj->lamplit)
+ return FALSE;
+
+ /* don't merge surcharged item with base-cost item */
+ if (obj->unpaid && !same_price(obj, otmp))
+ return FALSE;
+
+ /* if they have names, make sure they're the same */
+ objnamelth = strlen(safe_oname(obj));
+ otmpnamelth = strlen(safe_oname(otmp));
+ if ( (objnamelth != otmpnamelth &&
+ ((objnamelth && otmpnamelth) || obj->otyp == CORPSE)
+ ) ||
+ (objnamelth && otmpnamelth &&
+ strncmp(ONAME(obj), ONAME(otmp), objnamelth)))
+ return FALSE;
+
+ /* for the moment, any additional information is incompatible */
+ if (has_omonst(obj) || has_omid(obj) || has_olong(obj) ||
+ has_omonst(otmp) || has_omid(otmp) || has_olong(otmp))
+ return FALSE;
+
+ if(obj->oartifact != otmp->oartifact) return FALSE;
+
+ if(obj->known == otmp->known ||
+ !objects[otmp->otyp].oc_uses_known) {
+ return((boolean)(objects[obj->otyp].oc_merge));
+ } else return(FALSE);
}
int
doprgold()
{
- /* the messages used to refer to "carrying gold", but that didn't
- take containers into account */
+ /* the messages used to refer to "carrying gold", but that didn't
+ take containers into account */
long umoney = money_cnt(invent);
- if(!umoney)
- Your("wallet is empty.");
- else
- Your("wallet contains %ld %s.", umoney, currency(umoney));
- shopper_financial_report();
- return 0;
+ if(!umoney)
+ Your("wallet is empty.");
+ else
+ Your("wallet contains %ld %s.", umoney, currency(umoney));
+ shopper_financial_report();
+ return 0;
}
int
doprwep()
{
if (!uwep) {
- You("are empty %s.", body_part(HANDED));
+ You("are empty %s.", body_part(HANDED));
} else {
- prinv((char *)0, uwep, 0L);
- if (u.twoweap) prinv((char *)0, uswapwep, 0L);
+ prinv((char *)0, uwep, 0L);
+ if (u.twoweap) prinv((char *)0, uswapwep, 0L);
}
return 0;
}
boolean report_uskin;
{
if (!uskin || !report_uskin) {
- You("are not wearing any armor.");
+ You("are not wearing any armor.");
} else {
- char *p, *uskinname, buf[BUFSZ];
+ char *p, *uskinname, buf[BUFSZ];
- uskinname = strcpy(buf, simpleonames(uskin));
- /* shorten "set of <color> dragon scales" to "<color> scales"
- and "<color> dragon scale mail" to "<color> scale mail" */
- if (!strncmpi(uskinname, "set of ", 7)) uskinname += 7;
- if ((p = strstri(uskinname, " dragon ")) != 0)
- while ((p[1] = p[8]) != '\0') ++p;
+ uskinname = strcpy(buf, simpleonames(uskin));
+ /* shorten "set of <color> dragon scales" to "<color> scales"
+ and "<color> dragon scale mail" to "<color> scale mail" */
+ if (!strncmpi(uskinname, "set of ", 7)) uskinname += 7;
+ if ((p = strstri(uskinname, " dragon ")) != 0)
+ while ((p[1] = p[8]) != '\0') ++p;
- You("are not wearing armor but have %s embedded in your skin.",
- uskinname);
+ You("are not wearing armor but have %s embedded in your skin.",
+ uskinname);
}
}
int
doprarm()
{
- if (!wearing_armor()) {
- noarmor(TRUE);
- } else {
- char lets[8];
- register int ct = 0;
-
- if(uarmu) lets[ct++] = obj_to_let(uarmu);
- if(uarm) lets[ct++] = obj_to_let(uarm);
- if(uarmc) lets[ct++] = obj_to_let(uarmc);
- if(uarmh) lets[ct++] = obj_to_let(uarmh);
- if(uarms) lets[ct++] = obj_to_let(uarms);
- if(uarmg) lets[ct++] = obj_to_let(uarmg);
- if(uarmf) lets[ct++] = obj_to_let(uarmf);
- lets[ct] = 0;
- (void) display_inventory(lets, FALSE);
- }
- return 0;
+ if (!wearing_armor()) {
+ noarmor(TRUE);
+ } else {
+ char lets[8];
+ register int ct = 0;
+
+ if(uarmu) lets[ct++] = obj_to_let(uarmu);
+ if(uarm) lets[ct++] = obj_to_let(uarm);
+ if(uarmc) lets[ct++] = obj_to_let(uarmc);
+ if(uarmh) lets[ct++] = obj_to_let(uarmh);
+ if(uarms) lets[ct++] = obj_to_let(uarms);
+ if(uarmg) lets[ct++] = obj_to_let(uarmg);
+ if(uarmf) lets[ct++] = obj_to_let(uarmf);
+ lets[ct] = 0;
+ (void) display_inventory(lets, FALSE);
+ }
+ return 0;
}
int
doprring()
{
- if(!uleft && !uright)
- You("are not wearing any rings.");
- else {
- char lets[3];
- register int ct = 0;
+ if(!uleft && !uright)
+ You("are not wearing any rings.");
+ else {
+ char lets[3];
+ register int ct = 0;
- if(uleft) lets[ct++] = obj_to_let(uleft);
- if(uright) lets[ct++] = obj_to_let(uright);
- lets[ct] = 0;
- (void) display_inventory(lets, FALSE);
- }
- return 0;
+ if(uleft) lets[ct++] = obj_to_let(uleft);
+ if(uright) lets[ct++] = obj_to_let(uright);
+ lets[ct] = 0;
+ (void) display_inventory(lets, FALSE);
+ }
+ return 0;
}
int
dopramulet()
{
- if (!uamul)
- You("are not wearing an amulet.");
- else
- prinv((char *)0, uamul, 0L);
- return 0;
+ if (!uamul)
+ You("are not wearing an amulet.");
+ else
+ prinv((char *)0, uamul, 0L);
+ return 0;
}
STATIC_OVL boolean
tool_in_use(obj)
struct obj *obj;
{
- if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L) return TRUE;
- if (obj->oclass != TOOL_CLASS) return FALSE;
- return (boolean)(obj == uwep || obj->lamplit ||
- (obj->otyp == LEASH && obj->leashmon));
+ if ((obj->owornmask & (W_TOOL | W_SADDLE)) != 0L) return TRUE;
+ if (obj->oclass != TOOL_CLASS) return FALSE;
+ return (boolean)(obj == uwep || obj->lamplit ||
+ (obj->otyp == LEASH && obj->leashmon));
}
int
doprtool()
{
- struct obj *otmp;
- int ct = 0;
- char lets[52+1];
-
- for (otmp = invent; otmp; otmp = otmp->nobj)
- if (tool_in_use(otmp))
- lets[ct++] = obj_to_let(otmp);
- lets[ct] = '\0';
- if (!ct) You("are not using any tools.");
- else (void) display_inventory(lets, FALSE);
- return 0;
+ struct obj *otmp;
+ int ct = 0;
+ char lets[52+1];
+
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (tool_in_use(otmp))
+ lets[ct++] = obj_to_let(otmp);
+ lets[ct] = '\0';
+ if (!ct) You("are not using any tools.");
+ else (void) display_inventory(lets, FALSE);
+ return 0;
}
/* '*' command; combines the ')' + '[' + '=' + '"' + '(' commands;
int
doprinuse()
{
- struct obj *otmp;
- int ct = 0;
- char lets[52+1];
-
- for (otmp = invent; otmp; otmp = otmp->nobj)
- if (is_worn(otmp) || tool_in_use(otmp))
- lets[ct++] = obj_to_let(otmp);
- lets[ct] = '\0';
- if (!ct) You("are not wearing or wielding anything.");
- else (void) display_inventory(lets, FALSE);
- return 0;
+ struct obj *otmp;
+ int ct = 0;
+ char lets[52+1];
+
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (is_worn(otmp) || tool_in_use(otmp))
+ lets[ct++] = obj_to_let(otmp);
+ lets[ct] = '\0';
+ if (!ct) You("are not wearing or wielding anything.");
+ else (void) display_inventory(lets, FALSE);
+ return 0;
}
/*
register struct obj *obj;
long numused;
{
- register struct obj *otmp;
- boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
-
- /* burn_floor_paper() keeps an object pointer that it tries to
- * useupf() multiple times, so obj must survive if plural */
- if (obj->quan > numused)
- otmp = splitobj(obj, numused);
- else
- otmp = obj;
- if(costly_spot(otmp->ox, otmp->oy)) {
- if(index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
- addtobill(otmp, FALSE, FALSE, FALSE);
- else (void)stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
- }
- delobj(otmp);
- if (at_u && u.uundetected && hides_under(youmonst.data))
- (void) hideunder(&youmonst);
+ register struct obj *otmp;
+ boolean at_u = (obj->ox == u.ux && obj->oy == u.uy);
+
+ /* burn_floor_paper() keeps an object pointer that it tries to
+ * useupf() multiple times, so obj must survive if plural */
+ if (obj->quan > numused)
+ otmp = splitobj(obj, numused);
+ else
+ otmp = obj;
+ if(costly_spot(otmp->ox, otmp->oy)) {
+ if(index(u.urooms, *in_rooms(otmp->ox, otmp->oy, 0)))
+ addtobill(otmp, FALSE, FALSE, FALSE);
+ else (void)stolen_value(otmp, otmp->ox, otmp->oy, FALSE, FALSE);
+ }
+ delobj(otmp);
+ if (at_u && u.uundetected && hides_under(youmonst.data))
+ (void) hideunder(&youmonst);
}
/*
* This must match the object class order.
*/
STATIC_VAR NEARDATA const char *names[] = { 0,
- "Illegal objects", "Weapons", "Armor", "Rings", "Amulets",
- "Tools", "Comestibles", "Potions", "Scrolls", "Spellbooks",
- "Wands", "Coins", "Gems/Stones", "Boulders/Statues", "Iron balls",
- "Chains", "Venoms"
+ "Illegal objects", "Weapons", "Armor", "Rings", "Amulets",
+ "Tools", "Comestibles", "Potions", "Scrolls", "Spellbooks",
+ "Wands", "Coins", "Gems/Stones", "Boulders/Statues", "Iron balls",
+ "Chains", "Venoms"
};
static NEARDATA const char oth_symbols[] = {
- CONTAINED_SYM,
- '\0'
+ CONTAINED_SYM,
+ '\0'
};
static NEARDATA const char *oth_names[] = {
- "Bagged/Boxed items"
+ "Bagged/Boxed items"
};
static NEARDATA char *invbuf = (char *)0;
char let;
boolean unpaid;
{
- const char *class_name;
- const char *pos;
- int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
- unsigned len;
-
- if (oclass)
- class_name = names[oclass];
- else if ((pos = index(oth_symbols, let)) != 0)
- class_name = oth_names[pos - oth_symbols];
- else
- class_name = names[0];
-
- len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "");
- if (len > invbufsiz) {
- if (invbuf) free((genericptr_t)invbuf);
- invbufsiz = len + 10; /* add slop to reduce incremental realloc */
- invbuf = (char *) alloc(invbufsiz);
- }
- if (unpaid)
- Strcat(strcpy(invbuf, "Unpaid "), class_name);
- else
- Strcpy(invbuf, class_name);
- return invbuf;
+ const char *class_name;
+ const char *pos;
+ int oclass = (let >= 1 && let < MAXOCLASSES) ? let : 0;
+ unsigned len;
+
+ if (oclass)
+ class_name = names[oclass];
+ else if ((pos = index(oth_symbols, let)) != 0)
+ class_name = oth_names[pos - oth_symbols];
+ else
+ class_name = names[0];
+
+ len = strlen(class_name) + (unpaid ? sizeof "unpaid_" : sizeof "");
+ if (len > invbufsiz) {
+ if (invbuf) free((genericptr_t)invbuf);
+ invbufsiz = len + 10; /* add slop to reduce incremental realloc */
+ invbuf = (char *) alloc(invbufsiz);
+ }
+ if (unpaid)
+ Strcat(strcpy(invbuf, "Unpaid "), class_name);
+ else
+ Strcpy(invbuf, class_name);
+ return invbuf;
}
/* release the static buffer used by let_to_name() */
void
free_invbuf()
{
- if (invbuf) free((genericptr_t)invbuf), invbuf = (char *)0;
- invbufsiz = 0;
+ if (invbuf) free((genericptr_t)invbuf), invbuf = (char *)0;
+ invbufsiz = 0;
}
/* give consecutive letters to every item in inventory (for !fixinv mode) */
void
reassign()
{
- register int i;
- register struct obj *obj;
-
- for(obj = invent, i = 0; obj; obj = obj->nobj, i++) {
- if (obj->oclass == COIN_CLASS && obj->invlet == GOLD_SYM)
- --i; /* keep $ instead of using up i'th letter */
- else
- if (i < 52)
- obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26);
- else if (obj->oclass == COIN_CLASS)
- obj->invlet = GOLD_SYM;
- else
- obj->invlet = NOINVSYM;
- }
- if (i >= 52) i = 52 - 1;
- lastinvnr = i;
+ register int i;
+ register struct obj *obj;
+
+ for(obj = invent, i = 0; obj; obj = obj->nobj, i++) {
+ if (obj->oclass == COIN_CLASS && obj->invlet == GOLD_SYM)
+ --i; /* keep $ instead of using up i'th letter */
+ else
+ if (i < 52)
+ obj->invlet = (i < 26) ? ('a'+i) : ('A'+i-26);
+ else if (obj->oclass == COIN_CLASS)
+ obj->invlet = GOLD_SYM;
+ else
+ obj->invlet = NOINVSYM;
+ }
+ if (i >= 52) i = 52 - 1;
+ lastinvnr = i;
}
/* #adjust command
int
doorganize() /* inventory organizer by Del Lamb */
{
- struct obj *obj, *otmp, *splitting, *bumped;
- int ix, cur, trycnt;
- char let;
- char alphabet[52+1], buf[52+1];
- char qbuf[QBUFSZ];
- char allowall[3]; /* { ALLOW_COUNT, ALL_CLASSES, 0 } */
- const char *adj_type;
-
- if (!invent) {
- You("aren't carrying anything to adjust.");
- return 0;
- }
-
- if (!flags.invlet_constant) reassign();
- /* get object the user wants to organize (the 'from' slot) */
- allowall[0] = ALLOW_COUNT;
- allowall[1] = ALL_CLASSES;
- allowall[2] = '\0';
- if (!(obj = getobj(allowall,"adjust"))) return(0);
-
- /* figure out whether user gave a split count to getobj() */
- splitting = bumped = 0;
- for (otmp = invent; otmp; otmp = otmp->nobj)
- if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
- if (otmp->invlet == obj->invlet) splitting = otmp;
- break;
- }
-
- /* initialize the list with all lower and upper case letters */
- for (ix = 0, let = 'a'; let <= 'z'; ) alphabet[ix++] = let++;
- for (let = 'A'; let <= 'Z'; ) alphabet[ix++] = let++;
- alphabet[ix] = '\0';
- /* for floating inv letters, truncate list after the first open slot */
- if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
- alphabet[ix + (splitting ? 0 : 1)] = '\0';
-
- /* blank out all the letters currently in use in the inventory */
- /* except those that will be merged with the selected object */
- for (otmp = invent; otmp; otmp = otmp->nobj)
- if (otmp != obj && !mergable(otmp, obj)) {
- let = otmp->invlet;
- if (let >= 'a' && let <= 'z')
- alphabet[let - 'a'] = ' ';
- else if (let >= 'A' && let <= 'Z')
- alphabet[let - 'A' + 26] = ' ';
- }
-
- /* compact the list by removing all the blanks */
- for (ix = cur = 0; alphabet[ix]; ix++)
- if (alphabet[ix] != ' ') buf[cur++] = alphabet[ix];
- if (!cur && obj->invlet == NOINVSYM) buf[cur++] = NOINVSYM;
- buf[cur] = '\0';
- /* and by dashing runs of letters */
- if(cur > 5) compactify(buf);
-
- /* get 'to' slot to use as destination */
- Sprintf(qbuf, "Adjust letter to what [%s]%s?", buf,
- invent ? " (? see used letters)" : "");
- for (trycnt = 1; ; ++trycnt) {
- let = yn_function(qbuf, (char *)0, '\0');
- if(let == '?' || let == '*') {
- let = display_used_invlets(splitting ? obj->invlet : 0);
- if (!let) continue;
- if (let == '\033') goto noadjust;
- }
- if (index(quitchars, let) ||
- /* adjusting to same slot is meaningful since all
- compatible stacks get collected along the way,
- but splitting to same slot is not */
- (splitting && let == obj->invlet)) {
+ struct obj *obj, *otmp, *splitting, *bumped;
+ int ix, cur, trycnt;
+ char let;
+ char alphabet[52+1], buf[52+1];
+ char qbuf[QBUFSZ];
+ char allowall[3]; /* { ALLOW_COUNT, ALL_CLASSES, 0 } */
+ const char *adj_type;
+
+ if (!invent) {
+ You("aren't carrying anything to adjust.");
+ return 0;
+ }
+
+ if (!flags.invlet_constant) reassign();
+ /* get object the user wants to organize (the 'from' slot) */
+ allowall[0] = ALLOW_COUNT;
+ allowall[1] = ALL_CLASSES;
+ allowall[2] = '\0';
+ if (!(obj = getobj(allowall,"adjust"))) return(0);
+
+ /* figure out whether user gave a split count to getobj() */
+ splitting = bumped = 0;
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (otmp->nobj == obj) { /* knowledge of splitobj() operation */
+ if (otmp->invlet == obj->invlet) splitting = otmp;
+ break;
+ }
+
+ /* initialize the list with all lower and upper case letters */
+ for (ix = 0, let = 'a'; let <= 'z'; ) alphabet[ix++] = let++;
+ for (let = 'A'; let <= 'Z'; ) alphabet[ix++] = let++;
+ alphabet[ix] = '\0';
+ /* for floating inv letters, truncate list after the first open slot */
+ if (!flags.invlet_constant && (ix = inv_cnt(FALSE)) < 52)
+ alphabet[ix + (splitting ? 0 : 1)] = '\0';
+
+ /* blank out all the letters currently in use in the inventory */
+ /* except those that will be merged with the selected object */
+ for (otmp = invent; otmp; otmp = otmp->nobj)
+ if (otmp != obj && !mergable(otmp, obj)) {
+ let = otmp->invlet;
+ if (let >= 'a' && let <= 'z')
+ alphabet[let - 'a'] = ' ';
+ else if (let >= 'A' && let <= 'Z')
+ alphabet[let - 'A' + 26] = ' ';
+ }
+
+ /* compact the list by removing all the blanks */
+ for (ix = cur = 0; alphabet[ix]; ix++)
+ if (alphabet[ix] != ' ') buf[cur++] = alphabet[ix];
+ if (!cur && obj->invlet == NOINVSYM) buf[cur++] = NOINVSYM;
+ buf[cur] = '\0';
+ /* and by dashing runs of letters */
+ if(cur > 5) compactify(buf);
+
+ /* get 'to' slot to use as destination */
+ Sprintf(qbuf, "Adjust letter to what [%s]%s?", buf,
+ invent ? " (? see used letters)" : "");
+ for (trycnt = 1; ; ++trycnt) {
+ let = yn_function(qbuf, (char *)0, '\0');
+ if(let == '?' || let == '*') {
+ let = display_used_invlets(splitting ? obj->invlet : 0);
+ if (!let) continue;
+ if (let == '\033') goto noadjust;
+ }
+ if (index(quitchars, let) ||
+ /* adjusting to same slot is meaningful since all
+ compatible stacks get collected along the way,
+ but splitting to same slot is not */
+ (splitting && let == obj->invlet)) {
noadjust:
- if (splitting) (void) merged(&splitting, &obj);
- pline1(Never_mind);
- return 0;
- }
- if ((letter(let) && let != '@') || index(buf, let))
- break; /* got one */
- if (trycnt == 5) goto noadjust;
- pline("Select an inventory slot letter."); /* else try again */
- }
-
- /* change the inventory and print the resulting item */
- adj_type = !splitting ? "Moving:" : "Splitting:";
-
- /*
- * don't use freeinv/addinv to avoid double-touching artifacts,
- * dousing lamps, losing luck, cursing loadstone, etc.
- */
- extract_nobj(obj, &invent);
-
- for (otmp = invent; otmp; ) {
- if (!splitting) {
- if (merged(&otmp, &obj)) {
- adj_type = "Merging:";
- obj = otmp;
- otmp = otmp->nobj;
- extract_nobj(obj, &invent);
- continue; /* otmp has already been updated */
- } else if (otmp->invlet == let) {
- adj_type = "Swapping:";
- otmp->invlet = obj->invlet;
- }
- } else {
- /* splitting: don't merge extra compatible stacks;
- if destination is compatible, do merge with it,
- otherwise bump whatever is there to an open slot */
- if (otmp->invlet == let) {
- int olth = 0;
-
- if (has_oname(obj)) olth = strlen(ONAME(obj));
- /* ugly hack: if these objects aren't going to merge
- solely because they have conflicting user-assigned
- names, strip off the name of the one being moved */
- if (olth && !obj->oartifact && !mergable(otmp, obj)) {
- char *holdname = ONAME(obj);
- ONAME(obj) = (char *)0;
- /* restore name iff merging is still not possible */
- if (!mergable(otmp, obj)) {
- ONAME(obj) = holdname;
- holdname = (char *)0;
- } else free((genericptr_t)holdname);
- }
-
- if (merged(&otmp, &obj)) {
- obj = otmp;
- extract_nobj(obj, &invent);
- } else if (inv_cnt(FALSE) >= 52) {
- (void) merged(&splitting, &obj); /* undo split */
- /* "knapsack cannot accommodate any more items" */
- Your("pack is too full.");
- return 0;
- } else {
- bumped = otmp;
- extract_nobj(bumped, &invent);
- }
- break;
- } /* found 'to' slot */
- } /* splitting */
- otmp = otmp->nobj;
- }
-
- /* inline addinv; insert loose object at beginning of inventory */
- obj->invlet = let;
- obj->nobj = invent;
- obj->where = OBJ_INVENT;
- invent = obj;
- reorder_invent();
- if (bumped) {
- /* splitting the 'from' stack is causing an incompatible
- stack in the 'to' slot to be moved into an open one;
- we need to do another inline insertion to inventory */
- assigninvlet(bumped);
- bumped->nobj = invent;
- bumped->where = OBJ_INVENT;
- invent = bumped;
- reorder_invent();
- }
-
- /* messages deferred until inventory has been fully reestablished */
- prinv(adj_type, obj, 0L);
- if (bumped) prinv("Moving:", bumped, 0L);
- update_inventory();
- return(0);
+ if (splitting) (void) merged(&splitting, &obj);
+ pline1(Never_mind);
+ return 0;
+ }
+ if ((letter(let) && let != '@') || index(buf, let))
+ break; /* got one */
+ if (trycnt == 5) goto noadjust;
+ pline("Select an inventory slot letter."); /* else try again */
+ }
+
+ /* change the inventory and print the resulting item */
+ adj_type = !splitting ? "Moving:" : "Splitting:";
+
+ /*
+ * don't use freeinv/addinv to avoid double-touching artifacts,
+ * dousing lamps, losing luck, cursing loadstone, etc.
+ */
+ extract_nobj(obj, &invent);
+
+ for (otmp = invent; otmp; ) {
+ if (!splitting) {
+ if (merged(&otmp, &obj)) {
+ adj_type = "Merging:";
+ obj = otmp;
+ otmp = otmp->nobj;
+ extract_nobj(obj, &invent);
+ continue; /* otmp has already been updated */
+ } else if (otmp->invlet == let) {
+ adj_type = "Swapping:";
+ otmp->invlet = obj->invlet;
+ }
+ } else {
+ /* splitting: don't merge extra compatible stacks;
+ if destination is compatible, do merge with it,
+ otherwise bump whatever is there to an open slot */
+ if (otmp->invlet == let) {
+ int olth = 0;
+
+ if (has_oname(obj)) olth = strlen(ONAME(obj));
+ /* ugly hack: if these objects aren't going to merge
+ solely because they have conflicting user-assigned
+ names, strip off the name of the one being moved */
+ if (olth && !obj->oartifact && !mergable(otmp, obj)) {
+ char *holdname = ONAME(obj);
+ ONAME(obj) = (char *)0;
+ /* restore name iff merging is still not possible */
+ if (!mergable(otmp, obj)) {
+ ONAME(obj) = holdname;
+ holdname = (char *)0;
+ } else free((genericptr_t)holdname);
+ }
+
+ if (merged(&otmp, &obj)) {
+ obj = otmp;
+ extract_nobj(obj, &invent);
+ } else if (inv_cnt(FALSE) >= 52) {
+ (void) merged(&splitting, &obj); /* undo split */
+ /* "knapsack cannot accommodate any more items" */
+ Your("pack is too full.");
+ return 0;
+ } else {
+ bumped = otmp;
+ extract_nobj(bumped, &invent);
+ }
+ break;
+ } /* found 'to' slot */
+ } /* splitting */
+ otmp = otmp->nobj;
+ }
+
+ /* inline addinv; insert loose object at beginning of inventory */
+ obj->invlet = let;
+ obj->nobj = invent;
+ obj->where = OBJ_INVENT;
+ invent = obj;
+ reorder_invent();
+ if (bumped) {
+ /* splitting the 'from' stack is causing an incompatible
+ stack in the 'to' slot to be moved into an open one;
+ we need to do another inline insertion to inventory */
+ assigninvlet(bumped);
+ bumped->nobj = invent;
+ bumped->where = OBJ_INVENT;
+ invent = bumped;
+ reorder_invent();
+ }
+
+ /* messages deferred until inventory has been fully reestablished */
+ prinv(adj_type, obj, 0L);
+ if (bumped) prinv("Moving:", bumped, 0L);
+ update_inventory();
+ return(0);
}
/* common to display_minventory and display_cinventory */
invdisp_nothing(hdr, txt)
const char *hdr, *txt;
{
- winid win;
- anything any;
- menu_item *selected;
+ winid win;
+ anything any;
+ menu_item *selected;
- any = zeroany;
- win = create_nhwindow(NHW_MENU);
- start_menu(win);
- add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr, MENU_UNSELECTED);
- add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
- add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
- end_menu(win, (char *)0);
- if (select_menu(win, PICK_NONE, &selected) > 0)
- free((genericptr_t)selected);
- destroy_nhwindow(win);
- return;
+ any = zeroany;
+ win = create_nhwindow(NHW_MENU);
+ start_menu(win);
+ add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings, hdr, MENU_UNSELECTED);
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, "", MENU_UNSELECTED);
+ add_menu(win, NO_GLYPH, &any, 0, 0, ATR_NONE, txt, MENU_UNSELECTED);
+ end_menu(win, (char *)0);
+ if (select_menu(win, PICK_NONE, &selected) > 0)
+ free((genericptr_t)selected);
+ destroy_nhwindow(win);
+ return;
}
/* query_objlist callback: return things that could possibly be worn/wielded */
struct obj *obj;
{
return (obj->oclass == WEAPON_CLASS
- || obj->oclass == ARMOR_CLASS
- || obj->oclass == AMULET_CLASS
- || obj->oclass == RING_CLASS
- || obj->oclass == TOOL_CLASS);
+ || obj->oclass == ARMOR_CLASS
+ || obj->oclass == AMULET_CLASS
+ || obj->oclass == RING_CLASS
+ || obj->oclass == TOOL_CLASS);
}
/*
int dflags;
char *title;
{
- struct obj *ret;
- char tmp[QBUFSZ];
- int n;
- menu_item *selected = 0;
- int do_all = (dflags & MINV_ALL) != 0,
- incl_hero = (do_all && u.uswallow && mon == u.ustuck),
- have_inv = (mon->minvent != 0),
- have_any = (have_inv || incl_hero);
-
- Sprintf(tmp,"%s %s:", s_suffix(noit_Monnam(mon)),
- do_all ? "possessions" : "armament");
-
- if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
- /* Fool the 'weapon in hand' routine into
- * displaying 'weapon in claw', etc. properly.
- */
- youmonst.data = mon->data;
-
- n = query_objlist(title ? title : tmp, mon->minvent,
- INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0),
- &selected,
- (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE,
- do_all ? allow_all : worn_wield_only);
-
- set_uasmon();
- } else {
- invdisp_nothing(title ? title : tmp, "(none)");
- n = 0;
- }
-
- if (n > 0) {
- ret = selected[0].item.a_obj;
- free((genericptr_t)selected);
- } else
- ret = (struct obj *) 0;
- return ret;
+ struct obj *ret;
+ char tmp[QBUFSZ];
+ int n;
+ menu_item *selected = 0;
+ int do_all = (dflags & MINV_ALL) != 0,
+ incl_hero = (do_all && u.uswallow && mon == u.ustuck),
+ have_inv = (mon->minvent != 0),
+ have_any = (have_inv || incl_hero);
+
+ Sprintf(tmp,"%s %s:", s_suffix(noit_Monnam(mon)),
+ do_all ? "possessions" : "armament");
+
+ if (do_all ? have_any : (mon->misc_worn_check || MON_WEP(mon))) {
+ /* Fool the 'weapon in hand' routine into
+ * displaying 'weapon in claw', etc. properly.
+ */
+ youmonst.data = mon->data;
+
+ n = query_objlist(title ? title : tmp, mon->minvent,
+ INVORDER_SORT | (incl_hero ? INCLUDE_HERO : 0),
+ &selected,
+ (dflags & MINV_NOLET) ? PICK_NONE : PICK_ONE,
+ do_all ? allow_all : worn_wield_only);
+
+ set_uasmon();
+ } else {
+ invdisp_nothing(title ? title : tmp, "(none)");
+ n = 0;
+ }
+
+ if (n > 0) {
+ ret = selected[0].item.a_obj;
+ free((genericptr_t)selected);
+ } else
+ ret = (struct obj *) 0;
+ return ret;
}
/*
display_cinventory(obj)
register struct obj *obj;
{
- struct obj *ret;
- char qbuf[QBUFSZ];
- int n;
- menu_item *selected = 0;
-
- (void)safe_qbuf(qbuf, "Contents of ", ":",
- obj, doname, ansimpleoname, "that");
-
- if (obj->cobj) {
- n = query_objlist(qbuf, obj->cobj, INVORDER_SORT, &selected,
- PICK_NONE, allow_all);
- } else {
- invdisp_nothing(qbuf, "(empty)");
- n = 0;
- }
- if (n > 0) {
- ret = selected[0].item.a_obj;
- free((genericptr_t)selected);
- } else
- ret = (struct obj *) 0;
- obj->cknown = 1;
- return ret;
+ struct obj *ret;
+ char qbuf[QBUFSZ];
+ int n;
+ menu_item *selected = 0;
+
+ (void)safe_qbuf(qbuf, "Contents of ", ":",
+ obj, doname, ansimpleoname, "that");
+
+ if (obj->cobj) {
+ n = query_objlist(qbuf, obj->cobj, INVORDER_SORT, &selected,
+ PICK_NONE, allow_all);
+ } else {
+ invdisp_nothing(qbuf, "(empty)");
+ n = 0;
+ }
+ if (n > 0) {
+ ret = selected[0].item.a_obj;
+ free((genericptr_t)selected);
+ } else
+ ret = (struct obj *) 0;
+ obj->cknown = 1;
+ return ret;
}
/* query objlist callback: return TRUE if obj is at given location */
int x, y;
boolean as_if_seen;
{
- struct obj *obj;
- menu_item *selected = 0;
- int n;
-
- /* count # of objects here */
- for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
- if (obj->ox == x && obj->oy == y) {
- if (as_if_seen) obj->dknown = 1;
- n++;
- }
-
- if (n) {
- only.x = x;
- only.y = y;
- if (query_objlist("Things that are buried here:",
- level.buriedobjlist, INVORDER_SORT,
- &selected, PICK_NONE, only_here) > 0)
- free((genericptr_t)selected);
- only.x = only.y = 0;
- }
- return n;
+ struct obj *obj;
+ menu_item *selected = 0;
+ int n;
+
+ /* count # of objects here */
+ for (n = 0, obj = level.buriedobjlist; obj; obj = obj->nobj)
+ if (obj->ox == x && obj->oy == y) {
+ if (as_if_seen) obj->dknown = 1;
+ n++;
+ }
+
+ if (n) {
+ only.x = x;
+ only.y = y;
+ if (query_objlist("Things that are buried here:",
+ level.buriedobjlist, INVORDER_SORT,
+ &selected, PICK_NONE, only_here) > 0)
+ free((genericptr_t)selected);
+ only.x = only.y = 0;
+ }
+ return n;
}
/*invent.c*/
STATIC_DCL void FDECL(mon_obj_sanity, (struct monst *,const char *));
STATIC_DCL const char *FDECL(where_name, (struct obj *));
STATIC_DCL void FDECL(insane_object,
- (struct obj *,const char *,const char *,struct monst *));
+ (struct obj *,const char *,const char *,struct monst *));
STATIC_DCL void FDECL(check_contained, (struct obj *,const char *));
struct icp {
struct oextra *
newoextra()
{
- struct oextra *oextra;
+ struct oextra *oextra;
- oextra = (struct oextra *)alloc(sizeof(struct oextra));
- oextra->oname = 0;
- oextra->omonst = 0;
- oextra->omid = 0;
- oextra->olong = 0;
- oextra->omailcmd = 0;
- return oextra;
+ oextra = (struct oextra *)alloc(sizeof(struct oextra));
+ oextra->oname = 0;
+ oextra->omonst = 0;
+ oextra->omid = 0;
+ oextra->olong = 0;
+ oextra->omailcmd = 0;
+ return oextra;
}
void
dealloc_oextra(x)
struct oextra *x;
{
- if (x) {
- if (x->oname) free((genericptr_t)x->oname);
- if (x->omonst) free((genericptr_t)x->omonst);
- if (x->omid) free((genericptr_t)x->omid);
- if (x->olong) free((genericptr_t)x->olong);
- if (x->omailcmd) free((genericptr_t)x->omailcmd);
- free((genericptr_t)x);
- }
+ if (x) {
+ if (x->oname) free((genericptr_t)x->oname);
+ if (x->omonst) free((genericptr_t)x->omonst);
+ if (x->omid) free((genericptr_t)x->omid);
+ if (x->olong) free((genericptr_t)x->olong);
+ if (x->omailcmd) free((genericptr_t)x->omailcmd);
+ free((genericptr_t)x);
+ }
}
void
newomonst(otmp)
struct obj *otmp;
{
- if (!otmp->oextra) otmp->oextra = newoextra();
- if (!OMONST(otmp)) {
- OMONST(otmp) = (struct monst *)alloc(sizeof(struct monst));
- (void) memset((genericptr_t) OMONST(otmp), 0, sizeof(struct monst));
- }
+ if (!otmp->oextra) otmp->oextra = newoextra();
+ if (!OMONST(otmp)) {
+ OMONST(otmp) = (struct monst *)alloc(sizeof(struct monst));
+ (void) memset((genericptr_t) OMONST(otmp), 0, sizeof(struct monst));
+ }
}
void
free_omonst(otmp)
struct obj *otmp;
{
- if (otmp->oextra && OMONST(otmp)) {
- free((genericptr_t) OMONST(otmp));
- OMONST(otmp) = (struct monst *)0;
- }
+ if (otmp->oextra && OMONST(otmp)) {
+ free((genericptr_t) OMONST(otmp));
+ OMONST(otmp) = (struct monst *)0;
+ }
}
void
newomid(otmp)
struct obj *otmp;
{
- if (!otmp->oextra) otmp->oextra = newoextra();
- if (!OMID(otmp)) {
- OMID(otmp) = (unsigned *)alloc(sizeof(unsigned));
- (void) memset((genericptr_t) OMID(otmp), 0, sizeof(unsigned));
- }
+ if (!otmp->oextra) otmp->oextra = newoextra();
+ if (!OMID(otmp)) {
+ OMID(otmp) = (unsigned *)alloc(sizeof(unsigned));
+ (void) memset((genericptr_t) OMID(otmp), 0, sizeof(unsigned));
+ }
}
void
free_omid(otmp)
struct obj *otmp;
{
- if (otmp->oextra && OMID(otmp)) {
- free((genericptr_t) OMID(otmp));
- OMID(otmp) = (unsigned *)0;
- }
+ if (otmp->oextra && OMID(otmp)) {
+ free((genericptr_t) OMID(otmp));
+ OMID(otmp) = (unsigned *)0;
+ }
}
void
newolong(otmp)
struct obj *otmp;
{
- if (!otmp->oextra) otmp->oextra = newoextra();
- if (!OLONG(otmp)) {
- OLONG(otmp) = (long *)alloc(sizeof(long));
- (void) memset((genericptr_t) OLONG(otmp), 0, sizeof(long));
- }
+ if (!otmp->oextra) otmp->oextra = newoextra();
+ if (!OLONG(otmp)) {
+ OLONG(otmp) = (long *)alloc(sizeof(long));
+ (void) memset((genericptr_t) OLONG(otmp), 0, sizeof(long));
+ }
}
void
free_olong(otmp)
struct obj *otmp;
{
- if (otmp->oextra && OLONG(otmp)) {
- free((genericptr_t) OLONG(otmp));
- OLONG(otmp) = (long *)0;
- }
+ if (otmp->oextra && OLONG(otmp)) {
+ free((genericptr_t) OLONG(otmp));
+ OLONG(otmp) = (long *)0;
+ }
}
void
struct obj *otmp;
const char *response_cmd;
{
- if (!otmp->oextra) otmp->oextra = newoextra();
- if (OMAILCMD(otmp)) free_omailcmd(otmp);
- OMAILCMD(otmp) = dupstr(response_cmd);
+ if (!otmp->oextra) otmp->oextra = newoextra();
+ if (OMAILCMD(otmp)) free_omailcmd(otmp);
+ OMAILCMD(otmp) = dupstr(response_cmd);
}
void
free_omailcmd(otmp)
struct obj *otmp;
{
- if (otmp->oextra && OMAILCMD(otmp)) {
- free((genericptr_t) OMAILCMD(otmp));
- OMAILCMD(otmp) = (char *)0;
- }
+ if (otmp->oextra && OMAILCMD(otmp)) {
+ free((genericptr_t) OMAILCMD(otmp));
+ OMAILCMD(otmp) = (char *)0;
+ }
}
struct obj *
int x, y;
boolean artif;
{
- struct obj *otmp;
+ struct obj *otmp;
- otmp = mkobj(let, artif);
- place_object(otmp, x, y);
- return(otmp);
+ otmp = mkobj(let, artif);
+ place_object(otmp, x, y);
+ return(otmp);
}
struct obj *
int otyp, x, y;
boolean init, artif;
{
- struct obj *otmp;
+ struct obj *otmp;
- otmp = mksobj(otyp, init, artif);
- place_object(otmp, x, y);
- return(otmp);
+ otmp = mksobj(otyp, init, artif);
+ place_object(otmp, x, y);
+ return(otmp);
}
struct obj *
char oclass;
boolean artif;
{
- int tprob, i, prob = rnd(1000);
+ int tprob, i, prob = rnd(1000);
- if(oclass == RANDOM_CLASS) {
- const struct icp *iprobs =
- (Is_rogue_level(&u.uz)) ?
- (const struct icp *)rogueprobs :
- Inhell ? (const struct icp *)hellprobs :
- (const struct icp *)mkobjprobs;
+ if(oclass == RANDOM_CLASS) {
+ const struct icp *iprobs =
+ (Is_rogue_level(&u.uz)) ?
+ (const struct icp *)rogueprobs :
+ Inhell ? (const struct icp *)hellprobs :
+ (const struct icp *)mkobjprobs;
- for(tprob = rnd(100);
- (tprob -= iprobs->iprob) > 0;
- iprobs++);
- oclass = iprobs->iclass;
- }
+ for(tprob = rnd(100);
+ (tprob -= iprobs->iprob) > 0;
+ iprobs++);
+ oclass = iprobs->iclass;
+ }
- i = bases[(int)oclass];
- while((prob -= objects[i].oc_prob) > 0) i++;
+ i = bases[(int)oclass];
+ while((prob -= objects[i].oc_prob) > 0) i++;
- if(objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
- panic("probtype error, oclass=%d i=%d", (int) oclass, i);
+ if(objects[i].oc_class != oclass || !OBJ_NAME(objects[i]))
+ panic("probtype error, oclass=%d i=%d", (int) oclass, i);
- return(mksobj(i, TRUE, artif));
+ return(mksobj(i, TRUE, artif));
}
STATIC_OVL void
mkbox_cnts(box)
struct obj *box;
{
- register int n;
- register struct obj *otmp;
-
- box->cobj = (struct obj *) 0;
-
- switch (box->otyp) {
- case ICE_BOX: n = 20; break;
- case CHEST: n = 5; break;
- case LARGE_BOX: n = 3; break;
- case SACK:
- case OILSKIN_SACK:
- /* initial inventory: sack starts out empty */
- if (moves <= 1 && !in_mklev) { n = 0; break; }
- /*else FALLTHRU*/
- case BAG_OF_HOLDING: n = 1; break;
- default: n = 0; break;
- }
-
- for (n = rn2(n+1); n > 0; n--) {
- if (box->otyp == ICE_BOX) {
- if (!(otmp = mksobj(CORPSE, TRUE, TRUE))) continue;
- /* Note: setting age to 0 is correct. Age has a different
- * from usual meaning for objects stored in ice boxes. -KAA
- */
- otmp->age = 0L;
- if (otmp->timed) {
- (void) stop_timer(ROT_CORPSE, obj_to_any(otmp));
- (void) stop_timer(REVIVE_MON, obj_to_any(otmp));
- }
- } else {
- register int tprob;
- const struct icp *iprobs = boxiprobs;
-
- for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
- ;
- if (!(otmp = mkobj(iprobs->iclass, TRUE))) continue;
-
- /* handle a couple of special cases */
- if (otmp->oclass == COIN_CLASS) {
- /* 2.5 x level's usual amount; weight adjusted below */
- otmp->quan = (long)(rnd(level_difficulty()+2) * rnd(75));
- otmp->owt = weight(otmp);
- } else while (otmp->otyp == ROCK) {
- otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LOADSTONE);
- if (otmp->quan > 2L) otmp->quan = 1L;
- otmp->owt = weight(otmp);
- }
- if (box->otyp == BAG_OF_HOLDING) {
- if (Is_mbag(otmp)) {
- otmp->otyp = SACK;
- otmp->spe = 0;
- otmp->owt = weight(otmp);
- } else while (otmp->otyp == WAN_CANCELLATION)
- otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
- }
- }
- (void) add_to_container(box, otmp);
- }
+ register int n;
+ register struct obj *otmp;
+
+ box->cobj = (struct obj *) 0;
+
+ switch (box->otyp) {
+ case ICE_BOX: n = 20; break;
+ case CHEST: n = 5; break;
+ case LARGE_BOX: n = 3; break;
+ case SACK:
+ case OILSKIN_SACK:
+ /* initial inventory: sack starts out empty */
+ if (moves <= 1 && !in_mklev) { n = 0; break; }
+ /*else FALLTHRU*/
+ case BAG_OF_HOLDING: n = 1; break;
+ default: n = 0; break;
+ }
+
+ for (n = rn2(n+1); n > 0; n--) {
+ if (box->otyp == ICE_BOX) {
+ if (!(otmp = mksobj(CORPSE, TRUE, TRUE))) continue;
+ /* Note: setting age to 0 is correct. Age has a different
+ * from usual meaning for objects stored in ice boxes. -KAA
+ */
+ otmp->age = 0L;
+ if (otmp->timed) {
+ (void) stop_timer(ROT_CORPSE, obj_to_any(otmp));
+ (void) stop_timer(REVIVE_MON, obj_to_any(otmp));
+ }
+ } else {
+ register int tprob;
+ const struct icp *iprobs = boxiprobs;
+
+ for (tprob = rnd(100); (tprob -= iprobs->iprob) > 0; iprobs++)
+ ;
+ if (!(otmp = mkobj(iprobs->iclass, TRUE))) continue;
+
+ /* handle a couple of special cases */
+ if (otmp->oclass == COIN_CLASS) {
+ /* 2.5 x level's usual amount; weight adjusted below */
+ otmp->quan = (long)(rnd(level_difficulty()+2) * rnd(75));
+ otmp->owt = weight(otmp);
+ } else while (otmp->otyp == ROCK) {
+ otmp->otyp = rnd_class(DILITHIUM_CRYSTAL, LOADSTONE);
+ if (otmp->quan > 2L) otmp->quan = 1L;
+ otmp->owt = weight(otmp);
+ }
+ if (box->otyp == BAG_OF_HOLDING) {
+ if (Is_mbag(otmp)) {
+ otmp->otyp = SACK;
+ otmp->spe = 0;
+ otmp->owt = weight(otmp);
+ } else while (otmp->otyp == WAN_CANCELLATION)
+ otmp->otyp = rnd_class(WAN_LIGHT, WAN_LIGHTNING);
+ }
+ }
+ (void) add_to_container(box, otmp);
+ }
}
int
rndmonnum() /* select a random, common monster type */
{
- register struct permonst *ptr;
- register int i;
- unsigned short excludeflags;
+ register struct permonst *ptr;
+ register int i;
+ unsigned short excludeflags;
- /* Plan A: get a level-appropriate common monster */
- ptr = rndmonst();
- if (ptr) return(monsndx(ptr));
+ /* Plan A: get a level-appropriate common monster */
+ ptr = rndmonst();
+ if (ptr) return(monsndx(ptr));
- /* Plan B: get any common monster */
- excludeflags = G_UNIQ | G_NOGEN | (Inhell ? G_NOHELL : G_HELL);
- do {
- i = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
- ptr = &mons[i];
- } while ((ptr->geno & excludeflags) != 0);
+ /* Plan B: get any common monster */
+ excludeflags = G_UNIQ | G_NOGEN | (Inhell ? G_NOHELL : G_HELL);
+ do {
+ i = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
+ ptr = &mons[i];
+ } while ((ptr->geno & excludeflags) != 0);
- return(i);
+ return(i);
}
void
copy_oextra(obj2, obj1)
struct obj *obj2, *obj1;
{
- if(!obj2 || !obj1 || !obj1->oextra) return;
-
- if (!obj2->oextra) obj2->oextra = newoextra();
- if (has_oname(obj1)) oname(obj2, ONAME(obj1));
- if (has_omonst(obj1)) {
- if (!OMONST(obj2)) newomonst(obj2);
- (void)memcpy((genericptr_t)OMONST(obj2),
- (genericptr_t)OMONST(obj1),
- sizeof(struct monst));
- OMONST(obj2)->mextra = (struct mextra *)0;
- OMONST(obj2)->nmon = (struct monst *)0;
+ if(!obj2 || !obj1 || !obj1->oextra) return;
+
+ if (!obj2->oextra) obj2->oextra = newoextra();
+ if (has_oname(obj1)) oname(obj2, ONAME(obj1));
+ if (has_omonst(obj1)) {
+ if (!OMONST(obj2)) newomonst(obj2);
+ (void)memcpy((genericptr_t)OMONST(obj2),
+ (genericptr_t)OMONST(obj1),
+ sizeof(struct monst));
+ OMONST(obj2)->mextra = (struct mextra *)0;
+ OMONST(obj2)->nmon = (struct monst *)0;
#if 0
- OMONST(obj2)->m_id = context.ident++;
- if (OMONST(obj2)->m_id) /* ident overflowed */
- OMONST(obj2)->m_id = context.ident++;
+ OMONST(obj2)->m_id = context.ident++;
+ if (OMONST(obj2)->m_id) /* ident overflowed */
+ OMONST(obj2)->m_id = context.ident++;
#endif
- if (OMONST(obj1)->mextra)
- copy_mextra(OMONST(obj2),OMONST(obj1));
- }
- if (has_omid(obj1)) {
- if (!OMID(obj2)) newomid(obj2);
- (void)memcpy((genericptr_t)OMID(obj2),
- (genericptr_t)OMID(obj1),
- sizeof(unsigned));
- }
- if (has_olong(obj1)) {
- if (!OLONG(obj2)) newolong(obj2);
- (void)memcpy((genericptr_t)OLONG(obj2),
- (genericptr_t)OLONG(obj1),
- sizeof(long));
- }
- if (has_omailcmd(obj1)) {
- new_omailcmd(obj2, OMAILCMD(obj1));
- }
+ if (OMONST(obj1)->mextra)
+ copy_mextra(OMONST(obj2),OMONST(obj1));
+ }
+ if (has_omid(obj1)) {
+ if (!OMID(obj2)) newomid(obj2);
+ (void)memcpy((genericptr_t)OMID(obj2),
+ (genericptr_t)OMID(obj1),
+ sizeof(unsigned));
+ }
+ if (has_olong(obj1)) {
+ if (!OLONG(obj2)) newolong(obj2);
+ (void)memcpy((genericptr_t)OLONG(obj2),
+ (genericptr_t)OLONG(obj1),
+ sizeof(long));
+ }
+ if (has_omailcmd(obj1)) {
+ new_omailcmd(obj2, OMAILCMD(obj1));
+ }
}
/*
struct obj *obj;
long num;
{
- struct obj *otmp;
-
- if (obj->cobj || num <= 0L || obj->quan <= num)
- panic("splitobj"); /* can't split containers */
- otmp = newobj();
- *otmp = *obj; /* copies whole structure */
- otmp->oextra = (struct oextra *)0;
- otmp->o_id = context.ident++;
- if (!otmp->o_id) otmp->o_id = context.ident++; /* ident overflowed */
- otmp->timed = 0; /* not timed, yet */
- otmp->lamplit = 0; /* ditto */
- otmp->owornmask = 0L; /* new object isn't worn */
- obj->quan -= num;
- obj->owt = weight(obj);
- otmp->quan = num;
- otmp->owt = weight(otmp); /* -= obj->owt ? */
- obj->nobj = otmp;
- /* Only set nexthere when on the floor, nexthere is also used */
- /* as a back pointer to the container object when contained. */
- if (obj->where == OBJ_FLOOR)
- obj->nexthere = otmp;
- copy_oextra(otmp, obj);
- if (has_omid(otmp)) free_omid(otmp); /* only one association with m_id*/
- if (obj->unpaid) splitbill(obj,otmp);
- if (obj->timed) obj_split_timers(obj, otmp);
- if (obj_sheds_light(obj)) obj_split_light_source(obj, otmp);
- return otmp;
+ struct obj *otmp;
+
+ if (obj->cobj || num <= 0L || obj->quan <= num)
+ panic("splitobj"); /* can't split containers */
+ otmp = newobj();
+ *otmp = *obj; /* copies whole structure */
+ otmp->oextra = (struct oextra *)0;
+ otmp->o_id = context.ident++;
+ if (!otmp->o_id) otmp->o_id = context.ident++; /* ident overflowed */
+ otmp->timed = 0; /* not timed, yet */
+ otmp->lamplit = 0; /* ditto */
+ otmp->owornmask = 0L; /* new object isn't worn */
+ obj->quan -= num;
+ obj->owt = weight(obj);
+ otmp->quan = num;
+ otmp->owt = weight(otmp); /* -= obj->owt ? */
+ obj->nobj = otmp;
+ /* Only set nexthere when on the floor, nexthere is also used */
+ /* as a back pointer to the container object when contained. */
+ if (obj->where == OBJ_FLOOR)
+ obj->nexthere = otmp;
+ copy_oextra(otmp, obj);
+ if (has_omid(otmp)) free_omid(otmp); /* only one association with m_id*/
+ if (obj->unpaid) splitbill(obj,otmp);
+ if (obj->timed) obj_split_timers(obj, otmp);
+ if (obj_sheds_light(obj)) obj_split_light_source(obj, otmp);
+ return otmp;
}
/*
otmp->where = obj->where;
switch (obj->where) {
case OBJ_FREE:
- /* do nothing */
- break;
+ /* do nothing */
+ break;
case OBJ_INVENT:
- otmp->nobj = obj->nobj;
- obj->nobj = otmp;
- extract_nobj(obj, &invent);
- break;
+ otmp->nobj = obj->nobj;
+ obj->nobj = otmp;
+ extract_nobj(obj, &invent);
+ break;
case OBJ_CONTAINED:
- otmp->nobj = obj->nobj;
- otmp->ocontainer = obj->ocontainer;
- obj->nobj = otmp;
- extract_nobj(obj, &obj->ocontainer->cobj);
- break;
+ otmp->nobj = obj->nobj;
+ otmp->ocontainer = obj->ocontainer;
+ obj->nobj = otmp;
+ extract_nobj(obj, &obj->ocontainer->cobj);
+ break;
case OBJ_MINVENT:
- otmp->nobj = obj->nobj;
- otmp->ocarry = obj->ocarry;
- obj->nobj = otmp;
- extract_nobj(obj, &obj->ocarry->minvent);
- break;
+ otmp->nobj = obj->nobj;
+ otmp->ocarry = obj->ocarry;
+ obj->nobj = otmp;
+ extract_nobj(obj, &obj->ocarry->minvent);
+ break;
case OBJ_FLOOR:
- otmp->nobj = obj->nobj;
- otmp->nexthere = obj->nexthere;
- otmp->ox = obj->ox;
- otmp->oy = obj->oy;
- obj->nobj = otmp;
- obj->nexthere = otmp;
- extract_nobj(obj, &fobj);
- extract_nexthere(obj, &level.objects[obj->ox][obj->oy]);
- break;
+ otmp->nobj = obj->nobj;
+ otmp->nexthere = obj->nexthere;
+ otmp->ox = obj->ox;
+ otmp->oy = obj->oy;
+ obj->nobj = otmp;
+ obj->nexthere = otmp;
+ extract_nobj(obj, &fobj);
+ extract_nexthere(obj, &level.objects[obj->ox][obj->oy]);
+ break;
default:
- panic("replace_object: obj position");
- break;
+ panic("replace_object: obj position");
+ break;
}
}
bill_dummy_object(otmp)
register struct obj *otmp;
{
- register struct obj *dummy;
- long cost = 0L;
-
- if (otmp->unpaid) {
- cost = unpaid_cost(otmp, FALSE);
- subfrombill(otmp, shop_keeper(*u.ushops));
- }
- dummy = newobj();
- *dummy = *otmp;
- dummy->oextra = (struct oextra *)0;
- dummy->where = OBJ_FREE;
- dummy->o_id = context.ident++;
- if (!dummy->o_id) dummy->o_id = context.ident++; /* ident overflowed */
- dummy->timed = 0;
- copy_oextra(dummy, otmp);
- if (has_omid(dummy)) free_omid(dummy); /* only one association with m_id*/
- if (Is_candle(dummy)) dummy->lamplit = 0;
- addtobill(dummy, FALSE, TRUE, TRUE);
- if (cost) alter_cost(dummy, -cost);
- /* no_charge is only valid for some locations */
- otmp->no_charge = (otmp->where == OBJ_FLOOR ||
- otmp->where == OBJ_CONTAINED) ? 1 : 0;
- otmp->unpaid = 0;
- return;
+ register struct obj *dummy;
+ long cost = 0L;
+
+ if (otmp->unpaid) {
+ cost = unpaid_cost(otmp, FALSE);
+ subfrombill(otmp, shop_keeper(*u.ushops));
+ }
+ dummy = newobj();
+ *dummy = *otmp;
+ dummy->oextra = (struct oextra *)0;
+ dummy->where = OBJ_FREE;
+ dummy->o_id = context.ident++;
+ if (!dummy->o_id) dummy->o_id = context.ident++; /* ident overflowed */
+ dummy->timed = 0;
+ copy_oextra(dummy, otmp);
+ if (has_omid(dummy)) free_omid(dummy); /* only one association with m_id*/
+ if (Is_candle(dummy)) dummy->lamplit = 0;
+ addtobill(dummy, FALSE, TRUE, TRUE);
+ if (cost) alter_cost(dummy, -cost);
+ /* no_charge is only valid for some locations */
+ otmp->no_charge = (otmp->where == OBJ_FLOOR ||
+ otmp->where == OBJ_CONTAINED) ? 1 : 0;
+ otmp->unpaid = 0;
+ return;
}
/* alteration types; must match COST_xxx macros in hack.h */
static const char * const alteration_verbs[] = {
- "cancel", "drain", "uncharge", "unbless", "uncurse",
- "disenchant", "degrade", "dilute", "erase", "burn",
- "neutralize", "destroy", "splatter", "bite", "open",
- "break the lock on", "rust", "rot", "tarnish"
+ "cancel", "drain", "uncharge", "unbless", "uncurse",
+ "disenchant", "degrade", "dilute", "erase", "burn",
+ "neutralize", "destroy", "splatter", "bite", "open",
+ "break the lock on", "rust", "rot", "tarnish"
};
/* possibly bill for an object which the player has just modified */
struct monst *shkp = 0;
if (alter_type < 0 || alter_type >= SIZE(alteration_verbs)) {
- impossible("invalid alteration type (%d)", alter_type);
- alter_type = 0;
+ impossible("invalid alteration type (%d)", alter_type);
+ alter_type = 0;
}
ox = oy = 0; /* lint suppression */
objroom = '\0'; /* ditto */
if (carried(obj) || obj->where == OBJ_FREE) {
- /* OBJ_FREE catches obj_no_longer_held()'s transformation
- of crysknife back into worm tooth; the object has been
- removed from inventory but not necessarily placed at
- its new location yet--the unpaid flag will still be set
- if this item is owned by a shop */
- if (!obj->unpaid) return;
+ /* OBJ_FREE catches obj_no_longer_held()'s transformation
+ of crysknife back into worm tooth; the object has been
+ removed from inventory but not necessarily placed at
+ its new location yet--the unpaid flag will still be set
+ if this item is owned by a shop */
+ if (!obj->unpaid) return;
} else {
- /* this get_obj_location shouldn't fail, but if it does,
- use hero's location */
- if (!get_obj_location(obj, &ox, &oy, CONTAINED_TOO))
- ox = u.ux, oy = u.uy;
- if (!costly_spot(ox, oy)) return;
- objroom = *in_rooms(ox, oy, SHOPBASE);
- /* if no shop cares about it, we're done */
- if (!billable(&shkp, obj, objroom, FALSE)) return;
+ /* this get_obj_location shouldn't fail, but if it does,
+ use hero's location */
+ if (!get_obj_location(obj, &ox, &oy, CONTAINED_TOO))
+ ox = u.ux, oy = u.uy;
+ if (!costly_spot(ox, oy)) return;
+ objroom = *in_rooms(ox, oy, SHOPBASE);
+ /* if no shop cares about it, we're done */
+ if (!billable(&shkp, obj, objroom, FALSE)) return;
}
if (obj->quan == 1L)
- those = "that", them = "it";
+ those = "that", them = "it";
else
- those = "those", them = "them";
+ those = "those", them = "them";
/* when shopkeeper describes the object as being uncursed or unblessed
hero will know that it is now uncursed; will also make the feedback
switch (obj->where) {
case OBJ_FREE: /* obj_no_longer_held() */
case OBJ_INVENT:
- if (set_bknown) obj->bknown = 1;
- verbalize("You %s %s %s, you pay for %s!",
- alteration_verbs[alter_type], those,
- simpleonames(obj), them);
- bill_dummy_object(obj);
- break;
+ if (set_bknown) obj->bknown = 1;
+ verbalize("You %s %s %s, you pay for %s!",
+ alteration_verbs[alter_type], those,
+ simpleonames(obj), them);
+ bill_dummy_object(obj);
+ break;
case OBJ_FLOOR:
- if (set_bknown) obj->bknown = 1;
- if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) {
- verbalize("You %s %s, you pay for %s!",
- alteration_verbs[alter_type], those, them);
- bill_dummy_object(obj);
- } else {
- (void) stolen_value(obj, ox, oy, FALSE, FALSE);
- }
- break;
+ if (set_bknown) obj->bknown = 1;
+ if (costly_spot(u.ux, u.uy) && objroom == *u.ushops) {
+ verbalize("You %s %s, you pay for %s!",
+ alteration_verbs[alter_type], those, them);
+ bill_dummy_object(obj);
+ } else {
+ (void) stolen_value(obj, ox, oy, FALSE, FALSE);
+ }
+ break;
}
}
static const char dknowns[] = {
- WAND_CLASS, RING_CLASS, POTION_CLASS, SCROLL_CLASS,
- GEM_CLASS, SPBOOK_CLASS, WEAPON_CLASS, TOOL_CLASS, 0
+ WAND_CLASS, RING_CLASS, POTION_CLASS, SCROLL_CLASS,
+ GEM_CLASS, SPBOOK_CLASS, WEAPON_CLASS, TOOL_CLASS, 0
};
struct obj *
boolean init;
boolean artif;
{
- int mndx, tryct;
- struct obj *otmp;
- char let = objects[otyp].oc_class;
-
- otmp = newobj();
- *otmp = zeroobj;
- otmp->age = monstermoves;
- otmp->o_id = context.ident++;
- if (!otmp->o_id) otmp->o_id = context.ident++; /* ident overflowed */
- otmp->quan = 1L;
- otmp->oclass = let;
- otmp->otyp = otyp;
- otmp->where = OBJ_FREE;
- otmp->dknown = index(dknowns, let) ? 0 : 1;
- if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD) ||
- otmp->otyp == SHIELD_OF_REFLECTION)
- otmp->dknown = 0;
- if (!objects[otmp->otyp].oc_uses_known)
- otmp->known = 1;
- otmp->lknown = 0;
- otmp->cknown = 0;
- otmp->corpsenm = NON_PM;
-
- if (init) switch (let) {
- case WEAPON_CLASS:
- otmp->quan = is_multigen(otmp) ? (long) rn1(6,6) : 1L;
- if(!rn2(11)) {
- otmp->spe = rne(3);
- otmp->blessed = rn2(2);
- } else if(!rn2(10)) {
- curse(otmp);
- otmp->spe = -rne(3);
- } else blessorcurse(otmp, 10);
- if (is_poisonable(otmp) && !rn2(100))
- otmp->opoisoned = 1;
-
- if (artif && !rn2(20))
- otmp = mk_artifact(otmp, (aligntyp)A_NONE);
- break;
- case FOOD_CLASS:
- otmp->oeaten = 0;
+ int mndx, tryct;
+ struct obj *otmp;
+ char let = objects[otyp].oc_class;
+
+ otmp = newobj();
+ *otmp = zeroobj;
+ otmp->age = monstermoves;
+ otmp->o_id = context.ident++;
+ if (!otmp->o_id) otmp->o_id = context.ident++; /* ident overflowed */
+ otmp->quan = 1L;
+ otmp->oclass = let;
+ otmp->otyp = otyp;
+ otmp->where = OBJ_FREE;
+ otmp->dknown = index(dknowns, let) ? 0 : 1;
+ if ((otmp->otyp >= ELVEN_SHIELD && otmp->otyp <= ORCISH_SHIELD) ||
+ otmp->otyp == SHIELD_OF_REFLECTION)
+ otmp->dknown = 0;
+ if (!objects[otmp->otyp].oc_uses_known)
+ otmp->known = 1;
+ otmp->lknown = 0;
+ otmp->cknown = 0;
+ otmp->corpsenm = NON_PM;
+
+ if (init) switch (let) {
+ case WEAPON_CLASS:
+ otmp->quan = is_multigen(otmp) ? (long) rn1(6,6) : 1L;
+ if(!rn2(11)) {
+ otmp->spe = rne(3);
+ otmp->blessed = rn2(2);
+ } else if(!rn2(10)) {
+ curse(otmp);
+ otmp->spe = -rne(3);
+ } else blessorcurse(otmp, 10);
+ if (is_poisonable(otmp) && !rn2(100))
+ otmp->opoisoned = 1;
+
+ if (artif && !rn2(20))
+ otmp = mk_artifact(otmp, (aligntyp)A_NONE);
+ break;
+ case FOOD_CLASS:
+ otmp->oeaten = 0;
switch(otmp->otyp) {
case CORPSE:
/* possibly overridden by mkcorpstat() */
otmp->quan = (long) rnd(2);
break;
}
- if (Is_pudding(otmp)) {
- otmp->oglobby = 1;
- } else if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING
+ if (Is_pudding(otmp)) {
+ otmp->globby = 1;
+ otmp->known = otmp->bknown = otmp->rknown = otmp->dknown = 1;
+ /* this ensures that they don't fail merging because of
+ * BUC status or other irrelevancies */
+ } else {
+ if (otmp->otyp != CORPSE && otmp->otyp != MEAT_RING
&& otmp->otyp != KELP_FROND && !rn2(6)) {
- otmp->quan = 2L;
+ otmp->quan = 2L;
+ }
+ }
+ break;
+ case GEM_CLASS:
+ otmp->corpsenm = 0; /* LOADSTONE hack */
+ if (otmp->otyp == LOADSTONE) curse(otmp);
+ else if (otmp->otyp == ROCK) otmp->quan = (long) rn1(6,6);
+ else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2L;
+ else otmp->quan = 1L;
+ break;
+ case TOOL_CLASS:
+ switch(otmp->otyp) {
+ case TALLOW_CANDLE:
+ case WAX_CANDLE: otmp->spe = 1;
+ otmp->age = 20L * /* 400 or 200 */
+ (long)objects[otmp->otyp].oc_cost;
+ otmp->lamplit = 0;
+ otmp->quan = 1L +
+ (long)(rn2(2) ? rn2(7) : 0);
+ blessorcurse(otmp, 5);
+ break;
+ case BRASS_LANTERN:
+ case OIL_LAMP: otmp->spe = 1;
+ otmp->age = (long) rn1(500,1000);
+ otmp->lamplit = 0;
+ blessorcurse(otmp, 5);
+ break;
+ case MAGIC_LAMP: otmp->spe = 1;
+ otmp->lamplit = 0;
+ blessorcurse(otmp, 2);
+ break;
+ case CHEST:
+ case LARGE_BOX: otmp->olocked = !!(rn2(5));
+ otmp->otrapped = !(rn2(10));
+ case ICE_BOX:
+ case SACK:
+ case OILSKIN_SACK:
+ case BAG_OF_HOLDING: mkbox_cnts(otmp);
+ break;
+ case LEASH: otmp->leashmon = 0;
+ break;
+ case EXPENSIVE_CAMERA:
+ case TINNING_KIT:
+ case MAGIC_MARKER: otmp->spe = rn1(70,30);
+ break;
+ case CAN_OF_GREASE: otmp->spe = rnd(25);
+ blessorcurse(otmp, 10);
+ break;
+ case CRYSTAL_BALL: otmp->spe = rnd(5);
+ blessorcurse(otmp, 2);
+ break;
+ case HORN_OF_PLENTY:
+ case BAG_OF_TRICKS: otmp->spe = rnd(20);
+ break;
+ case FIGURINE: { int tryct2 = 0;
+ do
+ otmp->corpsenm = rndmonnum();
+ while(is_human(&mons[otmp->corpsenm])
+ && tryct2++ < 30);
+ blessorcurse(otmp, 4);
+ break;
+ }
+ case BELL_OF_OPENING: otmp->spe = 3;
+ break;
+ case MAGIC_FLUTE:
+ case MAGIC_HARP:
+ case FROST_HORN:
+ case FIRE_HORN:
+ case DRUM_OF_EARTHQUAKE:
+ otmp->spe = rn1(5,4);
+ break;
}
- break;
- case GEM_CLASS:
- otmp->corpsenm = 0; /* LOADSTONE hack */
- if (otmp->otyp == LOADSTONE) curse(otmp);
- else if (otmp->otyp == ROCK) otmp->quan = (long) rn1(6,6);
- else if (otmp->otyp != LUCKSTONE && !rn2(6)) otmp->quan = 2L;
- else otmp->quan = 1L;
- break;
- case TOOL_CLASS:
- switch(otmp->otyp) {
- case TALLOW_CANDLE:
- case WAX_CANDLE: otmp->spe = 1;
- otmp->age = 20L * /* 400 or 200 */
- (long)objects[otmp->otyp].oc_cost;
- otmp->lamplit = 0;
- otmp->quan = 1L +
- (long)(rn2(2) ? rn2(7) : 0);
- blessorcurse(otmp, 5);
- break;
- case BRASS_LANTERN:
- case OIL_LAMP: otmp->spe = 1;
- otmp->age = (long) rn1(500,1000);
- otmp->lamplit = 0;
- blessorcurse(otmp, 5);
- break;
- case MAGIC_LAMP: otmp->spe = 1;
- otmp->lamplit = 0;
- blessorcurse(otmp, 2);
- break;
- case CHEST:
- case LARGE_BOX: otmp->olocked = !!(rn2(5));
- otmp->otrapped = !(rn2(10));
- case ICE_BOX:
- case SACK:
- case OILSKIN_SACK:
- case BAG_OF_HOLDING: mkbox_cnts(otmp);
- break;
- case LEASH: otmp->leashmon = 0;
- break;
- case EXPENSIVE_CAMERA:
- case TINNING_KIT:
- case MAGIC_MARKER: otmp->spe = rn1(70,30);
- break;
- case CAN_OF_GREASE: otmp->spe = rnd(25);
- blessorcurse(otmp, 10);
- break;
- case CRYSTAL_BALL: otmp->spe = rnd(5);
- blessorcurse(otmp, 2);
- break;
- case HORN_OF_PLENTY:
- case BAG_OF_TRICKS: otmp->spe = rnd(20);
- break;
- case FIGURINE: { int tryct2 = 0;
- do
- otmp->corpsenm = rndmonnum();
- while(is_human(&mons[otmp->corpsenm])
- && tryct2++ < 30);
- blessorcurse(otmp, 4);
- break;
- }
- case BELL_OF_OPENING: otmp->spe = 3;
- break;
- case MAGIC_FLUTE:
- case MAGIC_HARP:
- case FROST_HORN:
- case FIRE_HORN:
- case DRUM_OF_EARTHQUAKE:
- otmp->spe = rn1(5,4);
- break;
- }
- break;
- case AMULET_CLASS:
- if (otmp->otyp == AMULET_OF_YENDOR) context.made_amulet = TRUE;
- if(rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION ||
- otmp->otyp == AMULET_OF_CHANGE ||
- otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) {
- curse(otmp);
- } else blessorcurse(otmp, 10);
- case VENOM_CLASS:
- case CHAIN_CLASS:
- case BALL_CLASS:
- break;
- case POTION_CLASS:
- otmp->fromsink = 0;
- if (otmp->otyp == POT_OIL)
- otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */
- /* fall through */
- case SCROLL_CLASS:
+ break;
+ case AMULET_CLASS:
+ if (otmp->otyp == AMULET_OF_YENDOR) context.made_amulet = TRUE;
+ if(rn2(10) && (otmp->otyp == AMULET_OF_STRANGULATION ||
+ otmp->otyp == AMULET_OF_CHANGE ||
+ otmp->otyp == AMULET_OF_RESTFUL_SLEEP)) {
+ curse(otmp);
+ } else blessorcurse(otmp, 10);
+ case VENOM_CLASS:
+ case CHAIN_CLASS:
+ case BALL_CLASS:
+ break;
+ case POTION_CLASS:
+ otmp->fromsink = 0;
+ if (otmp->otyp == POT_OIL)
+ otmp->age = MAX_OIL_IN_FLASK; /* amount of oil */
+ /* fall through */
+ case SCROLL_CLASS:
#ifdef MAIL
- if (otmp->otyp != SCR_MAIL)
+ if (otmp->otyp != SCR_MAIL)
#endif
- blessorcurse(otmp, 4);
- break;
- case SPBOOK_CLASS:
- otmp->spestudied = 0;
- blessorcurse(otmp, 17);
- break;
- case ARMOR_CLASS:
- if(rn2(10) && (otmp->otyp == FUMBLE_BOOTS ||
- otmp->otyp == LEVITATION_BOOTS ||
- otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT ||
- otmp->otyp == GAUNTLETS_OF_FUMBLING ||
- !rn2(11))) {
- curse(otmp);
- otmp->spe = -rne(3);
- } else if(!rn2(10)) {
- otmp->blessed = rn2(2);
- otmp->spe = rne(3);
- } else blessorcurse(otmp, 10);
- if (artif && !rn2(40))
- otmp = mk_artifact(otmp, (aligntyp)A_NONE);
- /* simulate lacquered armor for samurai */
- if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL &&
- (moves <= 1 || In_quest(&u.uz))) {
+ blessorcurse(otmp, 4);
+ break;
+ case SPBOOK_CLASS:
+ otmp->spestudied = 0;
+ blessorcurse(otmp, 17);
+ break;
+ case ARMOR_CLASS:
+ if(rn2(10) && (otmp->otyp == FUMBLE_BOOTS ||
+ otmp->otyp == LEVITATION_BOOTS ||
+ otmp->otyp == HELM_OF_OPPOSITE_ALIGNMENT ||
+ otmp->otyp == GAUNTLETS_OF_FUMBLING ||
+ !rn2(11))) {
+ curse(otmp);
+ otmp->spe = -rne(3);
+ } else if(!rn2(10)) {
+ otmp->blessed = rn2(2);
+ otmp->spe = rne(3);
+ } else blessorcurse(otmp, 10);
+ if (artif && !rn2(40))
+ otmp = mk_artifact(otmp, (aligntyp)A_NONE);
+ /* simulate lacquered armor for samurai */
+ if (Role_if(PM_SAMURAI) && otmp->otyp == SPLINT_MAIL &&
+ (moves <= 1 || In_quest(&u.uz))) {
#ifdef UNIXPC
- /* optimizer bitfield bug */
- otmp->oerodeproof = 1;
- otmp->rknown = 1;
+ /* optimizer bitfield bug */
+ otmp->oerodeproof = 1;
+ otmp->rknown = 1;
#else
- otmp->oerodeproof = otmp->rknown = 1;
+ otmp->oerodeproof = otmp->rknown = 1;
#endif
- }
- break;
- case WAND_CLASS:
- if(otmp->otyp == WAN_WISHING) otmp->spe = rnd(3); else
- otmp->spe = rn1(5,
- (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
- blessorcurse(otmp, 17);
- otmp->recharged = 0; /* used to control recharging */
- break;
- case RING_CLASS:
- if(objects[otmp->otyp].oc_charged) {
- blessorcurse(otmp, 3);
- if(rn2(10)) {
- if(rn2(10) && bcsign(otmp))
- otmp->spe = bcsign(otmp) * rne(3);
- else otmp->spe = rn2(2) ? rne(3) : -rne(3);
- }
- /* make useless +0 rings much less common */
- if (otmp->spe == 0) otmp->spe = rn2(4) - rn2(3);
- /* negative rings are usually cursed */
- if (otmp->spe < 0 && rn2(5)) curse(otmp);
- } else if(rn2(10) && (otmp->otyp == RIN_TELEPORTATION ||
- otmp->otyp == RIN_POLYMORPH ||
- otmp->otyp == RIN_AGGRAVATE_MONSTER ||
- otmp->otyp == RIN_HUNGER || !rn2(9))) {
- curse(otmp);
- }
- break;
- case ROCK_CLASS:
- switch (otmp->otyp) {
- case STATUE:
- /* possibly overridden by mkcorpstat() */
- otmp->corpsenm = rndmonnum();
- if (!verysmall(&mons[otmp->corpsenm]) &&
- rn2(level_difficulty()/2 + 10) > 10)
- (void) add_to_container(otmp,
- mkobj(SPBOOK_CLASS,FALSE));
- }
- break;
- case COIN_CLASS:
- break; /* do nothing */
- default:
- impossible("impossible mkobj %d, sym '%c'.", otmp->otyp,
- objects[otmp->otyp].oc_class);
- return (struct obj *)0;
- }
-
- /* some things must get done (corpsenm, timers) even if init = 0 */
- switch (otmp->otyp) {
- case CORPSE:
- if (otmp->corpsenm == NON_PM) {
- otmp->corpsenm = undead_to_corpse(rndmonnum());
- if (mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE|G_GONE))
- otmp->corpsenm = urole.malenum;
- }
- /*FALLTHRU*/
- case STATUE:
- case FIGURINE:
- if (otmp->corpsenm == NON_PM) otmp->corpsenm = rndmonnum();
- /*FALLTHRU*/
- case EGG:
- /* case TIN: */
- set_corpsenm(otmp, otmp->corpsenm);
- break;
- }
-
- /* unique objects may have an associated artifact entry */
- if (objects[otyp].oc_unique && !otmp->oartifact)
- otmp = mk_artifact(otmp, (aligntyp)A_NONE);
- otmp->owt = weight(otmp);
- return(otmp);
+ }
+ break;
+ case WAND_CLASS:
+ if(otmp->otyp == WAN_WISHING) otmp->spe = rnd(3); else
+ otmp->spe = rn1(5,
+ (objects[otmp->otyp].oc_dir == NODIR) ? 11 : 4);
+ blessorcurse(otmp, 17);
+ otmp->recharged = 0; /* used to control recharging */
+ break;
+ case RING_CLASS:
+ if(objects[otmp->otyp].oc_charged) {
+ blessorcurse(otmp, 3);
+ if(rn2(10)) {
+ if(rn2(10) && bcsign(otmp))
+ otmp->spe = bcsign(otmp) * rne(3);
+ else otmp->spe = rn2(2) ? rne(3) : -rne(3);
+ }
+ /* make useless +0 rings much less common */
+ if (otmp->spe == 0) otmp->spe = rn2(4) - rn2(3);
+ /* negative rings are usually cursed */
+ if (otmp->spe < 0 && rn2(5)) curse(otmp);
+ } else if(rn2(10) && (otmp->otyp == RIN_TELEPORTATION ||
+ otmp->otyp == RIN_POLYMORPH ||
+ otmp->otyp == RIN_AGGRAVATE_MONSTER ||
+ otmp->otyp == RIN_HUNGER || !rn2(9))) {
+ curse(otmp);
+ }
+ break;
+ case ROCK_CLASS:
+ switch (otmp->otyp) {
+ case STATUE:
+ /* possibly overridden by mkcorpstat() */
+ otmp->corpsenm = rndmonnum();
+ if (!verysmall(&mons[otmp->corpsenm]) &&
+ rn2(level_difficulty()/2 + 10) > 10)
+ (void) add_to_container(otmp,
+ mkobj(SPBOOK_CLASS,FALSE));
+ }
+ break;
+ case COIN_CLASS:
+ break; /* do nothing */
+ default:
+ impossible("impossible mkobj %d, sym '%c'.", otmp->otyp,
+ objects[otmp->otyp].oc_class);
+ return (struct obj *)0;
+ }
+
+ /* some things must get done (corpsenm, timers) even if init = 0 */
+ switch (otmp->otyp) {
+ case CORPSE:
+ if (otmp->corpsenm == NON_PM) {
+ otmp->corpsenm = undead_to_corpse(rndmonnum());
+ if (mvitals[otmp->corpsenm].mvflags & (G_NOCORPSE|G_GONE))
+ otmp->corpsenm = urole.malenum;
+ }
+ /*FALLTHRU*/
+ case STATUE:
+ case FIGURINE:
+ if (otmp->corpsenm == NON_PM) otmp->corpsenm = rndmonnum();
+ /*FALLTHRU*/
+ case EGG:
+ /* case TIN: */
+ set_corpsenm(otmp, otmp->corpsenm);
+ break;
+ }
+
+ /* unique objects may have an associated artifact entry */
+ if (objects[otyp].oc_unique && !otmp->oartifact)
+ otmp = mk_artifact(otmp, (aligntyp)A_NONE);
+ otmp->owt = weight(otmp);
+ return(otmp);
}
/*
struct obj *obj;
int id;
{
- long when = 0L;
-
- if (obj->timed) {
- if (obj->otyp == EGG)
- when = stop_timer(HATCH_EGG, obj_to_any(obj));
- else {
- when = 0L;
- obj_stop_timers(obj); /* corpse or figurine */
- }
- }
- obj->corpsenm = id;
- switch(obj->otyp) {
- case CORPSE:
- start_corpse_timeout(obj);
- obj->owt = weight(obj);
- break;
- case FIGURINE:
- if (obj->corpsenm != NON_PM
- && !dead_species(obj->corpsenm,TRUE)
- && (carried(obj) || mcarried(obj)))
- attach_fig_transform_timeout(obj);
- obj->owt = weight(obj);
- break;
- case EGG:
- if (obj->corpsenm != NON_PM
- && !dead_species(obj->corpsenm,TRUE))
- attach_egg_hatch_timeout(obj, when);
- break;
- default: /* tin, etc. */
- obj->owt = weight(obj);
- break;
- }
+ long when = 0L;
+
+ if (obj->timed) {
+ if (obj->otyp == EGG)
+ when = stop_timer(HATCH_EGG, obj_to_any(obj));
+ else {
+ when = 0L;
+ obj_stop_timers(obj); /* corpse or figurine */
+ }
+ }
+ obj->corpsenm = id;
+ switch(obj->otyp) {
+ case CORPSE:
+ start_corpse_timeout(obj);
+ obj->owt = weight(obj);
+ break;
+ case FIGURINE:
+ if (obj->corpsenm != NON_PM
+ && !dead_species(obj->corpsenm,TRUE)
+ && (carried(obj) || mcarried(obj)))
+ attach_fig_transform_timeout(obj);
+ obj->owt = weight(obj);
+ break;
+ case EGG:
+ if (obj->corpsenm != NON_PM
+ && !dead_species(obj->corpsenm,TRUE))
+ attach_egg_hatch_timeout(obj, when);
+ break;
+ default: /* tin, etc. */
+ obj->owt = weight(obj);
+ break;
+ }
}
/*
*/
void
start_corpse_timeout(body)
- struct obj *body;
+ struct obj *body;
{
- long when; /* rot away when this old */
- long corpse_age; /* age of corpse */
- int rot_adjust;
- short action;
+ long when; /* rot away when this old */
+ long corpse_age; /* age of corpse */
+ int rot_adjust;
+ short action;
#define TAINT_AGE (50L) /* age when corpses go bad */
#define TROLL_REVIVE_CHANCE 37 /* 1/37 chance for 50 turns ~ 75% chance */
#define ROT_AGE (250L) /* age when corpses rot away */
- /* lizards and lichen don't rot or revive */
- if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN) return;
-
- action = ROT_CORPSE; /* default action: rot away */
- rot_adjust = in_mklev ? 25 : 10; /* give some variation */
- corpse_age = monstermoves - body->age;
- if (corpse_age > ROT_AGE)
- when = rot_adjust;
- else
- when = ROT_AGE - corpse_age;
- when += (long)(rnz(rot_adjust) - rot_adjust);
-
- if (is_rider(&mons[body->corpsenm])) {
- /*
- * Riders always revive. They have a 1/3 chance per turn
- * of reviving after 12 turns. Always revive by 500.
- */
- action = REVIVE_MON;
- for (when = 12L; when < 500L; when++)
- if (!rn2(3)) break;
-
- } else if (mons[body->corpsenm].mlet == S_TROLL && !body->norevive) {
- long age;
- for (age = 2; age <= TAINT_AGE; age++)
- if (!rn2(TROLL_REVIVE_CHANCE)) { /* troll revives */
- action = REVIVE_MON;
- when = age;
- break;
- }
- }
-
- if (body->norevive) body->norevive = 0;
- (void) start_timer(when, TIMER_OBJECT, action, obj_to_any(body));
+ /* lizards and lichen don't rot or revive */
+ if (body->corpsenm == PM_LIZARD || body->corpsenm == PM_LICHEN) return;
+
+ action = ROT_CORPSE; /* default action: rot away */
+ rot_adjust = in_mklev ? 25 : 10; /* give some variation */
+ corpse_age = monstermoves - body->age;
+ if (corpse_age > ROT_AGE)
+ when = rot_adjust;
+ else
+ when = ROT_AGE - corpse_age;
+ when += (long)(rnz(rot_adjust) - rot_adjust);
+
+ if (is_rider(&mons[body->corpsenm])) {
+ /*
+ * Riders always revive. They have a 1/3 chance per turn
+ * of reviving after 12 turns. Always revive by 500.
+ */
+ action = REVIVE_MON;
+ for (when = 12L; when < 500L; when++)
+ if (!rn2(3)) break;
+
+ } else if (mons[body->corpsenm].mlet == S_TROLL && !body->norevive) {
+ long age;
+ for (age = 2; age <= TAINT_AGE; age++)
+ if (!rn2(TROLL_REVIVE_CHANCE)) { /* troll revives */
+ action = REVIVE_MON;
+ when = age;
+ break;
+ }
+ }
+
+ if (body->norevive) body->norevive = 0;
+ (void) start_timer(when, TIMER_OBJECT, action, obj_to_any(body));
}
STATIC_OVL void
struct obj *obj;
int old_range;
{
- char buf[BUFSZ];
- xchar ox, oy;
- int new_range = arti_light_radius(obj),
- delta = new_range - old_range;
-
- /* radius of light emitting artifact varies by curse/bless state
- so will change after blessing or cursing */
- if (delta) {
- obj_adjust_light_radius(obj, new_range);
- /* simplifying assumptions: hero is wielding this object;
- artifacts have to be in use to emit light and monsters'
- gear won't change bless or curse state */
- if (!Blind && get_obj_location(obj, &ox, &oy, 0)) {
- *buf = '\0';
- if (iflags.last_msg == PLNMSG_OBJ_GLOWS)
- /* we just saw "The <obj> glows <color>." from dipping */
- Strcpy(buf, (obj->quan == 1L) ? "It" : "They");
- else if (carried(obj) || cansee(ox, oy))
- Strcpy(buf, Yname2(obj));
- if (*buf) {
- /* initial activation says "dimly" if cursed,
- "brightly" if uncursed, and "brilliantly" if blessed;
- when changing intensity, using "less brightly" is
- straightforward for dimming, but we need "brighter"
- rather than "more brightly" for brightening; ugh */
- pline("%s %s %s%s.",
- buf, otense(obj, "shine"),
- (abs(delta) > 1) ? "much " : "",
- (delta > 0) ? "brighter" : "less brightly");
- }
- }
- }
+ char buf[BUFSZ];
+ xchar ox, oy;
+ int new_range = arti_light_radius(obj),
+ delta = new_range - old_range;
+
+ /* radius of light emitting artifact varies by curse/bless state
+ so will change after blessing or cursing */
+ if (delta) {
+ obj_adjust_light_radius(obj, new_range);
+ /* simplifying assumptions: hero is wielding this object;
+ artifacts have to be in use to emit light and monsters'
+ gear won't change bless or curse state */
+ if (!Blind && get_obj_location(obj, &ox, &oy, 0)) {
+ *buf = '\0';
+ if (iflags.last_msg == PLNMSG_OBJ_GLOWS)
+ /* we just saw "The <obj> glows <color>." from dipping */
+ Strcpy(buf, (obj->quan == 1L) ? "It" : "They");
+ else if (carried(obj) || cansee(ox, oy))
+ Strcpy(buf, Yname2(obj));
+ if (*buf) {
+ /* initial activation says "dimly" if cursed,
+ "brightly" if uncursed, and "brilliantly" if blessed;
+ when changing intensity, using "less brightly" is
+ straightforward for dimming, but we need "brighter"
+ rather than "more brightly" for brightening; ugh */
+ pline("%s %s %s%s.",
+ buf, otense(obj, "shine"),
+ (abs(delta) > 1) ? "much " : "",
+ (delta > 0) ? "brighter" : "less brightly");
+ }
+ }
+ }
}
/*
bless(otmp)
register struct obj *otmp;
{
- int old_light = 0;
+ int old_light = 0;
- if (otmp->oclass == COIN_CLASS) return;
- if (otmp->lamplit) old_light = arti_light_radius(otmp);
- otmp->cursed = 0;
- otmp->blessed = 1;
- if (carried(otmp) && confers_luck(otmp))
- set_moreluck();
- else if (otmp->otyp == BAG_OF_HOLDING)
- otmp->owt = weight(otmp);
- else if (otmp->otyp == FIGURINE && otmp->timed)
- (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
- if (otmp->lamplit) maybe_adjust_light(otmp, old_light);
- return;
+ if (otmp->oclass == COIN_CLASS) return;
+ if (otmp->lamplit) old_light = arti_light_radius(otmp);
+ otmp->cursed = 0;
+ otmp->blessed = 1;
+ if (carried(otmp) && confers_luck(otmp))
+ set_moreluck();
+ else if (otmp->otyp == BAG_OF_HOLDING)
+ otmp->owt = weight(otmp);
+ else if (otmp->otyp == FIGURINE && otmp->timed)
+ (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
+ if (otmp->lamplit) maybe_adjust_light(otmp, old_light);
+ return;
}
void
unbless(otmp)
register struct obj *otmp;
{
- int old_light = 0;
+ int old_light = 0;
- if (otmp->lamplit) old_light = arti_light_radius(otmp);
- otmp->blessed = 0;
- if (carried(otmp) && confers_luck(otmp))
- set_moreluck();
- else if (otmp->otyp == BAG_OF_HOLDING)
- otmp->owt = weight(otmp);
- if (otmp->lamplit) maybe_adjust_light(otmp, old_light);
+ if (otmp->lamplit) old_light = arti_light_radius(otmp);
+ otmp->blessed = 0;
+ if (carried(otmp) && confers_luck(otmp))
+ set_moreluck();
+ else if (otmp->otyp == BAG_OF_HOLDING)
+ otmp->owt = weight(otmp);
+ if (otmp->lamplit) maybe_adjust_light(otmp, old_light);
}
void
curse(otmp)
register struct obj *otmp;
{
- int old_light = 0;
-
- if (otmp->oclass == COIN_CLASS) return;
- if (otmp->lamplit) old_light = arti_light_radius(otmp);
- otmp->blessed = 0;
- otmp->cursed = 1;
- /* welded two-handed weapon interferes with some armor removal */
- if (otmp == uwep && bimanual(uwep)) reset_remarm();
- /* rules at top of wield.c state that twoweapon cannot be done
- with cursed alternate weapon */
- if (otmp == uswapwep && u.twoweap)
- drop_uswapwep();
- /* some cursed items need immediate updating */
- if (carried(otmp) && confers_luck(otmp))
- set_moreluck();
- else if (otmp->otyp == BAG_OF_HOLDING)
- otmp->owt = weight(otmp);
- else if (otmp->otyp == FIGURINE) {
- if (otmp->corpsenm != NON_PM
- && !dead_species(otmp->corpsenm,TRUE)
- && (carried(otmp) || mcarried(otmp)))
- attach_fig_transform_timeout(otmp);
- }
- if (otmp->lamplit) maybe_adjust_light(otmp, old_light);
- return;
+ int old_light = 0;
+
+ if (otmp->oclass == COIN_CLASS) return;
+ if (otmp->lamplit) old_light = arti_light_radius(otmp);
+ otmp->blessed = 0;
+ otmp->cursed = 1;
+ /* welded two-handed weapon interferes with some armor removal */
+ if (otmp == uwep && bimanual(uwep)) reset_remarm();
+ /* rules at top of wield.c state that twoweapon cannot be done
+ with cursed alternate weapon */
+ if (otmp == uswapwep && u.twoweap)
+ drop_uswapwep();
+ /* some cursed items need immediate updating */
+ if (carried(otmp) && confers_luck(otmp))
+ set_moreluck();
+ else if (otmp->otyp == BAG_OF_HOLDING)
+ otmp->owt = weight(otmp);
+ else if (otmp->otyp == FIGURINE) {
+ if (otmp->corpsenm != NON_PM
+ && !dead_species(otmp->corpsenm,TRUE)
+ && (carried(otmp) || mcarried(otmp)))
+ attach_fig_transform_timeout(otmp);
+ }
+ if (otmp->lamplit) maybe_adjust_light(otmp, old_light);
+ return;
}
void
uncurse(otmp)
register struct obj *otmp;
{
- int old_light = 0;
+ int old_light = 0;
- if (otmp->lamplit) old_light = arti_light_radius(otmp);
- otmp->cursed = 0;
- if (carried(otmp) && confers_luck(otmp))
- set_moreluck();
- else if (otmp->otyp == BAG_OF_HOLDING)
- otmp->owt = weight(otmp);
- else if (otmp->otyp == FIGURINE && otmp->timed)
- (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
- if (otmp->lamplit) maybe_adjust_light(otmp, old_light);
- return;
+ if (otmp->lamplit) old_light = arti_light_radius(otmp);
+ otmp->cursed = 0;
+ if (carried(otmp) && confers_luck(otmp))
+ set_moreluck();
+ else if (otmp->otyp == BAG_OF_HOLDING)
+ otmp->owt = weight(otmp);
+ else if (otmp->otyp == FIGURINE && otmp->timed)
+ (void) stop_timer(FIG_TRANSFORM, obj_to_any(otmp));
+ if (otmp->lamplit) maybe_adjust_light(otmp, old_light);
+ return;
}
void
register struct obj *otmp;
register int chance;
{
- if(otmp->blessed || otmp->cursed) return;
+ if(otmp->blessed || otmp->cursed) return;
- if(!rn2(chance)) {
- if(!rn2(2)) {
- curse(otmp);
- } else {
- bless(otmp);
- }
- }
- return;
+ if(!rn2(chance)) {
+ if(!rn2(2)) {
+ curse(otmp);
+ } else {
+ bless(otmp);
+ }
+ }
+ return;
}
int
bcsign(otmp)
register struct obj *otmp;
{
- return(!!otmp->blessed - !!otmp->cursed);
+ return(!!otmp->blessed - !!otmp->cursed);
}
/*
weight(obj)
register struct obj *obj;
{
- int wt = objects[obj->otyp].oc_weight;
-
- if (SchroedingersBox(obj))
- wt += mons[PM_HOUSECAT].cwt;
- if (Is_container(obj) || obj->otyp == STATUE) {
- struct obj *contents;
- register int cwt = 0;
-
- if (obj->otyp == STATUE && obj->corpsenm >= LOW_PM)
- wt = (int)obj->quan *
- ((int)mons[obj->corpsenm].cwt * 3 / 2);
-
- for(contents=obj->cobj; contents; contents=contents->nobj)
- cwt += weight(contents);
- /*
- * The weight of bags of holding is calculated as the weight
- * of the bag plus the weight of the bag's contents modified
- * as follows:
- *
- * Bag status Weight of contents
- * ---------- ------------------
- * cursed 2x
- * blessed x/4 [rounded up: (x+3)/4]
- * otherwise x/2 [rounded up: (x+1)/2]
- *
- * The macro DELTA_CWT in pickup.c also implements these
- * weight equations.
- */
- if (obj->otyp == BAG_OF_HOLDING)
- cwt = obj->cursed ? (cwt * 2) :
- obj->blessed ? ((cwt + 3) / 4) :
- ((cwt + 1) / 2);
-
- return wt + cwt;
- }
- if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) {
- long long_wt = obj->quan * (long) mons[obj->corpsenm].cwt;
-
- wt = (long_wt > LARGEST_INT) ? LARGEST_INT : (int)long_wt;
- if (obj->oeaten) wt = eaten_stat(wt, obj);
- return wt;
- } else if (obj->oclass == FOOD_CLASS && obj->oeaten) {
- return eaten_stat((int)obj->quan * wt, obj);
- } else if (obj->oclass == COIN_CLASS)
- return (int)((obj->quan + 50L) / 100L);
- else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0)
- return((int)(obj->owt)); /* kludge for "very" heavy iron ball */
- return(wt ? wt*(int)obj->quan : ((int)obj->quan + 1)>>1);
+ int wt = objects[obj->otyp].oc_weight;
+
+ if (SchroedingersBox(obj))
+ wt += mons[PM_HOUSECAT].cwt;
+ if (Is_container(obj) || obj->otyp == STATUE) {
+ struct obj *contents;
+ register int cwt = 0;
+
+ if (obj->otyp == STATUE && obj->corpsenm >= LOW_PM)
+ wt = (int)obj->quan *
+ ((int)mons[obj->corpsenm].cwt * 3 / 2);
+
+ for(contents=obj->cobj; contents; contents=contents->nobj)
+ cwt += weight(contents);
+ /*
+ * The weight of bags of holding is calculated as the weight
+ * of the bag plus the weight of the bag's contents modified
+ * as follows:
+ *
+ * Bag status Weight of contents
+ * ---------- ------------------
+ * cursed 2x
+ * blessed x/4 [rounded up: (x+3)/4]
+ * otherwise x/2 [rounded up: (x+1)/2]
+ *
+ * The macro DELTA_CWT in pickup.c also implements these
+ * weight equations.
+ */
+ if (obj->otyp == BAG_OF_HOLDING)
+ cwt = obj->cursed ? (cwt * 2) :
+ obj->blessed ? ((cwt + 3) / 4) :
+ ((cwt + 1) / 2);
+
+ return wt + cwt;
+ }
+ if (obj->otyp == CORPSE && obj->corpsenm >= LOW_PM) {
+ long long_wt = obj->quan * (long) mons[obj->corpsenm].cwt;
+
+ wt = (long_wt > LARGEST_INT) ? LARGEST_INT : (int)long_wt;
+ if (obj->oeaten) wt = eaten_stat(wt, obj);
+ return wt;
+ } else if (obj->oclass == FOOD_CLASS && obj->oeaten) {
+ return eaten_stat((int)obj->quan * wt, obj);
+ } else if (obj->oclass == COIN_CLASS)
+ return (int)((obj->quan + 50L) / 100L);
+ else if (obj->otyp == HEAVY_IRON_BALL && obj->owt != 0)
+ return((int)(obj->owt)); /* kludge for "very" heavy iron ball */
+ return(wt ? wt*(int)obj->quan : ((int)obj->quan + 1)>>1);
}
static int treefruits[] = {APPLE,ORANGE,PEAR,BANANA,EUCALYPTUS_LEAF};
rnd_treefruit_at(x,y)
int x, y;
{
- return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE);
+ return mksobj_at(treefruits[rn2(SIZE(treefruits))], x, y, TRUE, FALSE);
}
struct obj *
register struct obj *gold = g_at(x,y);
if (amount <= 0L)
- amount = (long)(1 + rnd(level_difficulty()+2) * rnd(30));
+ amount = (long)(1 + rnd(level_difficulty()+2) * rnd(30));
if (gold) {
- gold->quan += amount;
+ gold->quan += amount;
} else {
- gold = mksobj_at(GOLD_PIECE, x, y, TRUE, FALSE);
- gold->quan = amount;
+ gold = mksobj_at(GOLD_PIECE, x, y, TRUE, FALSE);
+ gold->quan = amount;
}
gold->owt = weight(gold);
return (gold);
/* return TRUE if the corpse has special timing */
#define special_corpse(num) (((num) == PM_LIZARD) \
- || ((num) == PM_LICHEN) \
- || (is_rider(&mons[num])) \
- || (mons[num].mlet == S_TROLL))
+ || ((num) == PM_LICHEN) \
+ || (is_rider(&mons[num])) \
+ || (mons[num].mlet == S_TROLL))
/*
* OEXTRA note: Passing mtmp causes mtraits to be saved
int x, y;
unsigned corpstatflags;
{
- register struct obj *otmp;
- boolean init = ((corpstatflags & CORPSTAT_INIT) != 0);
-
- if (objtype != CORPSE && objtype != STATUE)
- impossible("making corpstat type %d", objtype);
- if (x == 0 && y == 0) { /* special case - random placement */
- otmp = mksobj(objtype, init, FALSE);
- if (otmp) (void)rloco(otmp);
- } else
- otmp = mksobj_at(objtype, x, y, init, FALSE);
- if (otmp) {
- if (mtmp) {
- struct obj *otmp2;
-
- if (!ptr) ptr = mtmp->data;
- /* save_mtraits frees original data pointed to by otmp */
- otmp2 = save_mtraits(otmp, mtmp);
- if (otmp2) otmp = otmp2;
- }
- /* use the corpse or statue produced by mksobj() as-is
- unless `ptr' is non-null */
- if (ptr) {
- int old_corpsenm = otmp->corpsenm;
-
- otmp->corpsenm = monsndx(ptr);
- otmp->owt = weight(otmp);
- if (otmp->otyp == CORPSE &&
- (special_corpse(old_corpsenm) ||
- special_corpse(otmp->corpsenm))) {
- obj_stop_timers(otmp);
- start_corpse_timeout(otmp);
- }
- }
- }
- return(otmp);
+ register struct obj *otmp;
+ boolean init = ((corpstatflags & CORPSTAT_INIT) != 0);
+
+ if (objtype != CORPSE && objtype != STATUE)
+ impossible("making corpstat type %d", objtype);
+ if (x == 0 && y == 0) { /* special case - random placement */
+ otmp = mksobj(objtype, init, FALSE);
+ if (otmp) (void)rloco(otmp);
+ } else
+ otmp = mksobj_at(objtype, x, y, init, FALSE);
+ if (otmp) {
+ if (mtmp) {
+ struct obj *otmp2;
+
+ if (!ptr) ptr = mtmp->data;
+ /* save_mtraits frees original data pointed to by otmp */
+ otmp2 = save_mtraits(otmp, mtmp);
+ if (otmp2) otmp = otmp2;
+ }
+ /* use the corpse or statue produced by mksobj() as-is
+ unless `ptr' is non-null */
+ if (ptr) {
+ int old_corpsenm = otmp->corpsenm;
+
+ otmp->corpsenm = monsndx(ptr);
+ otmp->owt = weight(otmp);
+ if (otmp->otyp == CORPSE &&
+ (special_corpse(old_corpsenm) ||
+ special_corpse(otmp->corpsenm))) {
+ obj_stop_timers(otmp);
+ start_corpse_timeout(otmp);
+ }
+ }
+ }
+ return(otmp);
}
/*
corpse_revive_type(obj)
struct obj *obj;
{
- int revivetype;
- struct monst *mtmp;
- if (has_omonst(obj) &&
- ((mtmp = get_mtraits(obj, FALSE)) != (struct monst *)0)) {
- /* mtmp is a temporary pointer to a monster's stored
- attributes, not a real monster */
- revivetype = mtmp->mnum;
- } else
- revivetype = obj->corpsenm;
- return revivetype;
+ int revivetype;
+ struct monst *mtmp;
+ if (has_omonst(obj) &&
+ ((mtmp = get_mtraits(obj, FALSE)) != (struct monst *)0)) {
+ /* mtmp is a temporary pointer to a monster's stored
+ attributes, not a real monster */
+ revivetype = mtmp->mnum;
+ } else
+ revivetype = obj->corpsenm;
+ return revivetype;
}
/*
struct obj *obj;
struct monst *mtmp;
{
- if (mtmp->ispriest) forget_temple_entry(mtmp); /* EPRI() */
- if (!has_omonst(obj)) newomonst(obj);
- if (has_omonst(obj)) {
- struct monst *mtmp2 = OMONST(obj);
- *mtmp2 = *mtmp;
- mtmp2->mextra = (struct mextra *)0;
- if (mtmp->data) mtmp2->mnum = monsndx(mtmp->data);
- /* invalidate pointers */
- /* m_id is needed to know if this is a revived quest leader */
- /* but m_id must be cleared when loading bones */
- mtmp2->nmon = (struct monst *)0;
- mtmp2->data = (struct permonst *)0;
- mtmp2->minvent = (struct obj *)0;
- if (mtmp->mextra) copy_mextra(mtmp2, mtmp);
- }
- return obj;
+ if (mtmp->ispriest) forget_temple_entry(mtmp); /* EPRI() */
+ if (!has_omonst(obj)) newomonst(obj);
+ if (has_omonst(obj)) {
+ struct monst *mtmp2 = OMONST(obj);
+ *mtmp2 = *mtmp;
+ mtmp2->mextra = (struct mextra *)0;
+ if (mtmp->data) mtmp2->mnum = monsndx(mtmp->data);
+ /* invalidate pointers */
+ /* m_id is needed to know if this is a revived quest leader */
+ /* but m_id must be cleared when loading bones */
+ mtmp2->nmon = (struct monst *)0;
+ mtmp2->data = (struct permonst *)0;
+ mtmp2->minvent = (struct obj *)0;
+ if (mtmp->mextra) copy_mextra(mtmp2, mtmp);
+ }
+ return obj;
}
/* returns a pointer to a new monst structure based on
struct obj *obj;
boolean copyof;
{
- struct monst *mtmp = (struct monst *)0;
- struct monst *mnew = (struct monst *)0;
-
- if (has_omonst(obj)) mtmp = OMONST(obj);
- if (mtmp) {
- if (copyof) {
- mnew = newmonst();
- *mnew = *mtmp;
- mnew->mextra = (struct mextra *)0;
- if (mtmp->mextra) copy_mextra(mnew, mtmp);
- } else {
- /* Never insert this returned pointer into mon chains! */
- mnew = mtmp;
- }
- }
- return mnew;
+ struct monst *mtmp = (struct monst *)0;
+ struct monst *mnew = (struct monst *)0;
+
+ if (has_omonst(obj)) mtmp = OMONST(obj);
+ if (mtmp) {
+ if (copyof) {
+ mnew = newmonst();
+ *mnew = *mtmp;
+ mnew->mextra = (struct mextra *)0;
+ if (mtmp->mextra) copy_mextra(mnew, mtmp);
+ } else {
+ /* Never insert this returned pointer into mon chains! */
+ mnew = mtmp;
+ }
+ }
+ return mnew;
}
/* make an object named after someone listed in the scoreboard file */
int objtype; /* CORPSE or STATUE */
register int x, y;
{
- register struct obj *otmp, *otmp2;
- boolean initialize_it;
+ register struct obj *otmp, *otmp2;
+ boolean initialize_it;
- /* player statues never contain books */
- initialize_it = (objtype != STATUE);
- if ((otmp = mksobj_at(objtype, x, y, initialize_it, FALSE)) != 0) {
- /* tt_oname will return null if the scoreboard is empty */
- if ((otmp2 = tt_oname(otmp)) != 0) otmp = otmp2;
- }
- return(otmp);
+ /* player statues never contain books */
+ initialize_it = (objtype != STATUE);
+ if ((otmp = mksobj_at(objtype, x, y, initialize_it, FALSE)) != 0) {
+ /* tt_oname will return null if the scoreboard is empty */
+ if ((otmp2 = tt_oname(otmp)) != 0) otmp = otmp2;
+ }
+ return(otmp);
}
/* make a new corpse or statue, uninitialized if a statue (i.e. no books) */
int x, y;
const char *nm;
{
- struct obj *otmp;
- unsigned corpstatflags = (objtype != STATUE) ?
- CORPSTAT_INIT : CORPSTAT_NONE;
+ struct obj *otmp;
+ unsigned corpstatflags = (objtype != STATUE) ?
+ CORPSTAT_INIT : CORPSTAT_NONE;
- otmp = mkcorpstat(objtype, (struct monst *)0, ptr,
- x, y, corpstatflags);
- if (nm)
- otmp = oname(otmp, nm);
- return(otmp);
+ otmp = mkcorpstat(objtype, (struct monst *)0, ptr,
+ x, y, corpstatflags);
+ if (nm)
+ otmp = oname(otmp, nm);
+ return(otmp);
}
boolean
is_flammable(otmp)
register struct obj *otmp;
{
- int otyp = otmp->otyp;
- int omat = objects[otyp].oc_material;
+ int otyp = otmp->otyp;
+ int omat = objects[otyp].oc_material;
- /* Candles can be burned, but they're not flammable in the sense that
- * they can't get fire damage and it makes no sense for them to be
- * fireproofed.
- */
- if (Is_candle(otmp))
- return FALSE;
+ /* Candles can be burned, but they're not flammable in the sense that
+ * they can't get fire damage and it makes no sense for them to be
+ * fireproofed.
+ */
+ if (Is_candle(otmp))
+ return FALSE;
- if (objects[otyp].oc_oprop == FIRE_RES || otyp == WAN_FIRE)
- return FALSE;
+ if (objects[otyp].oc_oprop == FIRE_RES || otyp == WAN_FIRE)
+ return FALSE;
- return((boolean)((omat <= WOOD && omat != LIQUID) || omat == PLASTIC));
+ return((boolean)((omat <= WOOD && omat != LIQUID) || omat == PLASTIC));
}
boolean
is_rottable(otmp)
register struct obj *otmp;
{
- int otyp = otmp->otyp;
+ int otyp = otmp->otyp;
- return((boolean)(objects[otyp].oc_material <= WOOD &&
- objects[otyp].oc_material != LIQUID));
+ return((boolean)(objects[otyp].oc_material <= WOOD &&
+ objects[otyp].oc_material != LIQUID));
}
/*
register struct obj *otmp2 = level.objects[x][y];
if (otmp->where != OBJ_FREE)
- panic("place_object: obj not free");
+ panic("place_object: obj not free");
obj_no_longer_held(otmp);
/* (could bypass this vision update if there is already a boulder here) */
/* obj goes under boulders */
if (otmp2 && (otmp2->otyp == BOULDER)) {
- otmp->nexthere = otmp2->nexthere;
- otmp2->nexthere = otmp;
+ otmp->nexthere = otmp2->nexthere;
+ otmp2->nexthere = otmp;
} else {
- otmp->nexthere = otmp2;
- level.objects[x][y] = otmp;
+ otmp->nexthere = otmp2;
+ level.objects[x][y] = otmp;
}
/* set the new object's location */
int x, y;
boolean do_buried;
{
- struct obj *otmp;
+ struct obj *otmp;
- for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) {
- if (otmp->timed) obj_timer_checks(otmp, x, y, 0);
- }
- if (do_buried) {
- for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) {
- if (otmp->ox == x && otmp->oy == y) {
- if (otmp->timed) obj_timer_checks(otmp, x, y, 0);
- }
- }
- }
+ for (otmp = level.objects[x][y]; otmp; otmp = otmp->nexthere) {
+ if (otmp->timed) obj_timer_checks(otmp, x, y, 0);
+ }
+ if (do_buried) {
+ for (otmp = level.buriedobjlist; otmp; otmp = otmp->nobj) {
+ if (otmp->ox == x && otmp->oy == y) {
+ if (otmp->timed) obj_timer_checks(otmp, x, y, 0);
+ }
+ }
+ }
}
/*
long age, retval = otmp->age;
if (otmp->otyp == CORPSE && otmp->on_ice) {
- /* Adjust the age; must be same as obj_timer_checks() for off ice*/
- age = monstermoves - otmp->age;
- retval += age * (ROT_ICE_ADJUSTMENT-1) / ROT_ICE_ADJUSTMENT;
- debugpline("The %s age has ice modifications:otmp->age = %ld, returning %ld.",
- s_suffix(doname(otmp)),otmp->age, retval);
- debugpline("Effective age of corpse: %ld.",
- monstermoves - retval);
+ /* Adjust the age; must be same as obj_timer_checks() for off ice*/
+ age = monstermoves - otmp->age;
+ retval += age * (ROT_ICE_ADJUSTMENT-1) / ROT_ICE_ADJUSTMENT;
+ debugpline("The %s age has ice modifications:otmp->age = %ld, returning %ld.",
+ s_suffix(doname(otmp)),otmp->age, retval);
+ debugpline("Effective age of corpse: %ld.",
+ monstermoves - retval);
}
return retval;
}
/* Check for corpses just placed on or in ice */
if (otmp->otyp == CORPSE && (on_floor || buried) && is_ice(x,y)) {
- tleft = stop_timer(action, obj_to_any(otmp));
- if (tleft == 0L) {
- action = REVIVE_MON;
- tleft = stop_timer(action, obj_to_any(otmp));
- }
- if (tleft != 0L) {
- long age;
-
- /* mark the corpse as being on ice */
- otmp->on_ice = 1;
- debugpline("%s is now on ice at %d,%d.", The(xname(otmp)),x,y);
- /* Adjust the time remaining */
- tleft *= ROT_ICE_ADJUSTMENT;
- restart_timer = TRUE;
- /* Adjust the age; time spent off ice needs to be multiplied
- by the ice adjustment and subtracted from the age so that
- later calculations behave as if it had been on ice during
- that time (longwinded way of saying this is the inverse
- of removing it from the ice and of peeking at its age). */
- age = monstermoves - otmp->age;
- otmp->age = monstermoves - (age * ROT_ICE_ADJUSTMENT);
- }
+ tleft = stop_timer(action, obj_to_any(otmp));
+ if (tleft == 0L) {
+ action = REVIVE_MON;
+ tleft = stop_timer(action, obj_to_any(otmp));
+ }
+ if (tleft != 0L) {
+ long age;
+
+ /* mark the corpse as being on ice */
+ otmp->on_ice = 1;
+ debugpline("%s is now on ice at %d,%d.", The(xname(otmp)),x,y);
+ /* Adjust the time remaining */
+ tleft *= ROT_ICE_ADJUSTMENT;
+ restart_timer = TRUE;
+ /* Adjust the age; time spent off ice needs to be multiplied
+ by the ice adjustment and subtracted from the age so that
+ later calculations behave as if it had been on ice during
+ that time (longwinded way of saying this is the inverse
+ of removing it from the ice and of peeking at its age). */
+ age = monstermoves - otmp->age;
+ otmp->age = monstermoves - (age * ROT_ICE_ADJUSTMENT);
+ }
}
/* Check for corpses coming off ice */
else if ((force < 0) ||
- (otmp->otyp == CORPSE && otmp->on_ice &&
- !((on_floor || buried) && is_ice(x,y)))) {
- tleft = stop_timer(action, obj_to_any(otmp));
- if (tleft == 0L) {
- action = REVIVE_MON;
- tleft = stop_timer(action, obj_to_any(otmp));
- }
- if (tleft != 0L) {
- long age;
-
- otmp->on_ice = 0;
- debugpline("%s is no longer on ice at %d,%d.", The(xname(otmp)),x,y);
- /* Adjust the remaining time */
- tleft /= ROT_ICE_ADJUSTMENT;
- restart_timer = TRUE;
- /* Adjust the age */
- age = monstermoves - otmp->age;
- otmp->age += age * (ROT_ICE_ADJUSTMENT-1) / ROT_ICE_ADJUSTMENT;
- }
+ (otmp->otyp == CORPSE && otmp->on_ice &&
+ !((on_floor || buried) && is_ice(x,y)))) {
+ tleft = stop_timer(action, obj_to_any(otmp));
+ if (tleft == 0L) {
+ action = REVIVE_MON;
+ tleft = stop_timer(action, obj_to_any(otmp));
+ }
+ if (tleft != 0L) {
+ long age;
+
+ otmp->on_ice = 0;
+ debugpline("%s is no longer on ice at %d,%d.", The(xname(otmp)),x,y);
+ /* Adjust the remaining time */
+ tleft /= ROT_ICE_ADJUSTMENT;
+ restart_timer = TRUE;
+ /* Adjust the age */
+ age = monstermoves - otmp->age;
+ otmp->age += age * (ROT_ICE_ADJUSTMENT-1) / ROT_ICE_ADJUSTMENT;
+ }
}
/* now re-start the timer with the appropriate modifications */
if (restart_timer)
- (void) start_timer(tleft, TIMER_OBJECT, action, obj_to_any(otmp));
+ (void) start_timer(tleft, TIMER_OBJECT, action, obj_to_any(otmp));
}
#undef ROT_ICE_ADJUSTMENT
xchar y = otmp->oy;
if (otmp->where != OBJ_FLOOR)
- panic("remove_object: obj not on floor");
+ panic("remove_object: obj not on floor");
extract_nexthere(otmp, &level.objects[x][y]);
extract_nobj(otmp, &fobj);
/* update vision iff this was the only boulder at its spot */
if (otmp->otyp == BOULDER && !sobj_at(BOULDER, x, y))
- unblock_point(x,y); /* vision */
+ unblock_point(x,y); /* vision */
if (otmp->timed) obj_timer_checks(otmp,x,y,0);
}
boolean keeping_mon = (mtmp->mhp > 0);
while ((otmp = mtmp->minvent) != 0) {
- /* this has now become very similar to m_useupall()... */
- obj_extract_self(otmp);
- if (otmp->owornmask) {
- if (keeping_mon) {
- if (otmp == mwep) mwepgone(mtmp), mwep = 0;
- mtmp->misc_worn_check &= ~otmp->owornmask;
- update_mon_intrinsics(mtmp, otmp, FALSE, TRUE);
- }
- otmp->owornmask = 0L; /* obfree() expects this */
- }
- obfree(otmp, (struct obj *)0); /* dealloc_obj() isn't sufficient */
+ /* this has now become very similar to m_useupall()... */
+ obj_extract_self(otmp);
+ if (otmp->owornmask) {
+ if (keeping_mon) {
+ if (otmp == mwep) mwepgone(mtmp), mwep = 0;
+ mtmp->misc_worn_check &= ~otmp->owornmask;
+ update_mon_intrinsics(mtmp, otmp, FALSE, TRUE);
+ }
+ otmp->owornmask = 0L; /* obfree() expects this */
+ }
+ obfree(otmp, (struct obj *)0); /* dealloc_obj() isn't sufficient */
}
}
struct obj *obj;
{
switch (obj->where) {
- case OBJ_FREE:
- break;
- case OBJ_FLOOR:
- remove_object(obj);
- break;
- case OBJ_CONTAINED:
- extract_nobj(obj, &obj->ocontainer->cobj);
- container_weight(obj->ocontainer);
- break;
- case OBJ_INVENT:
- freeinv(obj);
- break;
- case OBJ_MINVENT:
- extract_nobj(obj, &obj->ocarry->minvent);
- break;
- case OBJ_MIGRATING:
- extract_nobj(obj, &migrating_objs);
- break;
- case OBJ_BURIED:
- extract_nobj(obj, &level.buriedobjlist);
- break;
- case OBJ_ONBILL:
- extract_nobj(obj, &billobjs);
- break;
- default:
- panic("obj_extract_self");
- break;
+ case OBJ_FREE:
+ break;
+ case OBJ_FLOOR:
+ remove_object(obj);
+ break;
+ case OBJ_CONTAINED:
+ extract_nobj(obj, &obj->ocontainer->cobj);
+ container_weight(obj->ocontainer);
+ break;
+ case OBJ_INVENT:
+ freeinv(obj);
+ break;
+ case OBJ_MINVENT:
+ extract_nobj(obj, &obj->ocarry->minvent);
+ break;
+ case OBJ_MIGRATING:
+ extract_nobj(obj, &migrating_objs);
+ break;
+ case OBJ_BURIED:
+ extract_nobj(obj, &level.buriedobjlist);
+ break;
+ case OBJ_ONBILL:
+ extract_nobj(obj, &billobjs);
+ break;
+ default:
+ panic("obj_extract_self");
+ break;
}
}
curr = *head_ptr;
for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nobj) {
- if (curr == obj) {
- if (prev)
- prev->nobj = curr->nobj;
- else
- *head_ptr = curr->nobj;
- break;
- }
+ if (curr == obj) {
+ if (prev)
+ prev->nobj = curr->nobj;
+ else
+ *head_ptr = curr->nobj;
+ break;
+ }
}
if (!curr) panic("extract_nobj: object lost");
obj->where = OBJ_FREE;
curr = *head_ptr;
for (prev = (struct obj *) 0; curr; prev = curr, curr = curr->nexthere) {
- if (curr == obj) {
- if (prev)
- prev->nexthere = curr->nexthere;
- else
- *head_ptr = curr->nexthere;
- break;
- }
+ if (curr == obj) {
+ if (prev)
+ prev->nexthere = curr->nexthere;
+ else
+ *head_ptr = curr->nexthere;
+ break;
+ }
}
if (!curr) panic("extract_nexthere: object lost");
}
struct obj *otmp;
if (obj->where != OBJ_FREE)
- panic("add_to_minv: obj not free");
+ panic("add_to_minv: obj not free");
/* merge if possible */
for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
- if (merged(&otmp, &obj))
- return 1; /* obj merged and then free'd */
+ if (merged(&otmp, &obj))
+ return 1; /* obj merged and then free'd */
/* else insert; don't bother forcing it to end of chain */
obj->where = OBJ_MINVENT;
obj->ocarry = mon;
struct obj *otmp;
if (obj->where != OBJ_FREE)
- panic("add_to_container: obj not free");
+ panic("add_to_container: obj not free");
if (container->where != OBJ_INVENT && container->where != OBJ_MINVENT)
- obj_no_longer_held(obj);
+ obj_no_longer_held(obj);
/* merge if possible */
for (otmp = container->cobj; otmp; otmp = otmp->nobj)
- if (merged(&otmp, &obj)) return (otmp);
+ if (merged(&otmp, &obj)) return (otmp);
obj->where = OBJ_CONTAINED;
obj->ocontainer = container;
struct obj *obj;
{
if (obj->where != OBJ_FREE)
- panic("add_to_migration: obj not free");
+ panic("add_to_migration: obj not free");
obj->where = OBJ_MIGRATING;
obj->nobj = migrating_objs;
struct obj *obj;
{
if (obj->where != OBJ_FREE)
- panic("add_to_buried: obj not free");
+ panic("add_to_buried: obj not free");
obj->where = OBJ_BURIED;
obj->nobj = level.buriedobjlist;
{
container->owt = weight(container);
if (container->where == OBJ_CONTAINED)
- container_weight(container->ocontainer);
+ container_weight(container->ocontainer);
/*
else if (container->where == OBJ_INVENT)
- recalculate load delay here ???
+ recalculate load delay here ???
*/
}
struct obj *obj;
{
if (obj->where != OBJ_FREE)
- panic("dealloc_obj: obj not free");
+ panic("dealloc_obj: obj not free");
/* free up any timers attached to the object */
if (obj->timed)
- obj_stop_timers(obj);
+ obj_stop_timers(obj);
/*
* Free up any light sources attached to the object.
* attached to it (and also requires lamplit to be set).
*/
if (obj_sheds_light(obj))
- del_light_source(LS_OBJECT, obj_to_any(obj));
+ del_light_source(LS_OBJECT, obj_to_any(obj));
if (obj == thrownobj) thrownobj = 0;
if (obj == kickedobj) kickedobj = 0;
int objcount = 0;
if (!horn || horn->otyp != HORN_OF_PLENTY) {
- impossible("bad horn o' plenty");
+ impossible("bad horn o' plenty");
} else if (horn->spe < 1) {
- pline1(nothing_happens);
+ pline1(nothing_happens);
} else {
- struct obj *obj;
- const char *what;
-
- consume_obj_charge(horn, !tipping);
- if (!rn2(13)) {
- obj = mkobj(POTION_CLASS, FALSE);
- if (objects[obj->otyp].oc_magic) do {
- obj->otyp = rnd_class(POT_BOOZE, POT_WATER);
- } while (obj->otyp == POT_SICKNESS);
- what = (obj->quan > 1L) ? "Some potions" : "A potion";
- } else {
- obj = mkobj(FOOD_CLASS, FALSE);
- if (obj->otyp == FOOD_RATION && !rn2(7))
- obj->otyp = LUMP_OF_ROYAL_JELLY;
- what = "Some food";
- }
- ++objcount;
- pline("%s %s out.", what, vtense(what, "spill"));
- obj->blessed = horn->blessed;
- obj->cursed = horn->cursed;
- obj->owt = weight(obj);
- /* using a shop's horn of plenty entails a usage fee and also
- confers ownership of the created item to the shopkeeper */
- if (horn->unpaid)
- addtobill(obj, FALSE, FALSE, tipping);
- /* if it ended up on bill, we don't want "(unpaid, N zorkids)"
- being included in its formatted name during next message */
- iflags.suppress_price++;
- if (!tipping) {
- obj = hold_another_object(obj, u.uswallow ?
- "Oops! %s out of your reach!" :
- (Is_airlevel(&u.uz) ||
- Is_waterlevel(&u.uz) ||
- levl[u.ux][u.uy].typ < IRONBARS ||
- levl[u.ux][u.uy].typ >= ICE) ?
- "Oops! %s away from you!" :
- "Oops! %s to the floor!",
- The(aobjnam(obj, "slip")),
- (const char *)0);
- } else {
- /* assumes this is taking place at hero's location */
- if (!can_reach_floor(TRUE)) {
- hitfloor(obj); /* does altar check, message, drop */
- } else {
- if (IS_ALTAR(levl[u.ux][u.uy].typ))
- doaltarobj(obj); /* does its own drop message */
- else
- pline("%s %s to the %s.", Doname2(obj),
- otense(obj, "drop"), surface(u.ux, u.uy));
- dropy(obj);
- }
- }
- iflags.suppress_price--;
- if (horn->dknown) makeknown(HORN_OF_PLENTY);
+ struct obj *obj;
+ const char *what;
+
+ consume_obj_charge(horn, !tipping);
+ if (!rn2(13)) {
+ obj = mkobj(POTION_CLASS, FALSE);
+ if (objects[obj->otyp].oc_magic) do {
+ obj->otyp = rnd_class(POT_BOOZE, POT_WATER);
+ } while (obj->otyp == POT_SICKNESS);
+ what = (obj->quan > 1L) ? "Some potions" : "A potion";
+ } else {
+ obj = mkobj(FOOD_CLASS, FALSE);
+ if (obj->otyp == FOOD_RATION && !rn2(7))
+ obj->otyp = LUMP_OF_ROYAL_JELLY;
+ what = "Some food";
+ }
+ ++objcount;
+ pline("%s %s out.", what, vtense(what, "spill"));
+ obj->blessed = horn->blessed;
+ obj->cursed = horn->cursed;
+ obj->owt = weight(obj);
+ /* using a shop's horn of plenty entails a usage fee and also
+ confers ownership of the created item to the shopkeeper */
+ if (horn->unpaid)
+ addtobill(obj, FALSE, FALSE, tipping);
+ /* if it ended up on bill, we don't want "(unpaid, N zorkids)"
+ being included in its formatted name during next message */
+ iflags.suppress_price++;
+ if (!tipping) {
+ obj = hold_another_object(obj, u.uswallow ?
+ "Oops! %s out of your reach!" :
+ (Is_airlevel(&u.uz) ||
+ Is_waterlevel(&u.uz) ||
+ levl[u.ux][u.uy].typ < IRONBARS ||
+ levl[u.ux][u.uy].typ >= ICE) ?
+ "Oops! %s away from you!" :
+ "Oops! %s to the floor!",
+ The(aobjnam(obj, "slip")),
+ (const char *)0);
+ } else {
+ /* assumes this is taking place at hero's location */
+ if (!can_reach_floor(TRUE)) {
+ hitfloor(obj); /* does altar check, message, drop */
+ } else {
+ if (IS_ALTAR(levl[u.ux][u.uy].typ))
+ doaltarobj(obj); /* does its own drop message */
+ else
+ pline("%s %s to the %s.", Doname2(obj),
+ otense(obj, "drop"), surface(u.ux, u.uy));
+ dropy(obj);
+ }
+ }
+ iflags.suppress_price--;
+ if (horn->dknown) makeknown(HORN_OF_PLENTY);
}
return objcount;
}
/* support for wizard-mode's `sanity_check' option */
static const char NEARDATA /* pline formats for insane_object() */
- ofmt0[] = "%s obj %s %s: %s",
- ofmt3[] = "%s [not null] %s %s: %s",
- /* " held by mon %p (%s)" will be appended, filled by M,mon_nam(M) */
- mfmt1[] = "%s obj %s %s (%s)",
- mfmt2[] = "%s obj %s %s (%s) *not*";
+ ofmt0[] = "%s obj %s %s: %s",
+ ofmt3[] = "%s [not null] %s %s: %s",
+ /* " held by mon %p (%s)" will be appended, filled by M,mon_nam(M) */
+ mfmt1[] = "%s obj %s %s (%s)",
+ mfmt2[] = "%s obj %s %s (%s) *not*";
/* Check all object lists for consistency. */
void
those objects should have already been sanity checked via
the floor list so container contents are skipped here */
for (x = 0; x < COLNO; x++)
- for (y = 0; y < ROWNO; y++)
- for (obj = level.objects[x][y]; obj; obj = obj->nexthere) {
- /* <ox,oy> should match <x,y>; <0,*> should always be empty */
- if (obj->where != OBJ_FLOOR || x == 0 ||
- obj->ox != x || obj->oy != y) {
- char at_fmt[BUFSZ];
-
- Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>",
- x, y, obj->ox, obj->oy);
- insane_object(obj, at_fmt, "location sanity",
- (struct monst *)0);
- }
- }
+ for (y = 0; y < ROWNO; y++)
+ for (obj = level.objects[x][y]; obj; obj = obj->nexthere) {
+ /* <ox,oy> should match <x,y>; <0,*> should always be empty */
+ if (obj->where != OBJ_FLOOR || x == 0 ||
+ obj->ox != x || obj->oy != y) {
+ char at_fmt[BUFSZ];
+
+ Sprintf(at_fmt, "%%s obj@<%d,%d> %%s %%s: %%s@<%d,%d>",
+ x, y, obj->ox, obj->oy);
+ insane_object(obj, at_fmt, "location sanity",
+ (struct monst *)0);
+ }
+ }
objlist_sanity(invent, OBJ_INVENT, "invent sanity");
objlist_sanity(migrating_objs, OBJ_MIGRATING, "migrating sanity");
/* monsters temporarily in transit;
they should have arrived with hero by the time we get called */
if (mydogs) {
- pline("mydogs sanity [not empty]");
- mon_obj_sanity(mydogs, "mydogs minvent sanity");
+ pline("mydogs sanity [not empty]");
+ mon_obj_sanity(mydogs, "mydogs minvent sanity");
}
/* objects temporarily freed from invent/floor lists;
they should have arrived somewhere by the time we get called */
if (thrownobj)
- insane_object(thrownobj, ofmt3, "thrownobj sanity", (struct monst *)0);
+ insane_object(thrownobj, ofmt3, "thrownobj sanity", (struct monst *)0);
if (kickedobj)
- insane_object(kickedobj, ofmt3, "kickedobj sanity", (struct monst *)0);
+ insane_object(kickedobj, ofmt3, "kickedobj sanity", (struct monst *)0);
/* [how about current_wand too?] */
}
struct obj *obj;
for (obj = objlist; obj; obj = obj->nobj) {
- if (obj->where != wheretype)
- insane_object(obj, ofmt0, mesg, (struct monst *)0);
- if (Has_contents(obj)) {
- if (wheretype == OBJ_ONBILL)
- /* containers on shop bill should always be empty */
- insane_object(obj, "%s obj contains something! %s %s: %s",
- mesg, (struct monst *)0);
- check_contained(obj, mesg);
- }
+ if (obj->where != wheretype)
+ insane_object(obj, ofmt0, mesg, (struct monst *)0);
+ if (Has_contents(obj)) {
+ if (wheretype == OBJ_ONBILL)
+ /* containers on shop bill should always be empty */
+ insane_object(obj, "%s obj contains something! %s %s: %s",
+ mesg, (struct monst *)0);
+ check_contained(obj, mesg);
+ }
}
}
struct obj *obj;
for (mon = monlist; mon; mon = mon->nmon)
- for (obj = mon->minvent; obj; obj = obj->nobj) {
- if (obj->where != OBJ_MINVENT)
- insane_object(obj, mfmt1, mesg, mon);
- if (obj->ocarry != mon)
- insane_object(obj, mfmt2, mesg, mon);
- check_contained(obj, mesg);
- }
+ for (obj = mon->minvent; obj; obj = obj->nobj) {
+ if (obj->where != OBJ_MINVENT)
+ insane_object(obj, mfmt1, mesg, mon);
+ if (obj->ocarry != mon)
+ insane_object(obj, mfmt2, mesg, mon);
+ check_contained(obj, mesg);
+ }
}
/* This must stay consistent with the defines in obj.h. */
static const char *obj_state_names[NOBJ_STATES] = {
- "free", "floor", "contained", "invent",
- "minvent", "migrating", "buried", "onbill"
+ "free", "floor", "contained", "invent",
+ "minvent", "migrating", "buried", "onbill"
};
STATIC_OVL const char *
if (!obj) return "nowhere";
where = obj->where;
if (where < 0 || where >= NOBJ_STATES || !obj_state_names[where]) {
- Sprintf(unknown, "unknown[%d]", where);
- return unknown;
+ Sprintf(unknown, "unknown[%d]", where);
+ return unknown;
}
return obj_state_names[where];
}
objnm = monnm = "null!";
if (obj) {
- iflags.override_ID++;
- objnm = doname(obj);
- iflags.override_ID--;
+ iflags.override_ID++;
+ objnm = doname(obj);
+ iflags.override_ID--;
}
if (mon || (strstri(mesg, "minvent") && !strstri(mesg, "contained"))) {
- Strcat(strcpy(altfmt, fmt), " held by mon %s (%s)");
- if (mon)
- monnm = x_monnam(mon, ARTICLE_A, (char *)0, EXACT_NAME, TRUE);
- pline(altfmt, mesg,
- fmt_ptr((genericptr_t)obj), where_name(obj), objnm,
- fmt_ptr((genericptr_t)mon), monnm);
+ Strcat(strcpy(altfmt, fmt), " held by mon %s (%s)");
+ if (mon)
+ monnm = x_monnam(mon, ARTICLE_A, (char *)0, EXACT_NAME, TRUE);
+ pline(altfmt, mesg,
+ fmt_ptr((genericptr_t)obj), where_name(obj), objnm,
+ fmt_ptr((genericptr_t)mon), monnm);
} else {
- pline(fmt, mesg, fmt_ptr((genericptr_t)obj), where_name(obj), objnm);
+ pline(fmt, mesg, fmt_ptr((genericptr_t)obj), where_name(obj), objnm);
}
}
/* change "invent sanity" to "contained invent sanity"
but leave "nested contained invent sanity" as is */
if (!strstri(mesg, "contained"))
- mesg = strcat(strcpy(mesgbuf, "contained "), mesg);
+ mesg = strcat(strcpy(mesgbuf, "contained "), mesg);
for (obj = container->cobj; obj; obj = obj->nobj) {
- /* catch direct cycle to avoid unbounded recursion */
- if (obj == container)
- panic("failed sanity check: container holds itself");
- if (obj->where != OBJ_CONTAINED)
- insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *)0);
- else if (obj->ocontainer != container)
- pline("%s obj %s in container %s, not %s", mesg,
- fmt_ptr((genericptr_t)obj),
- fmt_ptr((genericptr_t)obj->ocontainer),
- fmt_ptr((genericptr_t)container));
-
- if (Has_contents(obj)) {
- /* catch most likely indirect cycle; we won't notice if
- parent is present when something comes before it, or
- notice more deeply embedded cycles (grandparent, &c) */
- if (obj->cobj == container)
- panic("failed sanity check: container holds its parent");
- /* change "contained... sanity" to "nested contained... sanity"
- and "nested contained..." to "nested nested contained..." */
- Strcpy(nestedmesg, "nested ");
- copynchars(eos(nestedmesg), mesg,
- (int)sizeof nestedmesg - (int)strlen(nestedmesg) - 1);
- /* recursively check contents */
- check_contained(obj, nestedmesg);
- }
+ /* catch direct cycle to avoid unbounded recursion */
+ if (obj == container)
+ panic("failed sanity check: container holds itself");
+ if (obj->where != OBJ_CONTAINED)
+ insane_object(obj, "%s obj %s %s: %s", mesg, (struct monst *)0);
+ else if (obj->ocontainer != container)
+ pline("%s obj %s in container %s, not %s", mesg,
+ fmt_ptr((genericptr_t)obj),
+ fmt_ptr((genericptr_t)obj->ocontainer),
+ fmt_ptr((genericptr_t)container));
+
+ if (Has_contents(obj)) {
+ /* catch most likely indirect cycle; we won't notice if
+ parent is present when something comes before it, or
+ notice more deeply embedded cycles (grandparent, &c) */
+ if (obj->cobj == container)
+ panic("failed sanity check: container holds its parent");
+ /* change "contained... sanity" to "nested contained... sanity"
+ and "nested contained..." to "nested nested contained..." */
+ Strcpy(nestedmesg, "nested ");
+ copynchars(eos(nestedmesg), mesg,
+ (int)sizeof nestedmesg - (int)strlen(nestedmesg) - 1);
+ /* recursively check contents */
+ check_contained(obj, nestedmesg);
+ }
+ }
+}
+
+
+/*
+ * wrapper to make "near this object" convenient
+ */
+struct obj*
+obj_nexto(otmp)
+ struct obj* otmp;
+{
+ struct obj* otmp2 = NULL;
+
+ if (otmp) {
+ otmp2 = obj_nexto_xy(otmp->otyp, otmp->ox, otmp->oy, otmp->o_id);
+ } else {
+ impossible("obj_nexto: wasn't given an object to check");
+ }
+
+ return otmp2;
+}
+
+
+/*
+ * looks for objects of a particular type next to x, y
+ * skips over oid if found (lets us avoid ourselves if
+ * we're looking for a second type of an existing object)
+ *
+ * TODO: return a list of all objects near us so we can more
+ * reliably predict which one we want to 'find' first
+ */
+struct obj*
+obj_nexto_xy(otyp, x, y, oid)
+ int otyp, x, y, oid;
+{
+ struct obj* otmp;
+ int fx, fy, ex, ey;
+ short dx, dy;
+
+ /* check under our "feet" first */
+ otmp = sobj_at(otyp, x, y);
+ while (otmp) {
+ /* don't be clever and find ourselves */
+ if (otmp->o_id != oid) { return otmp; }
+ otmp = nxtobj(otmp, otyp, TRUE);
+ }
+
+ /* search in a random order */
+ dx = (rn2(2) ? -1 : 1);
+ dy = (rn2(2) ? -1 : 1);
+ ex = x - dx;
+ ey = y - dy;
+
+ for (fx = ex; abs(fx - ex) < 3; fx += dx) {
+ for (fy = ey; abs(fy - ey) < 3; fy += dy) {
+ /* 0, 0 was checked above */
+ if (fx != x || fy != y) {
+ if (otmp = sobj_at(otyp, fx, fy)) {
+ return otmp;
+ }
+ }
+ }
+ }
+
+ return NULL;
+}
+
+
+/*
+ * Causes one object to absorb another, smaller one of
+ * its own type, increasing weight accordingly.
+ * Returns the object that remains; frees the other.
+ */
+struct obj*
+obj_meld(obj1, obj2)
+ struct obj **obj1, **obj2;
+{
+ struct obj *otmp1 = NULL, *otmp2 = NULL;
+ int extrawt = 0;
+ boolean reversed = FALSE;
+
+ if (obj1 && obj2 && *obj1 && *obj2) {
+ otmp1 = *obj1;
+ otmp2 = *obj2;
+
+ if ((otmp1->owt == otmp2->owt && rn2(2))
+ || (otmp1->owt < otmp2->owt)) {
+ otmp2 = *obj1; otmp1 = *obj2;
+ reversed = TRUE;
+ }
+
+ extrawt = otmp2->oeaten ? otmp2->oeaten : otmp2->owt;
+ otmp1->owt += extrawt;
+ otmp1->oeaten += otmp1->oeaten ? extrawt : 0;
+ obj_extract_self(otmp2);
+ dealloc_obj(otmp2);
+ if (reversed) { *obj1 = NULL; } else { *obj2 = NULL; }
+ return otmp1;
}
+
+ impossible("obj_meld: not called with two actual objects");
+ return NULL;
}
+
/*mkobj.c*/
STATIC_DCL struct permonst *FDECL(accept_newcham_form, (int));
#define LEVEL_SPECIFIC_NOCORPSE(mdat) \
- (Is_rogue_level(&u.uz) || \
- (level.flags.graveyard && is_undead(mdat) && rn2(3)))
+ (Is_rogue_level(&u.uz) || \
+ (level.flags.graveyard && is_undead(mdat) && rn2(3)))
#if 0
/* part of the original warning code which was replaced in 3.3.1 */
const char *warnings[] = {
- "white", "pink", "red", "ruby", "purple", "black"
+ "white", "pink", "red", "ruby", "purple", "black"
};
#endif /* 0 */
undead_to_corpse(mndx)
int mndx;
{
- switch (mndx) {
- case PM_KOBOLD_ZOMBIE:
- case PM_KOBOLD_MUMMY: mndx = PM_KOBOLD; break;
- case PM_DWARF_ZOMBIE:
- case PM_DWARF_MUMMY: mndx = PM_DWARF; break;
- case PM_GNOME_ZOMBIE:
- case PM_GNOME_MUMMY: mndx = PM_GNOME; break;
- case PM_ORC_ZOMBIE:
- case PM_ORC_MUMMY: mndx = PM_ORC; break;
- case PM_ELF_ZOMBIE:
- case PM_ELF_MUMMY: mndx = PM_ELF; break;
- case PM_VAMPIRE:
- case PM_VAMPIRE_LORD:
+ switch (mndx) {
+ case PM_KOBOLD_ZOMBIE:
+ case PM_KOBOLD_MUMMY: mndx = PM_KOBOLD; break;
+ case PM_DWARF_ZOMBIE:
+ case PM_DWARF_MUMMY: mndx = PM_DWARF; break;
+ case PM_GNOME_ZOMBIE:
+ case PM_GNOME_MUMMY: mndx = PM_GNOME; break;
+ case PM_ORC_ZOMBIE:
+ case PM_ORC_MUMMY: mndx = PM_ORC; break;
+ case PM_ELF_ZOMBIE:
+ case PM_ELF_MUMMY: mndx = PM_ELF; break;
+ case PM_VAMPIRE:
+ case PM_VAMPIRE_LORD:
#if 0 /* DEFERRED */
- case PM_VAMPIRE_MAGE:
+ case PM_VAMPIRE_MAGE:
#endif
- case PM_HUMAN_ZOMBIE:
- case PM_HUMAN_MUMMY: mndx = PM_HUMAN; break;
- case PM_GIANT_ZOMBIE:
- case PM_GIANT_MUMMY: mndx = PM_GIANT; break;
- case PM_ETTIN_ZOMBIE:
- case PM_ETTIN_MUMMY: mndx = PM_ETTIN; break;
- default: break;
- }
- return mndx;
+ case PM_HUMAN_ZOMBIE:
+ case PM_HUMAN_MUMMY: mndx = PM_HUMAN; break;
+ case PM_GIANT_ZOMBIE:
+ case PM_GIANT_MUMMY: mndx = PM_GIANT; break;
+ case PM_ETTIN_ZOMBIE:
+ case PM_ETTIN_MUMMY: mndx = PM_ETTIN; break;
+ default: break;
+ }
+ return mndx;
}
/* Convert the monster index of some monsters (such as quest guardians)
genus(mndx, mode)
int mndx, mode;
{
- switch (mndx) {
+ switch (mndx) {
/* Quest guardians */
- case PM_STUDENT: mndx = mode ? PM_ARCHEOLOGIST : PM_HUMAN; break;
- case PM_CHIEFTAIN: mndx = mode ? PM_BARBARIAN : PM_HUMAN; break;
- case PM_NEANDERTHAL: mndx = mode ? PM_CAVEMAN : PM_HUMAN; break;
- case PM_ATTENDANT: mndx = mode ? PM_HEALER : PM_HUMAN; break;
- case PM_PAGE: mndx = mode ? PM_KNIGHT : PM_HUMAN; break;
- case PM_ABBOT: mndx = mode ? PM_MONK : PM_HUMAN; break;
- case PM_ACOLYTE: mndx = mode ? PM_PRIEST : PM_HUMAN; break;
- case PM_HUNTER: mndx = mode ? PM_RANGER : PM_HUMAN; break;
- case PM_THUG: mndx = mode ? PM_ROGUE : PM_HUMAN; break;
- case PM_ROSHI: mndx = mode ? PM_SAMURAI : PM_HUMAN; break;
- case PM_GUIDE: mndx = mode ? PM_TOURIST : PM_HUMAN; break;
- case PM_APPRENTICE: mndx = mode ? PM_WIZARD : PM_HUMAN; break;
- case PM_WARRIOR: mndx = mode ? PM_VALKYRIE : PM_HUMAN; break;
- default:
- if (mndx >= LOW_PM && mndx < NUMMONS) {
- struct permonst *ptr = &mons[mndx];
- if (is_human(ptr)) mndx = PM_HUMAN;
- else if (is_elf(ptr)) mndx = PM_ELF;
- else if (is_dwarf(ptr)) mndx = PM_DWARF;
- else if (is_gnome(ptr)) mndx = PM_GNOME;
- else if (is_orc(ptr)) mndx = PM_ORC;
- }
- break;
- }
- return mndx;
+ case PM_STUDENT: mndx = mode ? PM_ARCHEOLOGIST : PM_HUMAN; break;
+ case PM_CHIEFTAIN: mndx = mode ? PM_BARBARIAN : PM_HUMAN; break;
+ case PM_NEANDERTHAL: mndx = mode ? PM_CAVEMAN : PM_HUMAN; break;
+ case PM_ATTENDANT: mndx = mode ? PM_HEALER : PM_HUMAN; break;
+ case PM_PAGE: mndx = mode ? PM_KNIGHT : PM_HUMAN; break;
+ case PM_ABBOT: mndx = mode ? PM_MONK : PM_HUMAN; break;
+ case PM_ACOLYTE: mndx = mode ? PM_PRIEST : PM_HUMAN; break;
+ case PM_HUNTER: mndx = mode ? PM_RANGER : PM_HUMAN; break;
+ case PM_THUG: mndx = mode ? PM_ROGUE : PM_HUMAN; break;
+ case PM_ROSHI: mndx = mode ? PM_SAMURAI : PM_HUMAN; break;
+ case PM_GUIDE: mndx = mode ? PM_TOURIST : PM_HUMAN; break;
+ case PM_APPRENTICE: mndx = mode ? PM_WIZARD : PM_HUMAN; break;
+ case PM_WARRIOR: mndx = mode ? PM_VALKYRIE : PM_HUMAN; break;
+ default:
+ if (mndx >= LOW_PM && mndx < NUMMONS) {
+ struct permonst *ptr = &mons[mndx];
+ if (is_human(ptr)) mndx = PM_HUMAN;
+ else if (is_elf(ptr)) mndx = PM_ELF;
+ else if (is_dwarf(ptr)) mndx = PM_DWARF;
+ else if (is_gnome(ptr)) mndx = PM_GNOME;
+ else if (is_orc(ptr)) mndx = PM_ORC;
+ }
+ break;
+ }
+ return mndx;
}
/* return monster index if chameleon, or NON_PM if not */
pm_to_cham(mndx)
int mndx;
{
- int mcham = NON_PM;
+ int mcham = NON_PM;
- /*
- * As of 3.5.0 we just check M2_SHAPESHIFTER instead of having a
- * big switch statement with hardcoded shapeshifter types here.
- */
- if (mndx >= LOW_PM && is_shapeshifter(&mons[mndx])) mcham = mndx;
- return mcham;
+ /*
+ * As of 3.5.0 we just check M2_SHAPESHIFTER instead of having a
+ * big switch statement with hardcoded shapeshifter types here.
+ */
+ if (mndx >= LOW_PM && is_shapeshifter(&mons[mndx])) mcham = mndx;
+ return mcham;
}
/* for deciding whether corpse will carry along full monster data */
#define KEEPTRAITS(mon) ((mon)->isshk || (mon)->mtame || \
- unique_corpstat(mon->data) || \
- is_reviver((mon)->data) || \
- /* normally leader the will be unique, */ \
- /* but he might have been polymorphed */ \
- (mon)->m_id == quest_status.leader_m_id || \
- /* special cancellation handling for these */ \
- (dmgtype((mon)->data, AD_SEDU) || \
- dmgtype((mon)->data, AD_SSEX)))
+ unique_corpstat(mon->data) || \
+ is_reviver((mon)->data) || \
+ /* normally leader the will be unique, */ \
+ /* but he might have been polymorphed */ \
+ (mon)->m_id == quest_status.leader_m_id || \
+ /* special cancellation handling for these */ \
+ (dmgtype((mon)->data, AD_SEDU) || \
+ dmgtype((mon)->data, AD_SSEX)))
/* Creates a monster corpse, a "special" corpse, or nothing if it doesn't
* leave corpses. Monsters which leave "special" corpses should have
register struct monst *mtmp;
unsigned corpseflags;
{
- register struct permonst *mdat = mtmp->data;
- int num;
- struct obj *obj = (struct obj *)0;
- int x = mtmp->mx, y = mtmp->my;
- int mndx = monsndx(mdat);
- unsigned corpstatflags = corpseflags;
- boolean burythem = ((corpstatflags & CORPSTAT_BURIED) != 0);
-
- switch(mndx) {
- case PM_GRAY_DRAGON:
- case PM_SILVER_DRAGON:
+ register struct permonst *mdat = mtmp->data;
+ int num;
+ struct obj *obj = (struct obj *)0;
+ struct obj* otmp = (struct obj*)0;
+ int x = mtmp->mx, y = mtmp->my;
+ int mndx = monsndx(mdat);
+ unsigned corpstatflags = corpseflags;
+ boolean burythem = ((corpstatflags & CORPSTAT_BURIED) != 0);
+
+ switch(mndx) {
+ case PM_GRAY_DRAGON:
+ case PM_SILVER_DRAGON:
#if 0 /* DEFERRED */
- case PM_SHIMMERING_DRAGON:
+ case PM_SHIMMERING_DRAGON:
#endif
- case PM_RED_DRAGON:
- case PM_ORANGE_DRAGON:
- case PM_WHITE_DRAGON:
- case PM_BLACK_DRAGON:
- case PM_BLUE_DRAGON:
- case PM_GREEN_DRAGON:
- case PM_YELLOW_DRAGON:
- /* Make dragon scales. This assumes that the order of the */
- /* dragons is the same as the order of the scales. */
- if (!rn2(mtmp->mrevived ? 20 : 3)) {
- num = GRAY_DRAGON_SCALES + monsndx(mdat) - PM_GRAY_DRAGON;
- obj = mksobj_at(num, x, y, FALSE, FALSE);
- obj->spe = 0;
- obj->cursed = obj->blessed = FALSE;
- }
- goto default_1;
-
- case PM_WHITE_UNICORN:
- case PM_GRAY_UNICORN:
- case PM_BLACK_UNICORN:
- if (mtmp->mrevived && rn2(2)) {
- if (canseemon(mtmp))
- pline("%s recently regrown horn crumbles to dust.",
- s_suffix(Monnam(mtmp)));
- } else {
- obj = mksobj_at(UNICORN_HORN, x, y, TRUE, FALSE);
- if (obj && mtmp->mrevived) obj->degraded_horn = 1;
- }
- goto default_1;
- case PM_LONG_WORM:
- (void) mksobj_at(WORM_TOOTH, x, y, TRUE, FALSE);
- goto default_1;
- case PM_VAMPIRE:
- case PM_VAMPIRE_LORD:
- /* include mtmp in the mkcorpstat() call */
- num = undead_to_corpse(mndx);
- corpstatflags |= CORPSTAT_INIT;
- obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, corpstatflags);
- obj->age -= 100; /* this is an *OLD* corpse */
- break;
- case PM_KOBOLD_MUMMY:
- case PM_DWARF_MUMMY:
- case PM_GNOME_MUMMY:
- case PM_ORC_MUMMY:
- case PM_ELF_MUMMY:
- case PM_HUMAN_MUMMY:
- case PM_GIANT_MUMMY:
- case PM_ETTIN_MUMMY:
- case PM_KOBOLD_ZOMBIE:
- case PM_DWARF_ZOMBIE:
- case PM_GNOME_ZOMBIE:
- case PM_ORC_ZOMBIE:
- case PM_ELF_ZOMBIE:
- case PM_HUMAN_ZOMBIE:
- case PM_GIANT_ZOMBIE:
- case PM_ETTIN_ZOMBIE:
- num = undead_to_corpse(mndx);
- corpstatflags |= CORPSTAT_INIT;
- obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, corpstatflags);
- obj->age -= 100; /* this is an *OLD* corpse */
- break;
- case PM_IRON_GOLEM:
- num = d(2,6);
- while (num--)
- obj = mksobj_at(IRON_CHAIN, x, y, TRUE, FALSE);
- free_mname(mtmp); /* don't christen obj */
- break;
- case PM_GLASS_GOLEM:
- num = d(2,4); /* very low chance of creating all glass gems */
- while (num--)
- obj = mksobj_at((LAST_GEM + rnd(9)), x, y, TRUE, FALSE);
- free_mname(mtmp);
- break;
- case PM_CLAY_GOLEM:
- obj = mksobj_at(ROCK, x, y, FALSE, FALSE);
- obj->quan = (long)(rn2(20) + 50);
- obj->owt = weight(obj);
- free_mname(mtmp);
- break;
- case PM_STONE_GOLEM:
- corpstatflags &= ~CORPSTAT_INIT;
- obj = mkcorpstat(STATUE, (struct monst *)0,
- mdat, x, y, corpstatflags);
- break;
- case PM_WOOD_GOLEM:
- num = d(2,4);
- while(num--) {
- obj = mksobj_at(QUARTERSTAFF, x, y, TRUE, FALSE);
- }
- free_mname(mtmp);
- break;
- case PM_LEATHER_GOLEM:
- num = d(2,4);
- while(num--)
- obj = mksobj_at(LEATHER_ARMOR, x, y, TRUE, FALSE);
- free_mname(mtmp);
- break;
- case PM_GOLD_GOLEM:
- /* Good luck gives more coins */
- obj = mkgold((long)(200 - rnl(101)), x, y);
- free_mname(mtmp);
- break;
- case PM_PAPER_GOLEM:
- num = rnd(4);
- while (num--)
- obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE, FALSE);
- free_mname(mtmp);
- break;
+ case PM_RED_DRAGON:
+ case PM_ORANGE_DRAGON:
+ case PM_WHITE_DRAGON:
+ case PM_BLACK_DRAGON:
+ case PM_BLUE_DRAGON:
+ case PM_GREEN_DRAGON:
+ case PM_YELLOW_DRAGON:
+ /* Make dragon scales. This assumes that the order of the */
+ /* dragons is the same as the order of the scales. */
+ if (!rn2(mtmp->mrevived ? 20 : 3)) {
+ num = GRAY_DRAGON_SCALES + monsndx(mdat) - PM_GRAY_DRAGON;
+ obj = mksobj_at(num, x, y, FALSE, FALSE);
+ obj->spe = 0;
+ obj->cursed = obj->blessed = FALSE;
+ }
+ goto default_1;
+
+ case PM_WHITE_UNICORN:
+ case PM_GRAY_UNICORN:
+ case PM_BLACK_UNICORN:
+ if (mtmp->mrevived && rn2(2)) {
+ if (canseemon(mtmp))
+ pline("%s recently regrown horn crumbles to dust.",
+ s_suffix(Monnam(mtmp)));
+ } else {
+ obj = mksobj_at(UNICORN_HORN, x, y, TRUE, FALSE);
+ if (obj && mtmp->mrevived) obj->degraded_horn = 1;
+ }
+ goto default_1;
+ case PM_LONG_WORM:
+ (void) mksobj_at(WORM_TOOTH, x, y, TRUE, FALSE);
+ goto default_1;
+ case PM_VAMPIRE:
+ case PM_VAMPIRE_LORD:
+ /* include mtmp in the mkcorpstat() call */
+ num = undead_to_corpse(mndx);
+ corpstatflags |= CORPSTAT_INIT;
+ obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, corpstatflags);
+ obj->age -= 100; /* this is an *OLD* corpse */
+ break;
+ case PM_KOBOLD_MUMMY:
+ case PM_DWARF_MUMMY:
+ case PM_GNOME_MUMMY:
+ case PM_ORC_MUMMY:
+ case PM_ELF_MUMMY:
+ case PM_HUMAN_MUMMY:
+ case PM_GIANT_MUMMY:
+ case PM_ETTIN_MUMMY:
+ case PM_KOBOLD_ZOMBIE:
+ case PM_DWARF_ZOMBIE:
+ case PM_GNOME_ZOMBIE:
+ case PM_ORC_ZOMBIE:
+ case PM_ELF_ZOMBIE:
+ case PM_HUMAN_ZOMBIE:
+ case PM_GIANT_ZOMBIE:
+ case PM_ETTIN_ZOMBIE:
+ num = undead_to_corpse(mndx);
+ corpstatflags |= CORPSTAT_INIT;
+ obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, corpstatflags);
+ obj->age -= 100; /* this is an *OLD* corpse */
+ break;
+ case PM_IRON_GOLEM:
+ num = d(2,6);
+ while (num--)
+ obj = mksobj_at(IRON_CHAIN, x, y, TRUE, FALSE);
+ free_mname(mtmp); /* don't christen obj */
+ break;
+ case PM_GLASS_GOLEM:
+ num = d(2,4); /* very low chance of creating all glass gems */
+ while (num--)
+ obj = mksobj_at((LAST_GEM + rnd(9)), x, y, TRUE, FALSE);
+ free_mname(mtmp);
+ break;
+ case PM_CLAY_GOLEM:
+ obj = mksobj_at(ROCK, x, y, FALSE, FALSE);
+ obj->quan = (long)(rn2(20) + 50);
+ obj->owt = weight(obj);
+ free_mname(mtmp);
+ break;
+ case PM_STONE_GOLEM:
+ corpstatflags &= ~CORPSTAT_INIT;
+ obj = mkcorpstat(STATUE, (struct monst *)0,
+ mdat, x, y, corpstatflags);
+ break;
+ case PM_WOOD_GOLEM:
+ num = d(2,4);
+ while(num--) {
+ obj = mksobj_at(QUARTERSTAFF, x, y, TRUE, FALSE);
+ }
+ free_mname(mtmp);
+ break;
+ case PM_LEATHER_GOLEM:
+ num = d(2,4);
+ while(num--)
+ obj = mksobj_at(LEATHER_ARMOR, x, y, TRUE, FALSE);
+ free_mname(mtmp);
+ break;
+ case PM_GOLD_GOLEM:
+ /* Good luck gives more coins */
+ obj = mkgold((long)(200 - rnl(101)), x, y);
+ free_mname(mtmp);
+ break;
+ case PM_PAPER_GOLEM:
+ num = rnd(4);
+ while (num--)
+ obj = mksobj_at(SCR_BLANK_PAPER, x, y, TRUE, FALSE);
+ free_mname(mtmp);
+ break;
/* expired puddings will congeal into a large blob
like dragons, relies on the order remaining consistent */
case PM_GRAY_OOZE:
case PM_BROWN_PUDDING:
case PM_GREEN_SLIME:
case PM_BLACK_PUDDING:
+ /* we have to do this here because most other places
+ * expect there to be an object coming back; not this one */
obj = mksobj_at(GLOB_OF_BLACK_PUDDING - (PM_BLACK_PUDDING - mndx),
- x, y, TRUE, FALSE);
+ x, y, TRUE, FALSE);
+
+ while ((obj && (otmp = obj_nexto(obj)) != (struct obj*)0)) {
+ pline("The %s coalesce.", makeplural(obj_typename(obj->otyp)));
+ obj = obj_meld(&obj, &otmp);
+ }
free_mname(mtmp);
- break;
- default_1:
- default:
+ return obj;
+ break;
+ default_1:
+ default:
if (mvitals[mndx].mvflags & G_NOCORPSE)
return (struct obj *)0;
else {
return obj;
}
}
- break;
- }
- /* All special cases should precede the G_NOCORPSE check */
-
- /* if polymorph or undead turning has killed this monster,
- prevent the same attack beam from hitting its corpse */
- if (context.bypasses) bypass_obj(obj);
-
- if (has_mname(mtmp))
- obj = oname(obj, MNAME(mtmp));
-
- /* Avoid "It was hidden under a green mold corpse!"
- * during Blind combat. An unseen monster referred to as "it"
- * could be killed and leave a corpse. If a hider then hid
- * underneath it, you could be told the corpse type of a
- * monster that you never knew was there without this.
- * The code in hitmu() substitutes the word "something"
- * if the corpses obj->dknown is 0.
- */
- if (Blind && !sensemon(mtmp)) obj->dknown = 0;
+ break;
+ }
+ /* All special cases should precede the G_NOCORPSE check */
+
+ /* if polymorph or undead turning has killed this monster,
+ prevent the same attack beam from hitting its corpse */
+ if (context.bypasses) bypass_obj(obj);
+
+ if (has_mname(mtmp))
+ obj = oname(obj, MNAME(mtmp));
+
+ /* Avoid "It was hidden under a green mold corpse!"
+ * during Blind combat. An unseen monster referred to as "it"
+ * could be killed and leave a corpse. If a hider then hid
+ * underneath it, you could be told the corpse type of a
+ * monster that you never knew was there without this.
+ * The code in hitmu() substitutes the word "something"
+ * if the corpses obj->dknown is 0.
+ */
+ if (Blind && !sensemon(mtmp)) obj->dknown = 0;
- stackobj(obj);
- newsym(x, y);
- return obj;
+ stackobj(obj);
+ newsym(x, y);
+ return obj;
}
/* check mtmp and water/lava for compatibility, 0 (survived), 1 (died) */
boolean inpool, inlava, infountain;
inpool = is_pool(mtmp->mx,mtmp->my) &&
- !is_flyer(mtmp->data) && !is_floater(mtmp->data);
+ !is_flyer(mtmp->data) && !is_floater(mtmp->data);
inlava = is_lava(mtmp->mx,mtmp->my) &&
- !is_flyer(mtmp->data) && !is_floater(mtmp->data);
+ !is_flyer(mtmp->data) && !is_floater(mtmp->data);
infountain = IS_FOUNTAIN(levl[mtmp->mx][mtmp->my].typ);
- /* Flying and levitation keeps our steed out of the liquid */
- /* (but not water-walking or swimming) */
- if (mtmp == u.usteed && (Flying || Levitation))
- return (0);
+ /* Flying and levitation keeps our steed out of the liquid */
+ /* (but not water-walking or swimming) */
+ if (mtmp == u.usteed && (Flying || Levitation))
+ return (0);
/* Gremlin multiplying won't go on forever since the hit points
* keep going down, and when it gets to 1 hit point the clone
* function will fail.
*/
if (mtmp->data == &mons[PM_GREMLIN] && (inpool || infountain) && rn2(3)) {
- if (split_mon(mtmp, (struct monst *)0))
- dryup(mtmp->mx, mtmp->my, FALSE);
- if (inpool) water_damage_chain(mtmp->minvent, FALSE);
- return (0);
+ if (split_mon(mtmp, (struct monst *)0))
+ dryup(mtmp->mx, mtmp->my, FALSE);
+ if (inpool) water_damage_chain(mtmp->minvent, FALSE);
+ return (0);
} else if (mtmp->data == &mons[PM_IRON_GOLEM] && inpool && !rn2(5)) {
- int dam = d(2,6);
- if (cansee(mtmp->mx,mtmp->my))
- pline("%s rusts.", Monnam(mtmp));
- mtmp->mhp -= dam;
- if (mtmp->mhpmax > dam) mtmp->mhpmax -= dam;
- if (mtmp->mhp < 1) {
- mondead(mtmp);
- if (mtmp->mhp < 1) return (1);
- }
- water_damage_chain(mtmp->minvent, FALSE);
- return (0);
+ int dam = d(2,6);
+ if (cansee(mtmp->mx,mtmp->my))
+ pline("%s rusts.", Monnam(mtmp));
+ mtmp->mhp -= dam;
+ if (mtmp->mhpmax > dam) mtmp->mhpmax -= dam;
+ if (mtmp->mhp < 1) {
+ mondead(mtmp);
+ if (mtmp->mhp < 1) return (1);
+ }
+ water_damage_chain(mtmp->minvent, FALSE);
+ return (0);
}
if (inlava) {
- /*
- * Lava effects much as water effects. Lava likers are able to
- * protect their stuff. Fire resistant monsters can only protect
- * themselves --ALI
- */
- if (!is_clinger(mtmp->data) && !likes_lava(mtmp->data)) {
- if (!resists_fire(mtmp)) {
- if (cansee(mtmp->mx,mtmp->my))
- pline("%s %s.", Monnam(mtmp),
- mtmp->data == &mons[PM_WATER_ELEMENTAL] ?
- "boils away" : "burns to a crisp");
- mondead(mtmp);
- }
- else {
- if (--mtmp->mhp < 1) {
- if (cansee(mtmp->mx,mtmp->my))
- pline("%s surrenders to the fire.", Monnam(mtmp));
- mondead(mtmp);
- }
- else if (cansee(mtmp->mx,mtmp->my))
- pline("%s burns slightly.", Monnam(mtmp));
- }
- if (mtmp->mhp > 0) {
+ /*
+ * Lava effects much as water effects. Lava likers are able to
+ * protect their stuff. Fire resistant monsters can only protect
+ * themselves --ALI
+ */
+ if (!is_clinger(mtmp->data) && !likes_lava(mtmp->data)) {
+ if (!resists_fire(mtmp)) {
+ if (cansee(mtmp->mx,mtmp->my))
+ pline("%s %s.", Monnam(mtmp),
+ mtmp->data == &mons[PM_WATER_ELEMENTAL] ?
+ "boils away" : "burns to a crisp");
+ mondead(mtmp);
+ }
+ else {
+ if (--mtmp->mhp < 1) {
+ if (cansee(mtmp->mx,mtmp->my))
+ pline("%s surrenders to the fire.", Monnam(mtmp));
+ mondead(mtmp);
+ }
+ else if (cansee(mtmp->mx,mtmp->my))
+ pline("%s burns slightly.", Monnam(mtmp));
+ }
+ if (mtmp->mhp > 0) {
(void) fire_damage_chain(mtmp->minvent, FALSE, FALSE, mtmp->mx,
mtmp->my);
- (void) rloc(mtmp, FALSE);
- return 0;
- }
- return (1);
- }
+ (void) rloc(mtmp, FALSE);
+ return 0;
+ }
+ return (1);
+ }
} else if (inpool) {
- /* Most monsters drown in pools. flooreffects() will take care of
- * water damage to dead monsters' inventory, but survivors need to
- * be handled here. Swimmers are able to protect their stuff...
- */
- if (!is_clinger(mtmp->data)
- && !is_swimmer(mtmp->data) && !amphibious(mtmp->data)) {
- if (cansee(mtmp->mx,mtmp->my)) {
- pline("%s drowns.", Monnam(mtmp));
- }
- if (u.ustuck && u.uswallow && u.ustuck == mtmp) {
- /* This can happen after a purple worm plucks you off a
- flying steed while you are over water. */
- pline("%s sinks as water rushes in and flushes you out.",
- Monnam(mtmp));
- }
- mondead(mtmp);
- if (mtmp->mhp > 0) {
- water_damage_chain(mtmp->minvent, FALSE);
- (void) rloc(mtmp, FALSE);
- return 0;
- }
- return (1);
- }
+ /* Most monsters drown in pools. flooreffects() will take care of
+ * water damage to dead monsters' inventory, but survivors need to
+ * be handled here. Swimmers are able to protect their stuff...
+ */
+ if (!is_clinger(mtmp->data)
+ && !is_swimmer(mtmp->data) && !amphibious(mtmp->data)) {
+ if (cansee(mtmp->mx,mtmp->my)) {
+ pline("%s drowns.", Monnam(mtmp));
+ }
+ if (u.ustuck && u.uswallow && u.ustuck == mtmp) {
+ /* This can happen after a purple worm plucks you off a
+ flying steed while you are over water. */
+ pline("%s sinks as water rushes in and flushes you out.",
+ Monnam(mtmp));
+ }
+ mondead(mtmp);
+ if (mtmp->mhp > 0) {
+ water_damage_chain(mtmp->minvent, FALSE);
+ (void) rloc(mtmp, FALSE);
+ return 0;
+ }
+ return (1);
+ }
} else {
- /* but eels have a difficult time outside */
- if (mtmp->data->mlet == S_EEL && !Is_waterlevel(&u.uz)) {
- /* as mhp gets lower, the rate of further loss slows down */
- if (mtmp->mhp > 1 && rn2(mtmp->mhp) > rn2(8)) mtmp->mhp--;
- monflee(mtmp, 2, FALSE, FALSE);
- }
+ /* but eels have a difficult time outside */
+ if (mtmp->data->mlet == S_EEL && !Is_waterlevel(&u.uz)) {
+ /* as mhp gets lower, the rate of further loss slows down */
+ if (mtmp->mhp > 1 && rn2(mtmp->mhp) > rn2(8)) mtmp->mhp--;
+ monflee(mtmp, 2, FALSE, FALSE);
+ }
}
return (0);
}
* both adjustments have negligible effect on higher speeds.
*/
if (mon->mspeed == MSLOW)
- mmove = (2 * mmove + 1) / 3;
+ mmove = (2 * mmove + 1) / 3;
else if (mon->mspeed == MFAST)
- mmove = (4 * mmove + 2) / 3;
+ mmove = (4 * mmove + 2) / 3;
if (mon == u.usteed) {
- if (u.ugallop && context.mv) {
- /* average movement is 1.50 times normal */
- mmove = ((rn2(2) ? 4 : 5) * mmove) / 3;
- }
+ if (u.ugallop && context.mv) {
+ /* average movement is 1.50 times normal */
+ mmove = ((rn2(2) ? 4 : 5) * mmove) / 3;
+ }
} else if (mmove) {
- /* vary movement points allocated to slightly reduce predictability;
- random increment (avg +2) exceeds random decrement (avg +1) by
- a small amount; normal speed monsters will occasionally get an
- extra move and slow ones won't be quite as slow */
- mmove += rn2(5) - rn2(3); /* + 0..4 - 0..2, average net +1 */
- if (mmove < 1) mmove = 1;
+ /* vary movement points allocated to slightly reduce predictability;
+ random increment (avg +2) exceeds random decrement (avg +1) by
+ a small amount; normal speed monsters will occasionally get an
+ extra move and slow ones won't be quite as slow */
+ mmove += rn2(5) - rn2(3); /* + 0..4 - 0..2, average net +1 */
+ if (mmove < 1) mmove = 1;
}
return mmove;
struct monst *mtmp;
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
+ if (DEADMONSTER(mtmp)) continue;
- /* must check non-moving monsters once/turn in case
- * they managed to end up in liquid */
- if (mtmp->data->mmove == 0) {
- if (vision_full_recalc) vision_recalc(0);
- if (minliquid(mtmp)) continue;
- }
+ /* must check non-moving monsters once/turn in case
+ * they managed to end up in liquid */
+ if (mtmp->data->mmove == 0) {
+ if (vision_full_recalc) vision_recalc(0);
+ if (minliquid(mtmp)) continue;
+ }
- /* regenerate hit points */
- mon_regen(mtmp, FALSE);
+ /* regenerate hit points */
+ mon_regen(mtmp, FALSE);
- /* possibly polymorph shapechangers and lycanthropes */
- if (mtmp->cham >= LOW_PM) {
- if (is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE)
- decide_to_shapeshift(mtmp,0);
- else if (!rn2(6))
- (void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
- }
- were_change(mtmp);
+ /* possibly polymorph shapechangers and lycanthropes */
+ if (mtmp->cham >= LOW_PM) {
+ if (is_vampshifter(mtmp) || mtmp->data->mlet == S_VAMPIRE)
+ decide_to_shapeshift(mtmp,0);
+ else if (!rn2(6))
+ (void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
+ }
+ were_change(mtmp);
- /* gradually time out temporary problems */
- if (mtmp->mblinded && !--mtmp->mblinded)
- mtmp->mcansee = 1;
- if (mtmp->mfrozen && !--mtmp->mfrozen)
- mtmp->mcanmove = 1;
- if (mtmp->mfleetim && !--mtmp->mfleetim)
- mtmp->mflee = 0;
+ /* gradually time out temporary problems */
+ if (mtmp->mblinded && !--mtmp->mblinded)
+ mtmp->mcansee = 1;
+ if (mtmp->mfrozen && !--mtmp->mfrozen)
+ mtmp->mcanmove = 1;
+ if (mtmp->mfleetim && !--mtmp->mfleetim)
+ mtmp->mflee = 0;
- /* FIXME: mtmp->mlstmv ought to be updated here */
+ /* FIXME: mtmp->mlstmv ought to be updated here */
}
}
for(mtmp = fmon; mtmp; mtmp = nmtmp) {
#ifdef SAFERHANGUP
- if (program_state.done_hup) {
- somebody_can_move = FALSE;
- break;
- }
+ if (program_state.done_hup) {
+ somebody_can_move = FALSE;
+ break;
+ }
#endif
- nmtmp = mtmp->nmon;
- /* one dead monster needs to perform a move after death:
- vault guard whose temporary corridor is still on the map */
- if (mtmp->isgd && !mtmp->mx && mtmp->mhp <= 0) (void)gd_move(mtmp);
- if (DEADMONSTER(mtmp)) continue;
-
- /* Find a monster that we have not treated yet. */
- if(mtmp->movement < NORMAL_SPEED)
- continue;
-
- mtmp->movement -= NORMAL_SPEED;
- if (mtmp->movement >= NORMAL_SPEED)
- somebody_can_move = TRUE;
-
- if (vision_full_recalc) vision_recalc(0); /* vision! */
-
- if (minliquid(mtmp)) continue;
-
- if (is_hider(mtmp->data)) {
- /* unwatched mimics and piercers may hide again [MRS] */
- if(restrap(mtmp)) continue;
- if(mtmp->m_ap_type == M_AP_FURNITURE ||
- mtmp->m_ap_type == M_AP_OBJECT)
- continue;
- if(mtmp->mundetected) continue;
- } else if (mtmp->data->mlet == S_EEL && !mtmp->mundetected &&
- (mtmp->mflee || distu(mtmp->mx, mtmp->my) > 2) &&
- !canseemon(mtmp) && !rn2(4)) {
- /* some eels end up stuck in isolated pools, where they
- can't--or at least won't--move, so they never reach
- their post-move chance to re-hide */
- if (hideunder(mtmp)) continue;
- }
-
- /* continue if the monster died fighting */
- if (Conflict && !mtmp->iswiz && mtmp->mcansee) {
- /* Note:
- * Conflict does not take effect in the first round.
- * Therefore, A monster when stepping into the area will
- * get to swing at you.
- *
- * The call to fightm() must be _last_. The monster might
- * have died if it returns 1.
- */
- if (couldsee(mtmp->mx,mtmp->my) &&
- (distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) &&
- fightm(mtmp))
- continue; /* mon might have died */
- }
- if(dochugw(mtmp)) /* otherwise just move the monster */
- continue;
+ nmtmp = mtmp->nmon;
+ /* one dead monster needs to perform a move after death:
+ vault guard whose temporary corridor is still on the map */
+ if (mtmp->isgd && !mtmp->mx && mtmp->mhp <= 0) (void)gd_move(mtmp);
+ if (DEADMONSTER(mtmp)) continue;
+
+ /* Find a monster that we have not treated yet. */
+ if(mtmp->movement < NORMAL_SPEED)
+ continue;
+
+ mtmp->movement -= NORMAL_SPEED;
+ if (mtmp->movement >= NORMAL_SPEED)
+ somebody_can_move = TRUE;
+
+ if (vision_full_recalc) vision_recalc(0); /* vision! */
+
+ if (minliquid(mtmp)) continue;
+
+ if (is_hider(mtmp->data)) {
+ /* unwatched mimics and piercers may hide again [MRS] */
+ if(restrap(mtmp)) continue;
+ if(mtmp->m_ap_type == M_AP_FURNITURE ||
+ mtmp->m_ap_type == M_AP_OBJECT)
+ continue;
+ if(mtmp->mundetected) continue;
+ } else if (mtmp->data->mlet == S_EEL && !mtmp->mundetected &&
+ (mtmp->mflee || distu(mtmp->mx, mtmp->my) > 2) &&
+ !canseemon(mtmp) && !rn2(4)) {
+ /* some eels end up stuck in isolated pools, where they
+ can't--or at least won't--move, so they never reach
+ their post-move chance to re-hide */
+ if (hideunder(mtmp)) continue;
+ }
+
+ /* continue if the monster died fighting */
+ if (Conflict && !mtmp->iswiz && mtmp->mcansee) {
+ /* Note:
+ * Conflict does not take effect in the first round.
+ * Therefore, A monster when stepping into the area will
+ * get to swing at you.
+ *
+ * The call to fightm() must be _last_. The monster might
+ * have died if it returns 1.
+ */
+ if (couldsee(mtmp->mx,mtmp->my) &&
+ (distu(mtmp->mx,mtmp->my) <= BOLT_LIM*BOLT_LIM) &&
+ fightm(mtmp))
+ continue; /* mon might have died */
+ }
+ if(dochugw(mtmp)) /* otherwise just move the monster */
+ continue;
}
if (any_light_source())
- vision_full_recalc = 1; /* in case a mon moved with a light source */
+ vision_full_recalc = 1; /* in case a mon moved with a light source */
dmonsfree(); /* remove all dead monsters */
/* a monster may have levteleported player -dlc */
if (u.utotype) {
- deferred_goto();
- /* changed levels, so these monsters are dormant */
- somebody_can_move = FALSE;
+ deferred_goto();
+ /* changed levels, so these monsters are dormant */
+ somebody_can_move = FALSE;
}
return somebody_can_move;
}
#define mstoning(obj) (ofood(obj) && \
- (touch_petrifies(&mons[(obj)->corpsenm]) || \
- (obj)->corpsenm == PM_MEDUSA))
+ (touch_petrifies(&mons[(obj)->corpsenm]) || \
+ (obj)->corpsenm == PM_MEDUSA))
/*
* Maybe eat a metallic object (not just gold).
*/
int
meatmetal(mtmp)
- register struct monst *mtmp;
-{
- register struct obj *otmp;
- struct permonst *ptr;
- int poly, grow, heal, mstone;
-
- /* If a pet, eating is handled separately, in dog.c */
- if (mtmp->mtame) return 0;
-
- /* Eats topmost metal object if it is there */
- for (otmp = level.objects[mtmp->mx][mtmp->my];
- otmp; otmp = otmp->nexthere) {
- if (mtmp->data == &mons[PM_RUST_MONSTER] && !is_rustprone(otmp))
- continue;
- if (is_metallic(otmp) && !obj_resists(otmp, 5, 95) &&
- touch_artifact(otmp,mtmp)) {
- if (mtmp->data == &mons[PM_RUST_MONSTER] && otmp->oerodeproof) {
- if (canseemon(mtmp) && flags.verbose) {
- pline("%s eats %s!",
- Monnam(mtmp),
- distant_name(otmp,doname));
- }
- /* The object's rustproofing is gone now */
- otmp->oerodeproof = 0;
- mtmp->mstun = 1;
- if (canseemon(mtmp) && flags.verbose) {
- pline("%s spits %s out in disgust!",
- Monnam(mtmp), distant_name(otmp,doname));
- }
- /* KMH -- Don't eat indigestible/choking objects */
- } else if (otmp->otyp != AMULET_OF_STRANGULATION &&
- otmp->otyp != RIN_SLOW_DIGESTION) {
- if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
- pline("%s eats %s!", Monnam(mtmp),
- distant_name(otmp,doname));
- else if (flags.verbose)
- You_hear("a crunching sound.");
- mtmp->meating = otmp->owt/2 + 1;
- /* Heal up to the object's weight in hp */
- if (mtmp->mhp < mtmp->mhpmax) {
- mtmp->mhp += objects[otmp->otyp].oc_weight;
- if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
- }
- if(otmp == uball) {
- unpunish();
- delobj(otmp);
- } else if (otmp == uchain) {
- unpunish(); /* frees uchain */
- } else {
- poly = polyfodder(otmp);
- grow = mlevelgain(otmp);
- heal = mhealup(otmp);
- mstone = mstoning(otmp);
- delobj(otmp);
- ptr = mtmp->data;
- if (poly) {
- if (newcham(mtmp, (struct permonst *)0,
- FALSE, FALSE))
- ptr = mtmp->data;
- } else if (grow) {
- ptr = grow_up(mtmp, (struct monst *)0);
- } else if (mstone) {
- if (poly_when_stoned(ptr)) {
- mon_to_stone(mtmp);
- ptr = mtmp->data;
- } else if (!resists_ston(mtmp)) {
- if (canseemon(mtmp))
- pline("%s turns to stone!", Monnam(mtmp));
- monstone(mtmp);
- ptr = (struct permonst *)0;
- }
- } else if (heal) {
- mtmp->mhp = mtmp->mhpmax;
- }
- if (!ptr) return 2; /* it died */
- }
- /* Left behind a pile? */
- if (rnd(25) < 3)
- (void)mksobj_at(ROCK, mtmp->mx, mtmp->my, TRUE, FALSE);
- newsym(mtmp->mx, mtmp->my);
- return 1;
- }
- }
- }
- return 0;
+ register struct monst *mtmp;
+{
+ register struct obj *otmp;
+ struct permonst *ptr;
+ int poly, grow, heal, mstone;
+
+ /* If a pet, eating is handled separately, in dog.c */
+ if (mtmp->mtame) return 0;
+
+ /* Eats topmost metal object if it is there */
+ for (otmp = level.objects[mtmp->mx][mtmp->my];
+ otmp; otmp = otmp->nexthere) {
+ if (mtmp->data == &mons[PM_RUST_MONSTER] && !is_rustprone(otmp))
+ continue;
+ if (is_metallic(otmp) && !obj_resists(otmp, 5, 95) &&
+ touch_artifact(otmp,mtmp)) {
+ if (mtmp->data == &mons[PM_RUST_MONSTER] && otmp->oerodeproof) {
+ if (canseemon(mtmp) && flags.verbose) {
+ pline("%s eats %s!",
+ Monnam(mtmp),
+ distant_name(otmp,doname));
+ }
+ /* The object's rustproofing is gone now */
+ otmp->oerodeproof = 0;
+ mtmp->mstun = 1;
+ if (canseemon(mtmp) && flags.verbose) {
+ pline("%s spits %s out in disgust!",
+ Monnam(mtmp), distant_name(otmp,doname));
+ }
+ /* KMH -- Don't eat indigestible/choking objects */
+ } else if (otmp->otyp != AMULET_OF_STRANGULATION &&
+ otmp->otyp != RIN_SLOW_DIGESTION) {
+ if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
+ pline("%s eats %s!", Monnam(mtmp),
+ distant_name(otmp,doname));
+ else if (flags.verbose)
+ You_hear("a crunching sound.");
+ mtmp->meating = otmp->owt/2 + 1;
+ /* Heal up to the object's weight in hp */
+ if (mtmp->mhp < mtmp->mhpmax) {
+ mtmp->mhp += objects[otmp->otyp].oc_weight;
+ if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
+ }
+ if(otmp == uball) {
+ unpunish();
+ delobj(otmp);
+ } else if (otmp == uchain) {
+ unpunish(); /* frees uchain */
+ } else {
+ poly = polyfodder(otmp);
+ grow = mlevelgain(otmp);
+ heal = mhealup(otmp);
+ mstone = mstoning(otmp);
+ delobj(otmp);
+ ptr = mtmp->data;
+ if (poly) {
+ if (newcham(mtmp, (struct permonst *)0,
+ FALSE, FALSE))
+ ptr = mtmp->data;
+ } else if (grow) {
+ ptr = grow_up(mtmp, (struct monst *)0);
+ } else if (mstone) {
+ if (poly_when_stoned(ptr)) {
+ mon_to_stone(mtmp);
+ ptr = mtmp->data;
+ } else if (!resists_ston(mtmp)) {
+ if (canseemon(mtmp))
+ pline("%s turns to stone!", Monnam(mtmp));
+ monstone(mtmp);
+ ptr = (struct permonst *)0;
+ }
+ } else if (heal) {
+ mtmp->mhp = mtmp->mhpmax;
+ }
+ if (!ptr) return 2; /* it died */
+ }
+ /* Left behind a pile? */
+ if (rnd(25) < 3)
+ (void)mksobj_at(ROCK, mtmp->mx, mtmp->my, TRUE, FALSE);
+ newsym(mtmp->mx, mtmp->my);
+ return 1;
+ }
+ }
+ }
+ return 0;
}
/* monster eats a pile of objects */
int
meatobj(mtmp) /* for gelatinous cubes */
- register struct monst *mtmp;
-{
- register struct obj *otmp, *otmp2;
- struct permonst *ptr, *original_ptr = mtmp->data;
- int poly, grow, heal, count = 0, ecount = 0;
- char buf[BUFSZ];
-
- buf[0] = '\0';
- /* If a pet, eating is handled separately, in dog.c */
- if (mtmp->mtame) return 0;
-
- /* eat organic objects, including cloth and wood, if present;
- engulf others, except huge rocks and metal attached to player
- [despite comment at top, doesn't assume that eater is a g.cube] */
- for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
- otmp2 = otmp->nexthere;
-
- /* touch senstive items */
- if (otmp->otyp == CORPSE &&
- is_rider(&mons[otmp->corpsenm])) {
- /* Rider corpse isn't just inedible; can't engulf it either */
- (void)revive_corpse(otmp);
-
- /* untouchable (or inaccessible) items */
- } else if ((otmp->otyp == CORPSE &&
- touch_petrifies(&mons[otmp->corpsenm]) &&
- !resists_ston(mtmp)) ||
- /* don't engulf boulders and statues or ball&chain */
- otmp->oclass == ROCK_CLASS ||
- otmp == uball || otmp == uchain) {
- /* do nothing--neither eaten nor engulfed */
- continue;
-
- /* inedible items -- engulf these */
- } else if (!is_organic(otmp) ||
- obj_resists(otmp, 5, 95) ||
- !touch_artifact(otmp, mtmp) ||
- /* redundant due to non-organic composition but
- included for emphasis */
- (otmp->otyp == AMULET_OF_STRANGULATION ||
- otmp->otyp == RIN_SLOW_DIGESTION) ||
- /* cockatrice corpses handled above; this
- touch_petrifies() check catches eggs */
- ((otmp->otyp == CORPSE || otmp->otyp == EGG) &&
- ((touch_petrifies(&mons[otmp->corpsenm]) &&
- !resists_ston(mtmp)) ||
- (otmp->corpsenm == PM_GREEN_SLIME &&
- !slimeproof(mtmp->data))))) {
- /* engulf */
- ++ecount;
- if (ecount == 1)
- Sprintf(buf, "%s engulfs %s.", Monnam(mtmp),
- distant_name(otmp,doname));
- else if (ecount == 2)
- Sprintf(buf, "%s engulfs several objects.", Monnam(mtmp));
- obj_extract_self(otmp);
- (void) mpickobj(mtmp, otmp); /* slurp */
-
- /* lastly, edible items; yum! */
- } else {
- /* devour */
- ++count;
- if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
- pline("%s eats %s!", Monnam(mtmp),
- distant_name(otmp, doname));
- else if (flags.verbose)
- You_hear("a slurping sound.");
- /* Heal up to the object's weight in hp */
- if (mtmp->mhp < mtmp->mhpmax) {
- mtmp->mhp += objects[otmp->otyp].oc_weight;
- if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
- }
- if (Has_contents(otmp)) {
- register struct obj *otmp3;
- /* contents of eaten containers become engulfed; this
- is arbitrary, but otherwise g.cubes are too powerful */
- while ((otmp3 = otmp->cobj) != 0) {
- obj_extract_self(otmp3);
- if (otmp->otyp == ICE_BOX && otmp3->otyp == CORPSE) {
- otmp3->age = monstermoves - otmp3->age;
- start_corpse_timeout(otmp3);
- }
- (void) mpickobj(mtmp, otmp3);
- }
- }
- poly = polyfodder(otmp);
- grow = mlevelgain(otmp);
- heal = mhealup(otmp);
- delobj(otmp); /* munch */
- ptr = mtmp->data;
- if (poly) {
- if (newcham(mtmp, (struct permonst *)0, FALSE, FALSE))
- ptr = mtmp->data;
- } else if (grow) {
- ptr = grow_up(mtmp, (struct monst *)0);
- } else if (heal) {
- mtmp->mhp = mtmp->mhpmax;
- }
- /* in case it polymorphed or died */
- if (ptr != original_ptr)
- return !ptr ? 2 : 1;
- }
-
- /* Engulf & devour is instant, so don't set meating */
- if (mtmp->minvis) newsym(mtmp->mx, mtmp->my);
- }
-
- if (ecount > 0) {
- if (cansee(mtmp->mx, mtmp->my) && flags.verbose && buf[0])
- pline1(buf);
- else if (flags.verbose)
- You_hear("%s slurping sound%s.",
- ecount == 1 ? "a" : "several",
- ecount == 1 ? "" : "s");
- }
- return ((count > 0) || (ecount > 0)) ? 1 : 0;
+ register struct monst *mtmp;
+{
+ register struct obj *otmp, *otmp2;
+ struct permonst *ptr, *original_ptr = mtmp->data;
+ int poly, grow, heal, count = 0, ecount = 0;
+ char buf[BUFSZ];
+
+ buf[0] = '\0';
+ /* If a pet, eating is handled separately, in dog.c */
+ if (mtmp->mtame) return 0;
+
+ /* eat organic objects, including cloth and wood, if present;
+ engulf others, except huge rocks and metal attached to player
+ [despite comment at top, doesn't assume that eater is a g.cube] */
+ for (otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
+ otmp2 = otmp->nexthere;
+
+ /* touch senstive items */
+ if (otmp->otyp == CORPSE &&
+ is_rider(&mons[otmp->corpsenm])) {
+ /* Rider corpse isn't just inedible; can't engulf it either */
+ (void)revive_corpse(otmp);
+
+ /* untouchable (or inaccessible) items */
+ } else if ((otmp->otyp == CORPSE &&
+ touch_petrifies(&mons[otmp->corpsenm]) &&
+ !resists_ston(mtmp)) ||
+ /* don't engulf boulders and statues or ball&chain */
+ otmp->oclass == ROCK_CLASS ||
+ otmp == uball || otmp == uchain) {
+ /* do nothing--neither eaten nor engulfed */
+ continue;
+
+ /* inedible items -- engulf these */
+ } else if (!is_organic(otmp) ||
+ obj_resists(otmp, 5, 95) ||
+ !touch_artifact(otmp, mtmp) ||
+ /* redundant due to non-organic composition but
+ included for emphasis */
+ (otmp->otyp == AMULET_OF_STRANGULATION ||
+ otmp->otyp == RIN_SLOW_DIGESTION) ||
+ /* cockatrice corpses handled above; this
+ touch_petrifies() check catches eggs */
+ ((otmp->otyp == CORPSE || otmp->otyp == EGG) &&
+ ((touch_petrifies(&mons[otmp->corpsenm]) &&
+ !resists_ston(mtmp)) ||
+ (otmp->corpsenm == PM_GREEN_SLIME &&
+ !slimeproof(mtmp->data))))) {
+ /* engulf */
+ ++ecount;
+ if (ecount == 1)
+ Sprintf(buf, "%s engulfs %s.", Monnam(mtmp),
+ distant_name(otmp,doname));
+ else if (ecount == 2)
+ Sprintf(buf, "%s engulfs several objects.", Monnam(mtmp));
+ obj_extract_self(otmp);
+ (void) mpickobj(mtmp, otmp); /* slurp */
+
+ /* lastly, edible items; yum! */
+ } else {
+ /* devour */
+ ++count;
+ if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
+ pline("%s eats %s!", Monnam(mtmp),
+ distant_name(otmp, doname));
+ else if (flags.verbose)
+ You_hear("a slurping sound.");
+ /* Heal up to the object's weight in hp */
+ if (mtmp->mhp < mtmp->mhpmax) {
+ mtmp->mhp += objects[otmp->otyp].oc_weight;
+ if (mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
+ }
+ if (Has_contents(otmp)) {
+ register struct obj *otmp3;
+ /* contents of eaten containers become engulfed; this
+ is arbitrary, but otherwise g.cubes are too powerful */
+ while ((otmp3 = otmp->cobj) != 0) {
+ obj_extract_self(otmp3);
+ if (otmp->otyp == ICE_BOX && otmp3->otyp == CORPSE) {
+ otmp3->age = monstermoves - otmp3->age;
+ start_corpse_timeout(otmp3);
+ }
+ (void) mpickobj(mtmp, otmp3);
+ }
+ }
+ poly = polyfodder(otmp);
+ grow = mlevelgain(otmp);
+ heal = mhealup(otmp);
+ delobj(otmp); /* munch */
+ ptr = mtmp->data;
+ if (poly) {
+ if (newcham(mtmp, (struct permonst *)0, FALSE, FALSE))
+ ptr = mtmp->data;
+ } else if (grow) {
+ ptr = grow_up(mtmp, (struct monst *)0);
+ } else if (heal) {
+ mtmp->mhp = mtmp->mhpmax;
+ }
+ /* in case it polymorphed or died */
+ if (ptr != original_ptr)
+ return !ptr ? 2 : 1;
+ }
+
+ /* Engulf & devour is instant, so don't set meating */
+ if (mtmp->minvis) newsym(mtmp->mx, mtmp->my);
+ }
+
+ if (ecount > 0) {
+ if (cansee(mtmp->mx, mtmp->my) && flags.verbose && buf[0])
+ pline1(buf);
+ else if (flags.verbose)
+ You_hear("%s slurping sound%s.",
+ ecount == 1 ? "a" : "several",
+ ecount == 1 ? "" : "s");
+ }
+ return ((count > 0) || (ecount > 0)) ? 1 : 0;
}
void
mpickgold(mtmp)
- register struct monst *mtmp;
+ register struct monst *mtmp;
{
register struct obj *gold;
int mat_idx;
if ((gold = g_at(mtmp->mx, mtmp->my)) != 0) {
- mat_idx = objects[gold->otyp].oc_material;
+ mat_idx = objects[gold->otyp].oc_material;
obj_extract_self(gold);
add_to_minv(mtmp, gold);
- if (cansee(mtmp->mx, mtmp->my) ) {
- if (flags.verbose && !mtmp->isgd)
- pline("%s picks up some %s.", Monnam(mtmp),
- mat_idx == GOLD ? "gold" : "money");
- newsym(mtmp->mx, mtmp->my);
- }
+ if (cansee(mtmp->mx, mtmp->my) ) {
+ if (flags.verbose && !mtmp->isgd)
+ pline("%s picks up some %s.", Monnam(mtmp),
+ mat_idx == GOLD ? "gold" : "money");
+ newsym(mtmp->mx, mtmp->my);
+ }
}
}
boolean
mpickstuff(mtmp, str)
- register struct monst *mtmp;
- register const char *str;
+ register struct monst *mtmp;
+ register const char *str;
{
- register struct obj *otmp, *otmp2;
+ register struct obj *otmp, *otmp2;
/* prevent shopkeepers from leaving the door of their shop */
- if(mtmp->isshk && inhishop(mtmp)) return FALSE;
+ if(mtmp->isshk && inhishop(mtmp)) return FALSE;
- for(otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
- otmp2 = otmp->nexthere;
+ for(otmp = level.objects[mtmp->mx][mtmp->my]; otmp; otmp = otmp2) {
+ otmp2 = otmp->nexthere;
/* Nymphs take everything. Most monsters don't pick up corpses. */
- if (!str ? searches_for_item(mtmp,otmp) :
- !!(index(str, otmp->oclass))) {
- if (otmp->otyp == CORPSE && mtmp->data->mlet != S_NYMPH &&
- /* let a handful of corpse types thru to can_carry() */
- !touch_petrifies(&mons[otmp->corpsenm]) &&
- otmp->corpsenm != PM_LIZARD &&
- !acidic(&mons[otmp->corpsenm])) continue;
- if (!touch_artifact(otmp,mtmp)) continue;
- if (!can_carry(mtmp,otmp)) continue;
- if (is_pool(mtmp->mx,mtmp->my)) continue;
- if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
- pline("%s picks up %s.", Monnam(mtmp),
- (distu(mtmp->mx, mtmp->my) <= 5) ?
- doname(otmp) : distant_name(otmp, doname));
- obj_extract_self(otmp); /* remove from floor */
- (void) mpickobj(mtmp, otmp); /* may merge and free otmp */
- m_dowear(mtmp, FALSE);
- newsym(mtmp->mx, mtmp->my);
- return TRUE; /* pick only one object */
- }
- }
- return FALSE;
+ if (!str ? searches_for_item(mtmp,otmp) :
+ !!(index(str, otmp->oclass))) {
+ if (otmp->otyp == CORPSE && mtmp->data->mlet != S_NYMPH &&
+ /* let a handful of corpse types thru to can_carry() */
+ !touch_petrifies(&mons[otmp->corpsenm]) &&
+ otmp->corpsenm != PM_LIZARD &&
+ !acidic(&mons[otmp->corpsenm])) continue;
+ if (!touch_artifact(otmp,mtmp)) continue;
+ if (!can_carry(mtmp,otmp)) continue;
+ if (is_pool(mtmp->mx,mtmp->my)) continue;
+ if (cansee(mtmp->mx,mtmp->my) && flags.verbose)
+ pline("%s picks up %s.", Monnam(mtmp),
+ (distu(mtmp->mx, mtmp->my) <= 5) ?
+ doname(otmp) : distant_name(otmp, doname));
+ obj_extract_self(otmp); /* remove from floor */
+ (void) mpickobj(mtmp, otmp); /* may merge and free otmp */
+ m_dowear(mtmp, FALSE);
+ newsym(mtmp->mx, mtmp->my);
+ return TRUE; /* pick only one object */
+ }
+ }
+ return FALSE;
}
int
curr_mon_load(mtmp)
register struct monst *mtmp;
{
- register int curload = 0;
- register struct obj *obj;
+ register int curload = 0;
+ register struct obj *obj;
- for(obj = mtmp->minvent; obj; obj = obj->nobj) {
- if(obj->otyp != BOULDER || !throws_rocks(mtmp->data))
- curload += obj->owt;
- }
+ for(obj = mtmp->minvent; obj; obj = obj->nobj) {
+ if(obj->otyp != BOULDER || !throws_rocks(mtmp->data))
+ curload += obj->owt;
+ }
- return curload;
+ return curload;
}
int
max_mon_load(mtmp)
register struct monst *mtmp;
{
- register long maxload;
- /* Base monster carrying capacity is equal to human maximum
- * carrying capacity, or half human maximum if not strong.
- * (for a polymorphed player, the value used would be the
- * non-polymorphed carrying capacity instead of max/half max).
- * This is then modified by the ratio between the monster weights
- * and human weights. Corpseless monsters are given a capacity
- * proportional to their size instead of weight.
- */
- if (!mtmp->data->cwt)
- maxload = (MAX_CARR_CAP * (long)mtmp->data->msize) / MZ_HUMAN;
- else if (!strongmonst(mtmp->data)
- || (strongmonst(mtmp->data) && (mtmp->data->cwt > WT_HUMAN)))
- maxload = (MAX_CARR_CAP * (long)mtmp->data->cwt) / WT_HUMAN;
- else maxload = MAX_CARR_CAP; /*strong monsters w/cwt <= WT_HUMAN*/
+ register long maxload;
+ /* Base monster carrying capacity is equal to human maximum
+ * carrying capacity, or half human maximum if not strong.
+ * (for a polymorphed player, the value used would be the
+ * non-polymorphed carrying capacity instead of max/half max).
+ * This is then modified by the ratio between the monster weights
+ * and human weights. Corpseless monsters are given a capacity
+ * proportional to their size instead of weight.
+ */
+ if (!mtmp->data->cwt)
+ maxload = (MAX_CARR_CAP * (long)mtmp->data->msize) / MZ_HUMAN;
+ else if (!strongmonst(mtmp->data)
+ || (strongmonst(mtmp->data) && (mtmp->data->cwt > WT_HUMAN)))
+ maxload = (MAX_CARR_CAP * (long)mtmp->data->cwt) / WT_HUMAN;
+ else maxload = MAX_CARR_CAP; /*strong monsters w/cwt <= WT_HUMAN*/
- if (!strongmonst(mtmp->data)) maxload /= 2;
+ if (!strongmonst(mtmp->data)) maxload /= 2;
- if (maxload < 1) maxload = 1;
+ if (maxload < 1) maxload = 1;
- return (int) maxload;
+ return (int) maxload;
}
/* for restricting monsters' object-pickup */
struct monst *mtmp;
struct obj *otmp;
{
- int otyp = otmp->otyp, newload = otmp->owt;
- struct permonst *mdat = mtmp->data;
-
- if (notake(mdat)) return FALSE; /* can't carry anything */
-
- if (otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]) &&
- !(mtmp->misc_worn_check & W_ARMG) && !resists_ston(mtmp))
- return FALSE;
- if (otyp == CORPSE && is_rider(&mons[otmp->corpsenm]))
- return FALSE;
- if (objects[otyp].oc_material == SILVER && mon_hates_silver(mtmp) &&
- (otyp != BELL_OF_OPENING || !is_covetous(mdat)))
- return FALSE;
-
- /* Steeds don't pick up stuff (to avoid shop abuse) */
- if (mtmp == u.usteed) return (FALSE);
- if (mtmp->isshk) return(TRUE); /* no limit */
- if (mtmp->mpeaceful && !mtmp->mtame) return(FALSE);
- /* otherwise players might find themselves obligated to violate
- * their alignment if the monster takes something they need
- */
+ int otyp = otmp->otyp, newload = otmp->owt;
+ struct permonst *mdat = mtmp->data;
+
+ if (notake(mdat)) return FALSE; /* can't carry anything */
+
+ if (otyp == CORPSE && touch_petrifies(&mons[otmp->corpsenm]) &&
+ !(mtmp->misc_worn_check & W_ARMG) && !resists_ston(mtmp))
+ return FALSE;
+ if (otyp == CORPSE && is_rider(&mons[otmp->corpsenm]))
+ return FALSE;
+ if (objects[otyp].oc_material == SILVER && mon_hates_silver(mtmp) &&
+ (otyp != BELL_OF_OPENING || !is_covetous(mdat)))
+ return FALSE;
+
+ /* Steeds don't pick up stuff (to avoid shop abuse) */
+ if (mtmp == u.usteed) return (FALSE);
+ if (mtmp->isshk) return(TRUE); /* no limit */
+ if (mtmp->mpeaceful && !mtmp->mtame) return(FALSE);
+ /* otherwise players might find themselves obligated to violate
+ * their alignment if the monster takes something they need
+ */
- /* special--boulder throwers carry unlimited amounts of boulders */
- if (throws_rocks(mdat) && otyp == BOULDER)
- return(TRUE);
+ /* special--boulder throwers carry unlimited amounts of boulders */
+ if (throws_rocks(mdat) && otyp == BOULDER)
+ return(TRUE);
- /* nymphs deal in stolen merchandise, but not boulders or statues */
- if (mdat->mlet == S_NYMPH)
- return (boolean)(otmp->oclass != ROCK_CLASS);
+ /* nymphs deal in stolen merchandise, but not boulders or statues */
+ if (mdat->mlet == S_NYMPH)
+ return (boolean)(otmp->oclass != ROCK_CLASS);
- if (curr_mon_load(mtmp) + newload > max_mon_load(mtmp)) return FALSE;
+ if (curr_mon_load(mtmp) + newload > max_mon_load(mtmp)) return FALSE;
- return(TRUE);
+ return(TRUE);
}
/* return number of acceptable neighbour positions */
int
mfndpos(mon, poss, info, flag)
- register struct monst *mon;
- coord *poss; /* coord poss[9] */
- long *info; /* long info[9] */
- long flag;
-{
- struct permonst *mdat = mon->data;
- register xchar x,y,nx,ny;
- register int cnt = 0;
- register uchar ntyp;
- uchar nowtyp;
- boolean wantpool,poolok,lavaok,nodiag;
- boolean rockok = FALSE, treeok = FALSE, thrudoor;
- int maxx, maxy;
-
- x = mon->mx;
- y = mon->my;
- nowtyp = levl[x][y].typ;
-
- nodiag = NODIAG(mdat - mons);
- wantpool = mdat->mlet == S_EEL;
- poolok = is_flyer(mdat) || is_clinger(mdat) ||
- (is_swimmer(mdat) && !wantpool);
- lavaok = is_flyer(mdat) || is_clinger(mdat) || likes_lava(mdat);
- thrudoor = ((flag & (ALLOW_WALL|BUSTDOOR)) != 0L);
- if (flag & ALLOW_DIG) {
- struct obj *mw_tmp;
-
- /* need to be specific about what can currently be dug */
- if (!needspick(mdat)) {
- rockok = treeok = TRUE;
- } else if ((mw_tmp = MON_WEP(mon)) && mw_tmp->cursed &&
- mon->weapon_check == NO_WEAPON_WANTED) {
- rockok = is_pick(mw_tmp);
- treeok = is_axe(mw_tmp);
- } else {
- rockok = (m_carrying(mon, PICK_AXE) ||
- (m_carrying(mon, DWARVISH_MATTOCK) &&
- !which_armor(mon, W_ARMS)));
- treeok = (m_carrying(mon, AXE) ||
- (m_carrying(mon, BATTLE_AXE) &&
- !which_armor(mon, W_ARMS)));
- }
- thrudoor |= rockok || treeok;
- }
+ register struct monst *mon;
+ coord *poss; /* coord poss[9] */
+ long *info; /* long info[9] */
+ long flag;
+{
+ struct permonst *mdat = mon->data;
+ register xchar x,y,nx,ny;
+ register int cnt = 0;
+ register uchar ntyp;
+ uchar nowtyp;
+ boolean wantpool,poolok,lavaok,nodiag;
+ boolean rockok = FALSE, treeok = FALSE, thrudoor;
+ int maxx, maxy;
+
+ x = mon->mx;
+ y = mon->my;
+ nowtyp = levl[x][y].typ;
+
+ nodiag = NODIAG(mdat - mons);
+ wantpool = mdat->mlet == S_EEL;
+ poolok = is_flyer(mdat) || is_clinger(mdat) ||
+ (is_swimmer(mdat) && !wantpool);
+ lavaok = is_flyer(mdat) || is_clinger(mdat) || likes_lava(mdat);
+ thrudoor = ((flag & (ALLOW_WALL|BUSTDOOR)) != 0L);
+ if (flag & ALLOW_DIG) {
+ struct obj *mw_tmp;
+
+ /* need to be specific about what can currently be dug */
+ if (!needspick(mdat)) {
+ rockok = treeok = TRUE;
+ } else if ((mw_tmp = MON_WEP(mon)) && mw_tmp->cursed &&
+ mon->weapon_check == NO_WEAPON_WANTED) {
+ rockok = is_pick(mw_tmp);
+ treeok = is_axe(mw_tmp);
+ } else {
+ rockok = (m_carrying(mon, PICK_AXE) ||
+ (m_carrying(mon, DWARVISH_MATTOCK) &&
+ !which_armor(mon, W_ARMS)));
+ treeok = (m_carrying(mon, AXE) ||
+ (m_carrying(mon, BATTLE_AXE) &&
+ !which_armor(mon, W_ARMS)));
+ }
+ thrudoor |= rockok || treeok;
+ }
nexttry: /* eels prefer the water, but if there is no water nearby,
- they will crawl over land */
- if(mon->mconf) {
- flag |= ALLOW_ALL;
- flag &= ~NOTONL;
- }
- if(!mon->mcansee)
- flag |= ALLOW_SSM;
- maxx = min(x+1,COLNO-1);
- maxy = min(y+1,ROWNO-1);
- for(nx = max(1,x-1); nx <= maxx; nx++)
- for(ny = max(0,y-1); ny <= maxy; ny++) {
- if(nx == x && ny == y) continue;
- if(IS_ROCK(ntyp = levl[nx][ny].typ) &&
- !((flag & ALLOW_WALL) && may_passwall(nx,ny)) &&
- !((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx,ny))) continue;
- /* KMH -- Added iron bars */
- if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue;
- if (IS_DOOR(ntyp) && !(amorphous(mdat) || can_fog(mon)) &&
- (((levl[nx][ny].doormask & D_CLOSED) &&
- !(flag & OPENDOOR)) ||
- ((levl[nx][ny].doormask & D_LOCKED) &&
- !(flag & UNLOCKDOOR))) &&
- !thrudoor) continue;
- /* first diagonal checks (tight squeezes handled below) */
- if (nx != x && ny != y && (nodiag ||
- (IS_DOOR(nowtyp) && (levl[x][y].doormask & ~D_BROKEN)) ||
- (IS_DOOR(ntyp) && (levl[nx][ny].doormask & ~D_BROKEN)) ||
- ((IS_DOOR(nowtyp) || IS_DOOR(ntyp)) && Is_rogue_level(&u.uz)) ||
- /* mustn't pass between adjacent long worm segments,
- but can attack that way */
- (m_at(x, ny) && m_at(nx, y) && worm_cross(x, y, nx, ny) &&
- !m_at(nx, ny) && (nx != u.ux || ny != u.uy))))
- continue;
- if((is_pool(nx,ny) == wantpool || poolok) &&
- (lavaok || !is_lava(nx,ny))) {
- int dispx, dispy;
- boolean monseeu = (mon->mcansee && (!Invis || perceives(mdat)));
- boolean checkobj = OBJ_AT(nx,ny);
-
- /* Displacement also displaces the Elbereth/scare monster,
- * as long as you are visible.
- */
- if(Displaced && monseeu && (mon->mux==nx) && (mon->muy==ny)) {
- dispx = u.ux;
- dispy = u.uy;
- } else {
- dispx = nx;
- dispy = ny;
- }
-
- info[cnt] = 0;
- if (onscary(dispx, dispy, mon)) {
- if(!(flag & ALLOW_SSM)) continue;
- info[cnt] |= ALLOW_SSM;
- }
- if((nx == u.ux && ny == u.uy) ||
- (nx == mon->mux && ny == mon->muy)) {
- if (nx == u.ux && ny == u.uy) {
- /* If it's right next to you, it found you,
- * displaced or no. We must set mux and muy
- * right now, so when we return we can tell
- * that the ALLOW_U means to attack _you_ and
- * not the image.
- */
- mon->mux = u.ux;
- mon->muy = u.uy;
- }
- if(!(flag & ALLOW_U)) continue;
- info[cnt] |= ALLOW_U;
- } else {
- if(MON_AT(nx, ny)) {
- struct monst *mtmp2 = m_at(nx, ny);
- long mmflag = flag | mm_aggression(mon, mtmp2);
-
- if (mmflag & ALLOW_M) {
- info[cnt] |= ALLOW_M;
- if (mtmp2->mtame) {
- if (!(mmflag & ALLOW_TM)) continue;
- info[cnt] |= ALLOW_TM;
- }
- } else {
- mmflag = flag | mm_displacement(mon, mtmp2);
- if (!(mmflag & ALLOW_MDISP)) continue;
- info[cnt] |= ALLOW_MDISP;
- }
- }
- /* Note: ALLOW_SANCT only prevents movement, not */
- /* attack, into a temple. */
- if(level.flags.has_temple &&
- *in_rooms(nx, ny, TEMPLE) &&
- !*in_rooms(x, y, TEMPLE) &&
- in_your_sanctuary((struct monst *)0, nx, ny)) {
- if(!(flag & ALLOW_SANCT)) continue;
- info[cnt] |= ALLOW_SANCT;
- }
- }
- if(checkobj && sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
- if(flag & NOGARLIC) continue;
- info[cnt] |= NOGARLIC;
- }
- if(checkobj && sobj_at(BOULDER, nx, ny)) {
- if(!(flag & ALLOW_ROCK)) continue;
- info[cnt] |= ALLOW_ROCK;
- }
- if (monseeu && onlineu(nx,ny)) {
- if(flag & NOTONL) continue;
- info[cnt] |= NOTONL;
- }
- /* check for diagonal tight squeeze */
- if (nx != x && ny != y && bad_rock(mdat, x, ny) &&
- bad_rock(mdat, nx, y) && cant_squeeze_thru(mon))
- continue;
- /* The monster avoids a particular type of trap if it's familiar
- * with the trap type. Pets get ALLOW_TRAPS and checking is
- * done in dogmove.c. In either case, "harmless" traps are
- * neither avoided nor marked in info[].
- */
- { register struct trap *ttmp = t_at(nx, ny);
- if(ttmp) {
- if(ttmp->ttyp >= TRAPNUM || ttmp->ttyp == 0) {
+ they will crawl over land */
+ if(mon->mconf) {
+ flag |= ALLOW_ALL;
+ flag &= ~NOTONL;
+ }
+ if(!mon->mcansee)
+ flag |= ALLOW_SSM;
+ maxx = min(x+1,COLNO-1);
+ maxy = min(y+1,ROWNO-1);
+ for(nx = max(1,x-1); nx <= maxx; nx++)
+ for(ny = max(0,y-1); ny <= maxy; ny++) {
+ if(nx == x && ny == y) continue;
+ if(IS_ROCK(ntyp = levl[nx][ny].typ) &&
+ !((flag & ALLOW_WALL) && may_passwall(nx,ny)) &&
+ !((IS_TREE(ntyp) ? treeok : rockok) && may_dig(nx,ny))) continue;
+ /* KMH -- Added iron bars */
+ if (ntyp == IRONBARS && !(flag & ALLOW_BARS)) continue;
+ if (IS_DOOR(ntyp) && !(amorphous(mdat) || can_fog(mon)) &&
+ (((levl[nx][ny].doormask & D_CLOSED) &&
+ !(flag & OPENDOOR)) ||
+ ((levl[nx][ny].doormask & D_LOCKED) &&
+ !(flag & UNLOCKDOOR))) &&
+ !thrudoor) continue;
+ /* first diagonal checks (tight squeezes handled below) */
+ if (nx != x && ny != y && (nodiag ||
+ (IS_DOOR(nowtyp) && (levl[x][y].doormask & ~D_BROKEN)) ||
+ (IS_DOOR(ntyp) && (levl[nx][ny].doormask & ~D_BROKEN)) ||
+ ((IS_DOOR(nowtyp) || IS_DOOR(ntyp)) && Is_rogue_level(&u.uz)) ||
+ /* mustn't pass between adjacent long worm segments,
+ but can attack that way */
+ (m_at(x, ny) && m_at(nx, y) && worm_cross(x, y, nx, ny) &&
+ !m_at(nx, ny) && (nx != u.ux || ny != u.uy))))
+ continue;
+ if((is_pool(nx,ny) == wantpool || poolok) &&
+ (lavaok || !is_lava(nx,ny))) {
+ int dispx, dispy;
+ boolean monseeu = (mon->mcansee && (!Invis || perceives(mdat)));
+ boolean checkobj = OBJ_AT(nx,ny);
+
+ /* Displacement also displaces the Elbereth/scare monster,
+ * as long as you are visible.
+ */
+ if(Displaced && monseeu && (mon->mux==nx) && (mon->muy==ny)) {
+ dispx = u.ux;
+ dispy = u.uy;
+ } else {
+ dispx = nx;
+ dispy = ny;
+ }
+
+ info[cnt] = 0;
+ if (onscary(dispx, dispy, mon)) {
+ if(!(flag & ALLOW_SSM)) continue;
+ info[cnt] |= ALLOW_SSM;
+ }
+ if((nx == u.ux && ny == u.uy) ||
+ (nx == mon->mux && ny == mon->muy)) {
+ if (nx == u.ux && ny == u.uy) {
+ /* If it's right next to you, it found you,
+ * displaced or no. We must set mux and muy
+ * right now, so when we return we can tell
+ * that the ALLOW_U means to attack _you_ and
+ * not the image.
+ */
+ mon->mux = u.ux;
+ mon->muy = u.uy;
+ }
+ if(!(flag & ALLOW_U)) continue;
+ info[cnt] |= ALLOW_U;
+ } else {
+ if(MON_AT(nx, ny)) {
+ struct monst *mtmp2 = m_at(nx, ny);
+ long mmflag = flag | mm_aggression(mon, mtmp2);
+
+ if (mmflag & ALLOW_M) {
+ info[cnt] |= ALLOW_M;
+ if (mtmp2->mtame) {
+ if (!(mmflag & ALLOW_TM)) continue;
+ info[cnt] |= ALLOW_TM;
+ }
+ } else {
+ mmflag = flag | mm_displacement(mon, mtmp2);
+ if (!(mmflag & ALLOW_MDISP)) continue;
+ info[cnt] |= ALLOW_MDISP;
+ }
+ }
+ /* Note: ALLOW_SANCT only prevents movement, not */
+ /* attack, into a temple. */
+ if(level.flags.has_temple &&
+ *in_rooms(nx, ny, TEMPLE) &&
+ !*in_rooms(x, y, TEMPLE) &&
+ in_your_sanctuary((struct monst *)0, nx, ny)) {
+ if(!(flag & ALLOW_SANCT)) continue;
+ info[cnt] |= ALLOW_SANCT;
+ }
+ }
+ if(checkobj && sobj_at(CLOVE_OF_GARLIC, nx, ny)) {
+ if(flag & NOGARLIC) continue;
+ info[cnt] |= NOGARLIC;
+ }
+ if(checkobj && sobj_at(BOULDER, nx, ny)) {
+ if(!(flag & ALLOW_ROCK)) continue;
+ info[cnt] |= ALLOW_ROCK;
+ }
+ if (monseeu && onlineu(nx,ny)) {
+ if(flag & NOTONL) continue;
+ info[cnt] |= NOTONL;
+ }
+ /* check for diagonal tight squeeze */
+ if (nx != x && ny != y && bad_rock(mdat, x, ny) &&
+ bad_rock(mdat, nx, y) && cant_squeeze_thru(mon))
+ continue;
+ /* The monster avoids a particular type of trap if it's familiar
+ * with the trap type. Pets get ALLOW_TRAPS and checking is
+ * done in dogmove.c. In either case, "harmless" traps are
+ * neither avoided nor marked in info[].
+ */
+ { register struct trap *ttmp = t_at(nx, ny);
+ if(ttmp) {
+ if(ttmp->ttyp >= TRAPNUM || ttmp->ttyp == 0) {
impossible("A monster looked at a very strange trap of type %d.", ttmp->ttyp);
- continue;
- }
- if ((ttmp->ttyp != RUST_TRAP
- || mdat == &mons[PM_IRON_GOLEM])
- && ttmp->ttyp != STATUE_TRAP
- && ((ttmp->ttyp != PIT
- && ttmp->ttyp != SPIKED_PIT
- && ttmp->ttyp != TRAPDOOR
- && ttmp->ttyp != HOLE)
- || (!is_flyer(mdat)
- && !is_floater(mdat)
- && !is_clinger(mdat))
- || Sokoban)
- && (ttmp->ttyp != SLP_GAS_TRAP ||
- !resists_sleep(mon))
- && (ttmp->ttyp != BEAR_TRAP ||
- (mdat->msize > MZ_SMALL &&
- !amorphous(mdat) && !is_flyer(mdat) &&
- !is_whirly(mdat) && !unsolid(mdat)))
- && (ttmp->ttyp != FIRE_TRAP ||
- !resists_fire(mon))
- && (ttmp->ttyp != SQKY_BOARD || !is_flyer(mdat))
- && (ttmp->ttyp != WEB || (!amorphous(mdat) &&
- !webmaker(mdat)))
- && (ttmp->ttyp != ANTI_MAGIC ||
- !resists_magm(mon))
- ) {
- if (!(flag & ALLOW_TRAPS)) {
- if (mon->mtrapseen & (1L << (ttmp->ttyp - 1)))
- continue;
- }
- info[cnt] |= ALLOW_TRAPS;
- }
- }
- }
- poss[cnt].x = nx;
- poss[cnt].y = ny;
- cnt++;
- }
- }
- if(!cnt && wantpool && !is_pool(x,y)) {
- wantpool = FALSE;
- goto nexttry;
- }
- return(cnt);
+ continue;
+ }
+ if ((ttmp->ttyp != RUST_TRAP
+ || mdat == &mons[PM_IRON_GOLEM])
+ && ttmp->ttyp != STATUE_TRAP
+ && ((ttmp->ttyp != PIT
+ && ttmp->ttyp != SPIKED_PIT
+ && ttmp->ttyp != TRAPDOOR
+ && ttmp->ttyp != HOLE)
+ || (!is_flyer(mdat)
+ && !is_floater(mdat)
+ && !is_clinger(mdat))
+ || Sokoban)
+ && (ttmp->ttyp != SLP_GAS_TRAP ||
+ !resists_sleep(mon))
+ && (ttmp->ttyp != BEAR_TRAP ||
+ (mdat->msize > MZ_SMALL &&
+ !amorphous(mdat) && !is_flyer(mdat) &&
+ !is_whirly(mdat) && !unsolid(mdat)))
+ && (ttmp->ttyp != FIRE_TRAP ||
+ !resists_fire(mon))
+ && (ttmp->ttyp != SQKY_BOARD || !is_flyer(mdat))
+ && (ttmp->ttyp != WEB || (!amorphous(mdat) &&
+ !webmaker(mdat)))
+ && (ttmp->ttyp != ANTI_MAGIC ||
+ !resists_magm(mon))
+ ) {
+ if (!(flag & ALLOW_TRAPS)) {
+ if (mon->mtrapseen & (1L << (ttmp->ttyp - 1)))
+ continue;
+ }
+ info[cnt] |= ALLOW_TRAPS;
+ }
+ }
+ }
+ poss[cnt].x = nx;
+ poss[cnt].y = ny;
+ cnt++;
+ }
+ }
+ if(!cnt && wantpool && !is_pool(x,y)) {
+ wantpool = FALSE;
+ goto nexttry;
+ }
+ return(cnt);
}
/* Monster against monster special attacks; for the specified monster
STATIC_OVL long
mm_aggression(magr, mdef)
struct monst *magr, /* monster that is currently deciding where to move */
- *mdef; /* another monster which is next to it */
+ *mdef; /* another monster which is next to it */
{
- /* supposedly purple worms are attracted to shrieking because they
- like to eat shriekers, so attack the latter when feasible */
- if (magr->data == &mons[PM_PURPLE_WORM] &&
- mdef->data == &mons[PM_SHRIEKER])
- return ALLOW_M|ALLOW_TM;
- /* Various other combinations such as dog vs cat, cat vs rat, and
- elf vs orc have been suggested. For the time being we don't
- support those. */
- return 0L;
+ /* supposedly purple worms are attracted to shrieking because they
+ like to eat shriekers, so attack the latter when feasible */
+ if (magr->data == &mons[PM_PURPLE_WORM] &&
+ mdef->data == &mons[PM_SHRIEKER])
+ return ALLOW_M|ALLOW_TM;
+ /* Various other combinations such as dog vs cat, cat vs rat, and
+ elf vs orc have been suggested. For the time being we don't
+ support those. */
+ return 0L;
}
/* Monster displacing another monster out of the way */
STATIC_OVL long
mm_displacement(magr, mdef)
struct monst *magr, /* monster that is currently deciding where to move */
- *mdef; /* another monster which is next to it */
-{
- struct permonst *pa = magr->data,
- *pd = mdef->data;
-
- /* if attacker can't barge through, there's nothing to do;
- or if defender can barge through too, don't let attacker
- do so, otherwise they might just end up swapping places
- again when defender gets its chance to move */
- if ((pa->mflags3 & M3_DISPLACES) != 0 &&
- (pd->mflags3 & M3_DISPLACES) == 0 &&
- /* no displacing grid bugs diagonally */
- !(magr->mx != mdef->mx && magr->my != mdef->my &&
- NODIAG(monsndx(pd))) &&
- /* no displacing trapped monsters or multi-location longworms */
- !mdef->mtrapped && (!mdef->wormno || !count_wsegs(mdef)) &&
- /* riders can move anything; others, same size or smaller only */
- (is_rider(pa) || pa->msize >= pd->msize))
- return ALLOW_MDISP;
- return 0L;
+ *mdef; /* another monster which is next to it */
+{
+ struct permonst *pa = magr->data,
+ *pd = mdef->data;
+
+ /* if attacker can't barge through, there's nothing to do;
+ or if defender can barge through too, don't let attacker
+ do so, otherwise they might just end up swapping places
+ again when defender gets its chance to move */
+ if ((pa->mflags3 & M3_DISPLACES) != 0 &&
+ (pd->mflags3 & M3_DISPLACES) == 0 &&
+ /* no displacing grid bugs diagonally */
+ !(magr->mx != mdef->mx && magr->my != mdef->my &&
+ NODIAG(monsndx(pd))) &&
+ /* no displacing trapped monsters or multi-location longworms */
+ !mdef->mtrapped && (!mdef->wormno || !count_wsegs(mdef)) &&
+ /* riders can move anything; others, same size or smaller only */
+ (is_rider(pa) || pa->msize >= pd->msize))
+ return ALLOW_MDISP;
+ return 0L;
}
boolean
register int x,y;
/* Is the square close enough for the monster to move or attack into? */
{
- register int distance = dist2(mon->mx, mon->my, x, y);
+ register int distance = dist2(mon->mx, mon->my, x, y);
- if (distance == 2 && NODIAG(mon->data - mons)) return 0;
- return((boolean)(distance < 3));
+ if (distance == 2 && NODIAG(mon->data - mons)) return 0;
+ return((boolean)(distance < 3));
}
/* really free dead monsters */
int count = 0;
for (mtmp = &fmon; *mtmp;) {
- freetmp = *mtmp;
- if (freetmp->mhp <= 0 && !freetmp->isgd) {
- *mtmp = freetmp->nmon;
- dealloc_monst(freetmp);
- count++;
- } else
- mtmp = &(freetmp->nmon);
+ freetmp = *mtmp;
+ if (freetmp->mhp <= 0 && !freetmp->isgd) {
+ *mtmp = freetmp->nmon;
+ dealloc_monst(freetmp);
+ count++;
+ } else
+ mtmp = &(freetmp->nmon);
}
if (count != iflags.purge_monsters)
- impossible("dmonsfree: %d removed doesn't match %d pending",
- count, iflags.purge_monsters);
+ impossible("dmonsfree: %d removed doesn't match %d pending",
+ count, iflags.purge_monsters);
iflags.purge_monsters = 0;
}
/* transfer the monster's inventory */
for (otmp = mtmp2->minvent; otmp; otmp = otmp->nobj) {
- if (otmp->where != OBJ_MINVENT || otmp->ocarry != mtmp)
- debugpline("replmon: minvent inconsistency");
- otmp->ocarry = mtmp2;
+ if (otmp->where != OBJ_MINVENT || otmp->ocarry != mtmp)
+ debugpline("replmon: minvent inconsistency");
+ otmp->ocarry = mtmp2;
}
mtmp->minvent = 0;
if (mtmp != u.usteed) /* don't place steed onto the map */
place_monster(mtmp2, mtmp2->mx, mtmp2->my);
if (mtmp2->wormno) /* update level.monsters[wseg->wx][wseg->wy] */
- place_wsegs(mtmp2); /* locations to mtmp2 not mtmp. */
+ place_wsegs(mtmp2); /* locations to mtmp2 not mtmp. */
if (emits_light(mtmp2->data)) {
- /* since this is so rare, we don't have any `mon_move_light_source' */
- new_light_source(mtmp2->mx, mtmp2->my,
- emits_light(mtmp2->data),
- LS_MONSTER, monst_to_any(mtmp2));
- /* here we rely on the fact that `mtmp' hasn't actually been deleted */
- del_light_source(LS_MONSTER, monst_to_any(mtmp));
+ /* since this is so rare, we don't have any `mon_move_light_source' */
+ new_light_source(mtmp2->mx, mtmp2->my,
+ emits_light(mtmp2->data),
+ LS_MONSTER, monst_to_any(mtmp2));
+ /* here we rely on the fact that `mtmp' hasn't actually been deleted */
+ del_light_source(LS_MONSTER, monst_to_any(mtmp));
}
mtmp2->nmon = fmon;
fmon = mtmp2;
register struct monst *mon;
struct monst **monst_list; /* &migrating_mons or &mydogs or null */
{
- register struct monst *mtmp;
- boolean unhide = (monst_list != 0);
- int mx = mon->mx, my = mon->my;
-
- if (!fmon) panic("relmon: no fmon available.");
-
- if (unhide) {
- /* can't remain hidden across level changes (exception: wizard
- clone can continue imitating some other monster form); also,
- might be imitating a boulder so need line-of-sight unblocking */
- mon->mundetected = 0;
- if (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER)
- seemimic(mon);
- }
+ register struct monst *mtmp;
+ boolean unhide = (monst_list != 0);
+ int mx = mon->mx, my = mon->my;
+
+ if (!fmon) panic("relmon: no fmon available.");
+
+ if (unhide) {
+ /* can't remain hidden across level changes (exception: wizard
+ clone can continue imitating some other monster form); also,
+ might be imitating a boulder so need line-of-sight unblocking */
+ mon->mundetected = 0;
+ if (mon->m_ap_type && mon->m_ap_type != M_AP_MONSTER)
+ seemimic(mon);
+ }
- remove_monster(mx, my);
+ remove_monster(mx, my);
- if (mon == fmon) {
- fmon = fmon->nmon;
- } else {
- for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
- if (mtmp->nmon == mon) break;
+ if (mon == fmon) {
+ fmon = fmon->nmon;
+ } else {
+ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon)
+ if (mtmp->nmon == mon) break;
- if (mtmp) mtmp->nmon = mon->nmon;
- else panic("relmon: mon not in list.");
- }
+ if (mtmp) mtmp->nmon = mon->nmon;
+ else panic("relmon: mon not in list.");
+ }
- if (unhide) {
- newsym(mx, my);
- /* insert into mydogs or migrating_mons */
- mon->nmon = *monst_list;
- *monst_list = mon;
- } else {
- /* orphan has no next monster */
- mon->nmon = 0;
- }
+ if (unhide) {
+ newsym(mx, my);
+ /* insert into mydogs or migrating_mons */
+ mon->nmon = *monst_list;
+ *monst_list = mon;
+ } else {
+ /* orphan has no next monster */
+ mon->nmon = 0;
+ }
}
void
copy_mextra(mtmp2, mtmp1)
struct monst *mtmp2, *mtmp1;
{
- if(!mtmp2 || !mtmp1 || !mtmp1->mextra) return;
-
- if (!mtmp2->mextra) mtmp2->mextra = newmextra();
- if (MNAME(mtmp1)) {
- new_mname(mtmp2, (int)strlen(MNAME(mtmp1)) + 1);
- Strcpy(MNAME(mtmp2), MNAME(mtmp1));
- }
- if (EGD(mtmp1)) {
- if (!EGD(mtmp2)) newegd(mtmp2);
- (void)memcpy((genericptr_t)EGD(mtmp2),
- (genericptr_t)EGD(mtmp1),
- sizeof(struct egd));
- }
- if (EPRI(mtmp1)) {
- if (!EPRI(mtmp2)) newepri(mtmp2);
- (void)memcpy((genericptr_t)EPRI(mtmp2),
- (genericptr_t)EPRI(mtmp1),
- sizeof(struct epri));
- }
- if (ESHK(mtmp1)) {
- if (!ESHK(mtmp2)) neweshk(mtmp2);
- (void)memcpy((genericptr_t)ESHK(mtmp2),
- (genericptr_t)ESHK(mtmp1),
- sizeof(struct eshk));
- }
- if (EMIN(mtmp1)) {
- if (!EMIN(mtmp2)) newemin(mtmp2);
- (void)memcpy((genericptr_t)EMIN(mtmp2),
- (genericptr_t)EMIN(mtmp1),
- sizeof(struct emin));
- }
- if (EDOG(mtmp1)) {
- if (!EDOG(mtmp2)) newedog(mtmp2);
- (void)memcpy((genericptr_t)EDOG(mtmp2),
- (genericptr_t)EDOG(mtmp1),
- sizeof(struct edog));
- }
- if (has_mcorpsenm(mtmp1)) MCORPSENM(mtmp2) = MCORPSENM(mtmp1);
+ if(!mtmp2 || !mtmp1 || !mtmp1->mextra) return;
+
+ if (!mtmp2->mextra) mtmp2->mextra = newmextra();
+ if (MNAME(mtmp1)) {
+ new_mname(mtmp2, (int)strlen(MNAME(mtmp1)) + 1);
+ Strcpy(MNAME(mtmp2), MNAME(mtmp1));
+ }
+ if (EGD(mtmp1)) {
+ if (!EGD(mtmp2)) newegd(mtmp2);
+ (void)memcpy((genericptr_t)EGD(mtmp2),
+ (genericptr_t)EGD(mtmp1),
+ sizeof(struct egd));
+ }
+ if (EPRI(mtmp1)) {
+ if (!EPRI(mtmp2)) newepri(mtmp2);
+ (void)memcpy((genericptr_t)EPRI(mtmp2),
+ (genericptr_t)EPRI(mtmp1),
+ sizeof(struct epri));
+ }
+ if (ESHK(mtmp1)) {
+ if (!ESHK(mtmp2)) neweshk(mtmp2);
+ (void)memcpy((genericptr_t)ESHK(mtmp2),
+ (genericptr_t)ESHK(mtmp1),
+ sizeof(struct eshk));
+ }
+ if (EMIN(mtmp1)) {
+ if (!EMIN(mtmp2)) newemin(mtmp2);
+ (void)memcpy((genericptr_t)EMIN(mtmp2),
+ (genericptr_t)EMIN(mtmp1),
+ sizeof(struct emin));
+ }
+ if (EDOG(mtmp1)) {
+ if (!EDOG(mtmp2)) newedog(mtmp2);
+ (void)memcpy((genericptr_t)EDOG(mtmp2),
+ (genericptr_t)EDOG(mtmp1),
+ sizeof(struct edog));
+ }
+ if (has_mcorpsenm(mtmp1)) MCORPSENM(mtmp2) = MCORPSENM(mtmp1);
}
STATIC_OVL void
dealloc_mextra(x)
struct mextra *x;
{
- if (x) {
- if (x->mname) free((genericptr_t)x->mname);
- if (x->egd) free((genericptr_t)x->egd);
- if (x->epri) free((genericptr_t)x->epri);
- if (x->eshk) free((genericptr_t)x->eshk);
- if (x->emin) free((genericptr_t)x->emin);
- if (x->edog) free((genericptr_t)x->edog);
- /* [no action needed for x->mcorpsenm] */
- free((genericptr_t)x);
- }
+ if (x) {
+ if (x->mname) free((genericptr_t)x->mname);
+ if (x->egd) free((genericptr_t)x->egd);
+ if (x->epri) free((genericptr_t)x->epri);
+ if (x->eshk) free((genericptr_t)x->eshk);
+ if (x->emin) free((genericptr_t)x->emin);
+ if (x->edog) free((genericptr_t)x->edog);
+ /* [no action needed for x->mcorpsenm] */
+ free((genericptr_t)x);
+ }
}
void
dealloc_monst(mon)
struct monst *mon;
{
- if (mon->mextra) dealloc_mextra(mon->mextra);
- free((genericptr_t)mon);
+ if (mon->mextra) dealloc_mextra(mon->mextra);
+ free((genericptr_t)mon);
}
/* remove effects of mtmp from other data structures */
struct monst *mtmp;
struct permonst *mptr; /* reflects mtmp->data _prior_ to mtmp's death */
{
- if (mtmp->mleashed) m_unleash(mtmp, FALSE);
- /* to prevent an infinite relobj-flooreffects-hmon-killed loop */
- mtmp->mtrapped = 0;
- mtmp->mhp = 0; /* simplify some tests: force mhp to 0 */
- relobj(mtmp, 0, FALSE);
- remove_monster(mtmp->mx, mtmp->my);
- if (emits_light(mptr))
- del_light_source(LS_MONSTER, monst_to_any(mtmp));
- newsym(mtmp->mx,mtmp->my);
- unstuck(mtmp);
- fill_pit(mtmp->mx, mtmp->my);
+ if (mtmp->mleashed) m_unleash(mtmp, FALSE);
+ /* to prevent an infinite relobj-flooreffects-hmon-killed loop */
+ mtmp->mtrapped = 0;
+ mtmp->mhp = 0; /* simplify some tests: force mhp to 0 */
+ relobj(mtmp, 0, FALSE);
+ remove_monster(mtmp->mx, mtmp->my);
+ if (emits_light(mptr))
+ del_light_source(LS_MONSTER, monst_to_any(mtmp));
+ newsym(mtmp->mx,mtmp->my);
+ unstuck(mtmp);
+ fill_pit(mtmp->mx, mtmp->my);
- if(mtmp->isshk) shkgone(mtmp);
- if(mtmp->wormno) wormgone(mtmp);
- iflags.purge_monsters++;
+ if(mtmp->isshk) shkgone(mtmp);
+ if(mtmp->wormno) wormgone(mtmp);
+ iflags.purge_monsters++;
}
/* find the worn amulet of life saving which will save a monster */
mlifesaver(mon)
struct monst *mon;
{
- if (!nonliving(mon->data) || is_vampshifter(mon)) {
- struct obj *otmp = which_armor(mon, W_AMUL);
+ if (!nonliving(mon->data) || is_vampshifter(mon)) {
+ struct obj *otmp = which_armor(mon, W_AMUL);
- if (otmp && otmp->otyp == AMULET_OF_LIFE_SAVING)
- return otmp;
- }
- return (struct obj *)0;
+ if (otmp && otmp->otyp == AMULET_OF_LIFE_SAVING)
+ return otmp;
+ }
+ return (struct obj *)0;
}
STATIC_OVL void
lifesaved_monster(mtmp)
struct monst *mtmp;
{
- boolean surviver;
- struct obj *lifesave = mlifesaver(mtmp);
-
- if (lifesave) {
- /* not canseemon; amulets are on the head, so you don't want
- * to show this for a long worm with only a tail visible.
- * Nor do you check invisibility, because glowing and
- * disintegrating amulets are always visible. */
- if (cansee(mtmp->mx, mtmp->my)) {
- pline("But wait...");
- pline("%s medallion begins to glow!",
- s_suffix(Monnam(mtmp)));
- makeknown(AMULET_OF_LIFE_SAVING);
- /* amulet is visible, but monster might not be */
- if (canseemon(mtmp)) {
- if (attacktype(mtmp->data, AT_EXPL)
- || attacktype(mtmp->data, AT_BOOM))
- pline("%s reconstitutes!", Monnam(mtmp));
- else
- pline("%s looks much better!", Monnam(mtmp));
- }
- pline_The("medallion crumbles to dust!");
- }
- m_useup(mtmp, lifesave);
-
- surviver = !(mvitals[monsndx(mtmp->data)].mvflags & G_GENOD);
- mtmp->mcanmove = 1;
- mtmp->mfrozen = 0;
- if (mtmp->mtame && !mtmp->isminion) {
- wary_dog(mtmp, !surviver);
- }
- if (mtmp->mhpmax <= 0) mtmp->mhpmax = 10;
- mtmp->mhp = mtmp->mhpmax;
- if (surviver) return;
-
- /* genocided monster can't be life-saved */
- if (cansee(mtmp->mx, mtmp->my))
- pline("Unfortunately, %s is still genocided...",
- mon_nam(mtmp));
- }
- mtmp->mhp = 0;
+ boolean surviver;
+ struct obj *lifesave = mlifesaver(mtmp);
+
+ if (lifesave) {
+ /* not canseemon; amulets are on the head, so you don't want
+ * to show this for a long worm with only a tail visible.
+ * Nor do you check invisibility, because glowing and
+ * disintegrating amulets are always visible. */
+ if (cansee(mtmp->mx, mtmp->my)) {
+ pline("But wait...");
+ pline("%s medallion begins to glow!",
+ s_suffix(Monnam(mtmp)));
+ makeknown(AMULET_OF_LIFE_SAVING);
+ /* amulet is visible, but monster might not be */
+ if (canseemon(mtmp)) {
+ if (attacktype(mtmp->data, AT_EXPL)
+ || attacktype(mtmp->data, AT_BOOM))
+ pline("%s reconstitutes!", Monnam(mtmp));
+ else
+ pline("%s looks much better!", Monnam(mtmp));
+ }
+ pline_The("medallion crumbles to dust!");
+ }
+ m_useup(mtmp, lifesave);
+
+ surviver = !(mvitals[monsndx(mtmp->data)].mvflags & G_GENOD);
+ mtmp->mcanmove = 1;
+ mtmp->mfrozen = 0;
+ if (mtmp->mtame && !mtmp->isminion) {
+ wary_dog(mtmp, !surviver);
+ }
+ if (mtmp->mhpmax <= 0) mtmp->mhpmax = 10;
+ mtmp->mhp = mtmp->mhpmax;
+ if (surviver) return;
+
+ /* genocided monster can't be life-saved */
+ if (cansee(mtmp->mx, mtmp->my))
+ pline("Unfortunately, %s is still genocided...",
+ mon_nam(mtmp));
+ }
+ mtmp->mhp = 0;
}
void
mondead(mtmp)
register struct monst *mtmp;
{
- struct permonst *mptr;
- int tmp;
-
- lifesaved_monster(mtmp);
- if (mtmp->mhp > 0) return;
-
- if (is_vampshifter(mtmp)) {
- int mndx = mtmp->cham;
- int x = mtmp->mx, y = mtmp->my;
- /* this only happens if shapeshifted */
- if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)) {
- char buf[BUFSZ];
- boolean in_door = amorphous(mtmp->data) &&
- closed_door(mtmp->mx,mtmp->my);
- Sprintf(buf,
- "The %s%s suddenly %s and rises as %%s!",
- (nonliving(mtmp->data) ||
- noncorporeal(mtmp->data) ||
- amorphous(mtmp->data)) ? "" : "seemingly dead ",
- x_monnam(mtmp, ARTICLE_NONE, (char *)0,
- SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION |
- SUPPRESS_INVISIBLE | SUPPRESS_IT, FALSE),
- (nonliving(mtmp->data) ||
- noncorporeal(mtmp->data) ||
- amorphous(mtmp->data)) ?
- "reconstitutes" : "transforms");
- mtmp->mcanmove = 1;
- mtmp->mfrozen = 0;
- if (mtmp->mhpmax <= 0) mtmp->mhpmax = 10;
- mtmp->mhp = mtmp->mhpmax;
- /* this can happen if previously a fog cloud */
- if (u.uswallow && (mtmp == u.ustuck))
- expels(mtmp, mtmp->data, FALSE);
- if (in_door) {
- coord new_xy;
- if (enexto(&new_xy,
- mtmp->mx, mtmp->my, &mons[mndx])) {
- rloc_to(mtmp, new_xy.x, new_xy.y);
- }
- }
- newcham(mtmp, &mons[mndx], FALSE, FALSE);
- if (mtmp->data == &mons[mndx])
- mtmp->cham = NON_PM;
- else
- mtmp->cham = mndx;
- if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
- pline(buf, a_monnam(mtmp));
- newsym(x,y);
- return;
- }
- }
-
- /* dead vault guard is actually kept at coordinate <0,0> until
- his temporary corridor to/from the vault has been removed;
- need to do this after life-saving and before m_detach() */
- if (mtmp->isgd && !grddead(mtmp)) return;
-
- /* Player is thrown from his steed when it dies */
- if (mtmp == u.usteed)
- dismount_steed(DISMOUNT_GENERIC);
-
- mptr = mtmp->data; /* save this for m_detach() */
- /* restore chameleon, lycanthropes to true form at death */
- if (mtmp->cham >= LOW_PM) {
- set_mon_data(mtmp, &mons[mtmp->cham], -1);
- mtmp->cham = NON_PM;
- }
- else if (mtmp->data == &mons[PM_WEREJACKAL])
- set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
- else if (mtmp->data == &mons[PM_WEREWOLF])
- set_mon_data(mtmp, &mons[PM_HUMAN_WEREWOLF], -1);
- else if (mtmp->data == &mons[PM_WERERAT])
- set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT], -1);
-
- /* if MAXMONNO monsters of a given type have died, and it
- * can be done, extinguish that monster.
- *
- * mvitals[].died does double duty as total number of dead monsters
- * and as experience factor for the player killing more monsters.
- * this means that a dragon dying by other means reduces the
- * experience the player gets for killing a dragon directly; this
- * is probably not too bad, since the player likely finagled the
- * first dead dragon via ring of conflict or pets, and extinguishing
- * based on only player kills probably opens more avenues of abuse
- * for rings of conflict and such.
- */
- tmp = monsndx(mtmp->data);
- if (mvitals[tmp].died < 255) mvitals[tmp].died++;
-
- /* if it's a (possibly polymorphed) quest leader, mark him as dead */
- if (mtmp->m_id == quest_status.leader_m_id)
- quest_status.leader_is_dead = TRUE;
+ struct permonst *mptr;
+ int tmp;
+
+ lifesaved_monster(mtmp);
+ if (mtmp->mhp > 0) return;
+
+ if (is_vampshifter(mtmp)) {
+ int mndx = mtmp->cham;
+ int x = mtmp->mx, y = mtmp->my;
+ /* this only happens if shapeshifted */
+ if (mndx >= LOW_PM && mndx != monsndx(mtmp->data)) {
+ char buf[BUFSZ];
+ boolean in_door = amorphous(mtmp->data) &&
+ closed_door(mtmp->mx,mtmp->my);
+ Sprintf(buf,
+ "The %s%s suddenly %s and rises as %%s!",
+ (nonliving(mtmp->data) ||
+ noncorporeal(mtmp->data) ||
+ amorphous(mtmp->data)) ? "" : "seemingly dead ",
+ x_monnam(mtmp, ARTICLE_NONE, (char *)0,
+ SUPPRESS_SADDLE | SUPPRESS_HALLUCINATION |
+ SUPPRESS_INVISIBLE | SUPPRESS_IT, FALSE),
+ (nonliving(mtmp->data) ||
+ noncorporeal(mtmp->data) ||
+ amorphous(mtmp->data)) ?
+ "reconstitutes" : "transforms");
+ mtmp->mcanmove = 1;
+ mtmp->mfrozen = 0;
+ if (mtmp->mhpmax <= 0) mtmp->mhpmax = 10;
+ mtmp->mhp = mtmp->mhpmax;
+ /* this can happen if previously a fog cloud */
+ if (u.uswallow && (mtmp == u.ustuck))
+ expels(mtmp, mtmp->data, FALSE);
+ if (in_door) {
+ coord new_xy;
+ if (enexto(&new_xy,
+ mtmp->mx, mtmp->my, &mons[mndx])) {
+ rloc_to(mtmp, new_xy.x, new_xy.y);
+ }
+ }
+ newcham(mtmp, &mons[mndx], FALSE, FALSE);
+ if (mtmp->data == &mons[mndx])
+ mtmp->cham = NON_PM;
+ else
+ mtmp->cham = mndx;
+ if ((!Blind && canseemon(mtmp)) || sensemon(mtmp))
+ pline(buf, a_monnam(mtmp));
+ newsym(x,y);
+ return;
+ }
+ }
+
+ /* dead vault guard is actually kept at coordinate <0,0> until
+ his temporary corridor to/from the vault has been removed;
+ need to do this after life-saving and before m_detach() */
+ if (mtmp->isgd && !grddead(mtmp)) return;
+
+ /* Player is thrown from his steed when it dies */
+ if (mtmp == u.usteed)
+ dismount_steed(DISMOUNT_GENERIC);
+
+ mptr = mtmp->data; /* save this for m_detach() */
+ /* restore chameleon, lycanthropes to true form at death */
+ if (mtmp->cham >= LOW_PM) {
+ set_mon_data(mtmp, &mons[mtmp->cham], -1);
+ mtmp->cham = NON_PM;
+ }
+ else if (mtmp->data == &mons[PM_WEREJACKAL])
+ set_mon_data(mtmp, &mons[PM_HUMAN_WEREJACKAL], -1);
+ else if (mtmp->data == &mons[PM_WEREWOLF])
+ set_mon_data(mtmp, &mons[PM_HUMAN_WEREWOLF], -1);
+ else if (mtmp->data == &mons[PM_WERERAT])
+ set_mon_data(mtmp, &mons[PM_HUMAN_WERERAT], -1);
+
+ /* if MAXMONNO monsters of a given type have died, and it
+ * can be done, extinguish that monster.
+ *
+ * mvitals[].died does double duty as total number of dead monsters
+ * and as experience factor for the player killing more monsters.
+ * this means that a dragon dying by other means reduces the
+ * experience the player gets for killing a dragon directly; this
+ * is probably not too bad, since the player likely finagled the
+ * first dead dragon via ring of conflict or pets, and extinguishing
+ * based on only player kills probably opens more avenues of abuse
+ * for rings of conflict and such.
+ */
+ tmp = monsndx(mtmp->data);
+ if (mvitals[tmp].died < 255) mvitals[tmp].died++;
+
+ /* if it's a (possibly polymorphed) quest leader, mark him as dead */
+ if (mtmp->m_id == quest_status.leader_m_id)
+ quest_status.leader_is_dead = TRUE;
#ifdef MAIL
- /* if the mail daemon dies, no more mail delivery. -3. */
- if (tmp == PM_MAIL_DAEMON) mvitals[tmp].mvflags |= G_GENOD;
+ /* if the mail daemon dies, no more mail delivery. -3. */
+ if (tmp == PM_MAIL_DAEMON) mvitals[tmp].mvflags |= G_GENOD;
#endif
- if (mtmp->data->mlet == S_KOP) {
- /* Dead Kops may come back. */
- switch(rnd(5)) {
- case 1: /* returns near the stairs */
- (void) makemon(mtmp->data,xdnstair,ydnstair,NO_MM_FLAGS);
- break;
- case 2: /* randomly */
- (void) makemon(mtmp->data,0,0,NO_MM_FLAGS);
- break;
- default:
- break;
- }
- }
- if(mtmp->iswiz) wizdead();
- if(mtmp->data->msound == MS_NEMESIS) nemdead();
- if(glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
- unmap_object(mtmp->mx, mtmp->my);
- m_detach(mtmp, mptr);
+ if (mtmp->data->mlet == S_KOP) {
+ /* Dead Kops may come back. */
+ switch(rnd(5)) {
+ case 1: /* returns near the stairs */
+ (void) makemon(mtmp->data,xdnstair,ydnstair,NO_MM_FLAGS);
+ break;
+ case 2: /* randomly */
+ (void) makemon(mtmp->data,0,0,NO_MM_FLAGS);
+ break;
+ default:
+ break;
+ }
+ }
+ if(mtmp->iswiz) wizdead();
+ if(mtmp->data->msound == MS_NEMESIS) nemdead();
+ if(glyph_is_invisible(levl[mtmp->mx][mtmp->my].glyph))
+ unmap_object(mtmp->mx, mtmp->my);
+ m_detach(mtmp, mptr);
}
/* TRUE if corpse might be dropped, magr may die if mon was swallowed */
struct monst *magr; /* killer, if swallowed */
boolean was_swallowed; /* digestion */
{
- struct permonst *mdat = mon->data;
- int i, tmp;
-
- if (mdat == &mons[PM_VLAD_THE_IMPALER] || mdat->mlet == S_LICH) {
- if (cansee(mon->mx, mon->my) && !was_swallowed)
- pline("%s body crumbles into dust.", s_suffix(Monnam(mon)));
- return FALSE;
- }
-
- /* Gas spores always explode upon death */
- for(i = 0; i < NATTK; i++) {
- if (mdat->mattk[i].aatyp == AT_BOOM) {
- if (mdat->mattk[i].damn)
- tmp = d((int)mdat->mattk[i].damn,
- (int)mdat->mattk[i].damd);
- else if(mdat->mattk[i].damd)
- tmp = d((int)mdat->mlevel+1, (int)mdat->mattk[i].damd);
- else tmp = 0;
- if (was_swallowed && magr) {
- if (magr == &youmonst) {
- There("is an explosion in your %s!",
- body_part(STOMACH));
- Sprintf(killer.name, "%s explosion",
- s_suffix(mdat->mname));
- losehp(Maybe_Half_Phys(tmp), killer.name, KILLED_BY_AN);
- } else {
- You_hear("an explosion.");
- magr->mhp -= tmp;
- if (magr->mhp < 1) mondied(magr);
- if (magr->mhp < 1) { /* maybe lifesaved */
- if (canspotmon(magr))
- pline("%s rips open!", Monnam(magr));
- } else if (canseemon(magr))
- pline("%s seems to have indigestion.",
- Monnam(magr));
- }
-
- return FALSE;
- }
-
- Sprintf(killer.name, "%s explosion", s_suffix(mdat->mname));
- killer.format = KILLED_BY_AN;
- explode(mon->mx, mon->my, -1, tmp, MON_EXPLODE, EXPL_NOXIOUS);
- return (FALSE);
- }
- }
-
- /* must duplicate this below check in xkilled() since it results in
- * creating no objects as well as no corpse
- */
- if (LEVEL_SPECIFIC_NOCORPSE(mdat))
- return FALSE;
-
- if (((bigmonst(mdat) || mdat == &mons[PM_LIZARD]) && !mon->mcloned) ||
- is_golem(mdat) || is_mplayer(mdat) || is_rider(mdat))
- return TRUE;
- tmp = 2 + ((mdat->geno & G_FREQ) < 2) + verysmall(mdat);
- return (boolean) !rn2(tmp);
+ struct permonst *mdat = mon->data;
+ int i, tmp;
+
+ if (mdat == &mons[PM_VLAD_THE_IMPALER] || mdat->mlet == S_LICH) {
+ if (cansee(mon->mx, mon->my) && !was_swallowed)
+ pline("%s body crumbles into dust.", s_suffix(Monnam(mon)));
+ return FALSE;
+ }
+
+ /* Gas spores always explode upon death */
+ for(i = 0; i < NATTK; i++) {
+ if (mdat->mattk[i].aatyp == AT_BOOM) {
+ if (mdat->mattk[i].damn)
+ tmp = d((int)mdat->mattk[i].damn,
+ (int)mdat->mattk[i].damd);
+ else if(mdat->mattk[i].damd)
+ tmp = d((int)mdat->mlevel+1, (int)mdat->mattk[i].damd);
+ else tmp = 0;
+ if (was_swallowed && magr) {
+ if (magr == &youmonst) {
+ There("is an explosion in your %s!",
+ body_part(STOMACH));
+ Sprintf(killer.name, "%s explosion",
+ s_suffix(mdat->mname));
+ losehp(Maybe_Half_Phys(tmp), killer.name, KILLED_BY_AN);
+ } else {
+ You_hear("an explosion.");
+ magr->mhp -= tmp;
+ if (magr->mhp < 1) mondied(magr);
+ if (magr->mhp < 1) { /* maybe lifesaved */
+ if (canspotmon(magr))
+ pline("%s rips open!", Monnam(magr));
+ } else if (canseemon(magr))
+ pline("%s seems to have indigestion.",
+ Monnam(magr));
+ }
+
+ return FALSE;
+ }
+
+ Sprintf(killer.name, "%s explosion", s_suffix(mdat->mname));
+ killer.format = KILLED_BY_AN;
+ explode(mon->mx, mon->my, -1, tmp, MON_EXPLODE, EXPL_NOXIOUS);
+ return (FALSE);
+ }
+ }
+
+ /* must duplicate this below check in xkilled() since it results in
+ * creating no objects as well as no corpse
+ */
+ if (LEVEL_SPECIFIC_NOCORPSE(mdat))
+ return FALSE;
+
+ if (((bigmonst(mdat) || mdat == &mons[PM_LIZARD]) && !mon->mcloned) ||
+ is_golem(mdat) || is_mplayer(mdat) || is_rider(mdat))
+ return TRUE;
+ tmp = 2 + ((mdat->geno & G_FREQ) < 2) + verysmall(mdat);
+ return (boolean) !rn2(tmp);
}
/* drop (perhaps) a cadaver and remove monster */
mondied(mdef)
register struct monst *mdef;
{
- mondead(mdef);
- if (mdef->mhp > 0) return; /* lifesaved */
+ mondead(mdef);
+ if (mdef->mhp > 0) return; /* lifesaved */
- if (corpse_chance(mdef, (struct monst *)0, FALSE) &&
- (accessible(mdef->mx, mdef->my) || is_pool(mdef->mx, mdef->my)))
- (void) make_corpse(mdef,CORPSTAT_NONE);
+ if (corpse_chance(mdef, (struct monst *)0, FALSE) &&
+ (accessible(mdef->mx, mdef->my) || is_pool(mdef->mx, mdef->my)))
+ (void) make_corpse(mdef,CORPSTAT_NONE);
}
/* monster disappears, not dies */
mongone(mdef)
register struct monst *mdef;
{
- mdef->mhp = 0; /* can skip some inventory bookkeeping */
- /* Player is thrown from his steed when it disappears */
- if (mdef == u.usteed)
- dismount_steed(DISMOUNT_GENERIC);
+ mdef->mhp = 0; /* can skip some inventory bookkeeping */
+ /* Player is thrown from his steed when it disappears */
+ if (mdef == u.usteed)
+ dismount_steed(DISMOUNT_GENERIC);
- /* drop special items like the Amulet so that a dismissed Kop or nurse
- can't remove them from the game */
- mdrop_special_objs(mdef);
- /* release rest of monster's inventory--it is removed from game */
- discard_minvent(mdef);
- m_detach(mdef, mdef->data);
+ /* drop special items like the Amulet so that a dismissed Kop or nurse
+ can't remove them from the game */
+ mdrop_special_objs(mdef);
+ /* release rest of monster's inventory--it is removed from game */
+ discard_minvent(mdef);
+ m_detach(mdef, mdef->data);
}
/* drop a statue or rock and remove monster */
monstone(mdef)
register struct monst *mdef;
{
- struct obj *otmp, *obj, *oldminvent;
- xchar x = mdef->mx, y = mdef->my;
- boolean wasinside = FALSE;
-
- /* we have to make the statue before calling mondead, to be able to
- * put inventory in it, and we have to check for lifesaving before
- * making the statue....
- */
- lifesaved_monster(mdef);
- if (mdef->mhp > 0) return;
-
- mdef->mtrapped = 0; /* (see m_detach) */
-
- if ((int)mdef->data->msize > MZ_TINY ||
- !rn2(2 + ((int) (mdef->data->geno & G_FREQ) > 2))) {
- oldminvent = 0;
- /* some objects may end up outside the statue */
- while ((obj = mdef->minvent) != 0) {
- obj_extract_self(obj);
- if (obj->owornmask)
- update_mon_intrinsics(mdef, obj, FALSE, TRUE);
- obj_no_longer_held(obj);
- if (obj->owornmask & W_WEP)
- setmnotwielded(mdef,obj);
- obj->owornmask = 0L;
- if (obj->otyp == BOULDER ||
+ struct obj *otmp, *obj, *oldminvent;
+ xchar x = mdef->mx, y = mdef->my;
+ boolean wasinside = FALSE;
+
+ /* we have to make the statue before calling mondead, to be able to
+ * put inventory in it, and we have to check for lifesaving before
+ * making the statue....
+ */
+ lifesaved_monster(mdef);
+ if (mdef->mhp > 0) return;
+
+ mdef->mtrapped = 0; /* (see m_detach) */
+
+ if ((int)mdef->data->msize > MZ_TINY ||
+ !rn2(2 + ((int) (mdef->data->geno & G_FREQ) > 2))) {
+ oldminvent = 0;
+ /* some objects may end up outside the statue */
+ while ((obj = mdef->minvent) != 0) {
+ obj_extract_self(obj);
+ if (obj->owornmask)
+ update_mon_intrinsics(mdef, obj, FALSE, TRUE);
+ obj_no_longer_held(obj);
+ if (obj->owornmask & W_WEP)
+ setmnotwielded(mdef,obj);
+ obj->owornmask = 0L;
+ if (obj->otyp == BOULDER ||
#if 0 /* monsters don't carry statues */
(obj->otyp == STATUE && mons[obj->corpsenm].msize >= mdef->data->msize) ||
#endif
- obj_resists(obj, 0, 0)) {
- if (flooreffects(obj, x, y, "fall")) continue;
- place_object(obj, x, y);
- } else {
- if (obj->lamplit) end_burn(obj, TRUE);
- obj->nobj = oldminvent;
- oldminvent = obj;
- }
- }
- /* defer statue creation until after inventory removal
- so that saved monster traits won't retain any stale
- item-conferred attributes */
- otmp = mkcorpstat(STATUE, mdef, mdef->data, x, y, CORPSTAT_NONE);
- if (has_mname(mdef)) otmp = oname(otmp, MNAME(mdef));
- while ((obj = oldminvent) != 0) {
- oldminvent = obj->nobj;
- (void) add_to_container(otmp, obj);
- }
- /* Archeologists should not break unique statues */
- if (mdef->data->geno & G_UNIQ)
- otmp->spe = 1;
- otmp->owt = weight(otmp);
- } else
- otmp = mksobj_at(ROCK, x, y, TRUE, FALSE);
-
- stackobj(otmp);
- /* mondead() already does this, but we must do it before the newsym */
- if(glyph_is_invisible(levl[x][y].glyph))
- unmap_object(x, y);
- if (cansee(x, y)) newsym(x,y);
- /* We don't currently trap the hero in the statue in this case but we could */
- if (u.uswallow && u.ustuck == mdef) wasinside = TRUE;
- mondead(mdef);
- if (wasinside) {
- if (is_animal(mdef->data))
- You("%s through an opening in the new %s.",
- locomotion(youmonst.data, "jump"),
- xname(otmp));
- }
+ obj_resists(obj, 0, 0)) {
+ if (flooreffects(obj, x, y, "fall")) continue;
+ place_object(obj, x, y);
+ } else {
+ if (obj->lamplit) end_burn(obj, TRUE);
+ obj->nobj = oldminvent;
+ oldminvent = obj;
+ }
+ }
+ /* defer statue creation until after inventory removal
+ so that saved monster traits won't retain any stale
+ item-conferred attributes */
+ otmp = mkcorpstat(STATUE, mdef, mdef->data, x, y, CORPSTAT_NONE);
+ if (has_mname(mdef)) otmp = oname(otmp, MNAME(mdef));
+ while ((obj = oldminvent) != 0) {
+ oldminvent = obj->nobj;
+ (void) add_to_container(otmp, obj);
+ }
+ /* Archeologists should not break unique statues */
+ if (mdef->data->geno & G_UNIQ)
+ otmp->spe = 1;
+ otmp->owt = weight(otmp);
+ } else
+ otmp = mksobj_at(ROCK, x, y, TRUE, FALSE);
+
+ stackobj(otmp);
+ /* mondead() already does this, but we must do it before the newsym */
+ if(glyph_is_invisible(levl[x][y].glyph))
+ unmap_object(x, y);
+ if (cansee(x, y)) newsym(x,y);
+ /* We don't currently trap the hero in the statue in this case but we could */
+ if (u.uswallow && u.ustuck == mdef) wasinside = TRUE;
+ mondead(mdef);
+ if (wasinside) {
+ if (is_animal(mdef->data))
+ You("%s through an opening in the new %s.",
+ locomotion(youmonst.data, "jump"),
+ xname(otmp));
+ }
}
/* another monster has killed the monster mdef */
const char *fltxt;
int how;
{
- boolean be_sad = FALSE; /* true if unseen pet is killed */
+ boolean be_sad = FALSE; /* true if unseen pet is killed */
- if ((mdef->wormno ? worm_known(mdef) : cansee(mdef->mx, mdef->my))
- && fltxt)
- pline("%s is %s%s%s!", Monnam(mdef),
- nonliving(mdef->data) ? "destroyed" : "killed",
- *fltxt ? " by the " : "",
- fltxt
- );
- else
- be_sad = (mdef->mtame != 0);
+ if ((mdef->wormno ? worm_known(mdef) : cansee(mdef->mx, mdef->my))
+ && fltxt)
+ pline("%s is %s%s%s!", Monnam(mdef),
+ nonliving(mdef->data) ? "destroyed" : "killed",
+ *fltxt ? " by the " : "",
+ fltxt
+ );
+ else
+ be_sad = (mdef->mtame != 0);
- /* no corpses if digested or disintegrated */
- if(how == AD_DGST || how == -AD_RBRE)
- mondead(mdef);
- else
- mondied(mdef);
+ /* no corpses if digested or disintegrated */
+ if(how == AD_DGST || how == -AD_RBRE)
+ mondead(mdef);
+ else
+ mondied(mdef);
- if (be_sad && mdef->mhp <= 0)
- You("have a sad feeling for a moment, then it passes.");
+ if (be_sad && mdef->mhp <= 0)
+ You("have a sad feeling for a moment, then it passes.");
}
void
unstuck(mtmp)
register struct monst *mtmp;
{
- if(u.ustuck == mtmp) {
- if(u.uswallow){
- u.ux = mtmp->mx;
- u.uy = mtmp->my;
- u.uswallow = 0;
- u.uswldtim = 0;
- if (Punished) placebc();
- vision_full_recalc = 1;
- docrt();
- }
- u.ustuck = 0;
- }
+ if(u.ustuck == mtmp) {
+ if(u.uswallow){
+ u.ux = mtmp->mx;
+ u.uy = mtmp->my;
+ u.uswallow = 0;
+ u.uswldtim = 0;
+ if (Punished) placebc();
+ vision_full_recalc = 1;
+ docrt();
+ }
+ u.ustuck = 0;
+ }
}
void
killed(mtmp)
register struct monst *mtmp;
{
- xkilled(mtmp, 1);
+ xkilled(mtmp, 1);
}
/* the player has killed the monster mtmp */
*/
int dest;
{
- int tmp, mndx, x = mtmp->mx, y = mtmp->my;
- struct permonst *mdat;
- struct obj *otmp;
- struct trap *t;
- boolean wasinside = u.uswallow && (u.ustuck == mtmp);
- boolean burycorpse = FALSE;
-
- /* KMH, conduct */
- u.uconduct.killer++;
-
- if (dest & 1) {
- const char *verb = nonliving(mtmp->data) ? "destroy" : "kill";
-
- if (!wasinside && !canspotmon(mtmp))
- You("%s it!", verb);
- else {
- You("%s %s!", verb,
- !mtmp->mtame ? mon_nam(mtmp) :
- x_monnam(mtmp,
- (has_mname(mtmp)) ? ARTICLE_NONE : ARTICLE_THE,
- "poor",
- (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0,
- FALSE));
- }
- }
-
- if (mtmp->mtrapped && (t = t_at(x, y)) != 0 &&
- (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) {
-
- if (sobj_at(BOULDER, x, y))
- dest |= 2; /*
- * Prevent corpses/treasure being created "on top"
- * of the boulder that is about to fall in. This is
- * out of order, but cannot be helped unless this
- * whole routine is rearranged.
- */
- if (m_carrying(mtmp, BOULDER))
- burycorpse = TRUE;
- }
-
- /* your pet knows who just killed it...watch out */
- if (mtmp->mtame && !mtmp->isminion) EDOG(mtmp)->killed_by_u = 1;
-
- if (wasinside && thrownobj && thrownobj != uball) {
- /* thrown object has killed hero's engulfer; add it to mon's
- inventory now so that it will be placed with mon's other
- stuff prior to lookhere/autopickup when hero is expelled
- below (as a side-effect, this missile has immunity from
- being consumed [for this shot/throw only]) */
- mpickobj(mtmp, thrownobj);
- /* let throwing code know that missile has been disposed of */
- thrownobj = 0;
- }
-
- /* dispose of monster and make cadaver */
- if(stoned) monstone(mtmp);
- else mondead(mtmp);
-
- if (mtmp->mhp > 0) { /* monster lifesaved */
- /* Cannot put the non-visible lifesaving message in
- * lifesaved_monster() since the message appears only when you
- * kill it (as opposed to visible lifesaving which always
- * appears).
- */
- stoned = FALSE;
- if (!cansee(x,y)) pline("Maybe not...");
- return;
- }
-
- mdat = mtmp->data; /* note: mondead can change mtmp->data */
- mndx = monsndx(mdat);
-
- if (stoned) {
- stoned = FALSE;
- goto cleanup;
- }
-
- if((dest & 2) || LEVEL_SPECIFIC_NOCORPSE(mdat))
- goto cleanup;
+ int tmp, mndx, x = mtmp->mx, y = mtmp->my;
+ struct permonst *mdat;
+ struct obj *otmp;
+ struct trap *t;
+ boolean wasinside = u.uswallow && (u.ustuck == mtmp);
+ boolean burycorpse = FALSE;
+
+ /* KMH, conduct */
+ u.uconduct.killer++;
+
+ if (dest & 1) {
+ const char *verb = nonliving(mtmp->data) ? "destroy" : "kill";
+
+ if (!wasinside && !canspotmon(mtmp))
+ You("%s it!", verb);
+ else {
+ You("%s %s!", verb,
+ !mtmp->mtame ? mon_nam(mtmp) :
+ x_monnam(mtmp,
+ (has_mname(mtmp)) ? ARTICLE_NONE : ARTICLE_THE,
+ "poor",
+ (has_mname(mtmp)) ? SUPPRESS_SADDLE : 0,
+ FALSE));
+ }
+ }
+
+ if (mtmp->mtrapped && (t = t_at(x, y)) != 0 &&
+ (t->ttyp == PIT || t->ttyp == SPIKED_PIT)) {
+
+ if (sobj_at(BOULDER, x, y))
+ dest |= 2; /*
+ * Prevent corpses/treasure being created "on top"
+ * of the boulder that is about to fall in. This is
+ * out of order, but cannot be helped unless this
+ * whole routine is rearranged.
+ */
+ if (m_carrying(mtmp, BOULDER))
+ burycorpse = TRUE;
+ }
+
+ /* your pet knows who just killed it...watch out */
+ if (mtmp->mtame && !mtmp->isminion) EDOG(mtmp)->killed_by_u = 1;
+
+ if (wasinside && thrownobj && thrownobj != uball) {
+ /* thrown object has killed hero's engulfer; add it to mon's
+ inventory now so that it will be placed with mon's other
+ stuff prior to lookhere/autopickup when hero is expelled
+ below (as a side-effect, this missile has immunity from
+ being consumed [for this shot/throw only]) */
+ mpickobj(mtmp, thrownobj);
+ /* let throwing code know that missile has been disposed of */
+ thrownobj = 0;
+ }
+
+ /* dispose of monster and make cadaver */
+ if(stoned) monstone(mtmp);
+ else mondead(mtmp);
+
+ if (mtmp->mhp > 0) { /* monster lifesaved */
+ /* Cannot put the non-visible lifesaving message in
+ * lifesaved_monster() since the message appears only when you
+ * kill it (as opposed to visible lifesaving which always
+ * appears).
+ */
+ stoned = FALSE;
+ if (!cansee(x,y)) pline("Maybe not...");
+ return;
+ }
+
+ mdat = mtmp->data; /* note: mondead can change mtmp->data */
+ mndx = monsndx(mdat);
+
+ if (stoned) {
+ stoned = FALSE;
+ goto cleanup;
+ }
+
+ if((dest & 2) || LEVEL_SPECIFIC_NOCORPSE(mdat))
+ goto cleanup;
#ifdef MAIL
- if(mdat == &mons[PM_MAIL_DAEMON]) {
- stackobj(mksobj_at(SCR_MAIL, x, y, FALSE, FALSE));
- }
+ if(mdat == &mons[PM_MAIL_DAEMON]) {
+ stackobj(mksobj_at(SCR_MAIL, x, y, FALSE, FALSE));
+ }
#endif
- if (accessible(x, y) || is_pool(x, y)) {
- struct obj *cadaver;
- int otyp;
-
- /* illogical but traditional "treasure drop" */
- if (!rn2(6) && !(mvitals[mndx].mvflags & G_NOCORPSE)
- /* no extra item from swallower or steed */
- && (x != u.ux || y != u.uy)
- /* no extra item from kops--too easy to abuse */
- && mdat->mlet != S_KOP
+ if (accessible(x, y) || is_pool(x, y)) {
+ struct obj *cadaver;
+ int otyp;
+
+ /* illogical but traditional "treasure drop" */
+ if (!rn2(6) && !(mvitals[mndx].mvflags & G_NOCORPSE)
+ /* no extra item from swallower or steed */
+ && (x != u.ux || y != u.uy)
+ /* no extra item from kops--too easy to abuse */
+ && mdat->mlet != S_KOP
/* no items from cloned monsters */
- && !mtmp->mcloned) {
- otmp = mkobj(RANDOM_CLASS, TRUE);
- /* don't create large objects from small monsters */
- otyp = otmp->otyp;
- if (mdat->msize < MZ_HUMAN && otyp != FIGURINE &&
- /* oc_big is also oc_bimanual and oc_bulky */
- (otmp->owt > 30 || objects[otyp].oc_big)) {
- delobj(otmp);
- } else if (!flooreffects(otmp, x, y,
- (dest & 1) ? "fall" : "")) {
- place_object(otmp, x, y);
- stackobj(otmp);
- }
- }
- /* corpse--none if hero was inside the monster */
- if (!wasinside && corpse_chance(mtmp, (struct monst *)0, FALSE)) {
- cadaver = make_corpse(mtmp, burycorpse ?
- CORPSTAT_BURIED : CORPSTAT_NONE);
- if (burycorpse && cadaver && cansee(x,y) && !mtmp->minvis &&
- cadaver->where == OBJ_BURIED && (dest & 1)) {
- pline("%s corpse ends up buried.", s_suffix(Monnam(mtmp)));
- }
- }
- }
- if (wasinside) spoteffects(TRUE); /* poor man's expels() */
- /* monster is gone, corpse or other object might now be visible */
- newsym(x, y);
+ && !mtmp->mcloned) {
+ otmp = mkobj(RANDOM_CLASS, TRUE);
+ /* don't create large objects from small monsters */
+ otyp = otmp->otyp;
+ if (mdat->msize < MZ_HUMAN && otyp != FIGURINE &&
+ /* oc_big is also oc_bimanual and oc_bulky */
+ (otmp->owt > 30 || objects[otyp].oc_big)) {
+ delobj(otmp);
+ } else if (!flooreffects(otmp, x, y,
+ (dest & 1) ? "fall" : "")) {
+ place_object(otmp, x, y);
+ stackobj(otmp);
+ }
+ }
+ /* corpse--none if hero was inside the monster */
+ if (!wasinside && corpse_chance(mtmp, (struct monst *)0, FALSE)) {
+ cadaver = make_corpse(mtmp, burycorpse ?
+ CORPSTAT_BURIED : CORPSTAT_NONE);
+ if (burycorpse && cadaver && cansee(x,y) && !mtmp->minvis &&
+ cadaver->where == OBJ_BURIED && (dest & 1)) {
+ pline("%s corpse ends up buried.", s_suffix(Monnam(mtmp)));
+ }
+ }
+ }
+ if (wasinside) spoteffects(TRUE); /* poor man's expels() */
+ /* monster is gone, corpse or other object might now be visible */
+ newsym(x, y);
cleanup:
- /* punish bad behaviour */
- if(is_human(mdat) && (!always_hostile(mdat) && mtmp->malign <= 0) &&
- (mndx < PM_ARCHEOLOGIST || mndx > PM_WIZARD) &&
- u.ualign.type != A_CHAOTIC) {
- HTelepat &= ~INTRINSIC;
- change_luck(-2);
- You("murderer!");
- if (Blind && !Blind_telepat)
- see_monsters(); /* Can't sense monsters any more. */
- }
- if((mtmp->mpeaceful && !rn2(2)) || mtmp->mtame) change_luck(-1);
- if (is_unicorn(mdat) &&
- sgn(u.ualign.type) == sgn(mdat->maligntyp)) {
- change_luck(-5);
- You_feel("guilty...");
- }
-
- /* give experience points */
- tmp = experience(mtmp, (int)mvitals[mndx].died);
- more_experienced(tmp, 0);
- newexplevel(); /* will decide if you go up */
-
- /* adjust alignment points */
- if (mtmp->m_id == quest_status.leader_m_id) { /* REAL BAD! */
- adjalign(-(u.ualign.record+(int)ALIGNLIM/2));
- pline("That was %sa bad idea...",
- u.uevent.qcompleted ? "probably " : "");
- } else if (mdat->msound == MS_NEMESIS) /* Real good! */
- adjalign((int)(ALIGNLIM/4));
- else if (mdat->msound == MS_GUARDIAN) { /* Bad */
- adjalign(-(int)(ALIGNLIM/8));
- if (!Hallucination) pline("That was probably a bad idea...");
- else pline("Whoopsie-daisy!");
- }else if (mtmp->ispriest) {
- adjalign((p_coaligned(mtmp)) ? -2 : 2);
- /* cancel divine protection for killing your priest */
- if (p_coaligned(mtmp)) u.ublessed = 0;
- if (mdat->maligntyp == A_NONE)
- adjalign((int)(ALIGNLIM / 4)); /* BIG bonus */
- } else if (mtmp->mtame) {
- adjalign(-15); /* bad!! */
- /* your god is mighty displeased... */
- if (!Hallucination) You_hear("the rumble of distant thunder...");
- else You_hear("the studio audience applaud!");
- } else if (mtmp->mpeaceful)
- adjalign(-5);
-
- /* malign was already adjusted for u.ualign.type and randomization */
- adjalign(mtmp->malign);
+ /* punish bad behaviour */
+ if(is_human(mdat) && (!always_hostile(mdat) && mtmp->malign <= 0) &&
+ (mndx < PM_ARCHEOLOGIST || mndx > PM_WIZARD) &&
+ u.ualign.type != A_CHAOTIC) {
+ HTelepat &= ~INTRINSIC;
+ change_luck(-2);
+ You("murderer!");
+ if (Blind && !Blind_telepat)
+ see_monsters(); /* Can't sense monsters any more. */
+ }
+ if((mtmp->mpeaceful && !rn2(2)) || mtmp->mtame) change_luck(-1);
+ if (is_unicorn(mdat) &&
+ sgn(u.ualign.type) == sgn(mdat->maligntyp)) {
+ change_luck(-5);
+ You_feel("guilty...");
+ }
+
+ /* give experience points */
+ tmp = experience(mtmp, (int)mvitals[mndx].died);
+ more_experienced(tmp, 0);
+ newexplevel(); /* will decide if you go up */
+
+ /* adjust alignment points */
+ if (mtmp->m_id == quest_status.leader_m_id) { /* REAL BAD! */
+ adjalign(-(u.ualign.record+(int)ALIGNLIM/2));
+ pline("That was %sa bad idea...",
+ u.uevent.qcompleted ? "probably " : "");
+ } else if (mdat->msound == MS_NEMESIS) /* Real good! */
+ adjalign((int)(ALIGNLIM/4));
+ else if (mdat->msound == MS_GUARDIAN) { /* Bad */
+ adjalign(-(int)(ALIGNLIM/8));
+ if (!Hallucination) pline("That was probably a bad idea...");
+ else pline("Whoopsie-daisy!");
+ }else if (mtmp->ispriest) {
+ adjalign((p_coaligned(mtmp)) ? -2 : 2);
+ /* cancel divine protection for killing your priest */
+ if (p_coaligned(mtmp)) u.ublessed = 0;
+ if (mdat->maligntyp == A_NONE)
+ adjalign((int)(ALIGNLIM / 4)); /* BIG bonus */
+ } else if (mtmp->mtame) {
+ adjalign(-15); /* bad!! */
+ /* your god is mighty displeased... */
+ if (!Hallucination) You_hear("the rumble of distant thunder...");
+ else You_hear("the studio audience applaud!");
+ } else if (mtmp->mpeaceful)
+ adjalign(-5);
+
+ /* malign was already adjusted for u.ualign.type and randomization */
+ adjalign(mtmp->malign);
}
/* changes the monster into a stone monster of the same type */
register struct monst *mtmp;
{
if(mtmp->data->mlet == S_GOLEM) {
- /* it's a golem, and not a stone golem */
- if(canseemon(mtmp))
- pline("%s solidifies...", Monnam(mtmp));
- if (newcham(mtmp, &mons[PM_STONE_GOLEM], FALSE, FALSE)) {
- if(canseemon(mtmp))
- pline("Now it's %s.", an(mtmp->data->mname));
- } else {
- if(canseemon(mtmp))
- pline("... and returns to normal.");
- }
+ /* it's a golem, and not a stone golem */
+ if(canseemon(mtmp))
+ pline("%s solidifies...", Monnam(mtmp));
+ if (newcham(mtmp, &mons[PM_STONE_GOLEM], FALSE, FALSE)) {
+ if(canseemon(mtmp))
+ pline("Now it's %s.", an(mtmp->data->mname));
+ } else {
+ if(canseemon(mtmp))
+ pline("... and returns to normal.");
+ }
} else
- impossible("Can't polystone %s!", a_monnam(mtmp));
+ impossible("Can't polystone %s!", a_monnam(mtmp));
}
/* might place monst on far side of a wall or boulder */
void
mnexto(mtmp) /* Make monster mtmp next to you (if possible) */
- struct monst *mtmp;
+ struct monst *mtmp;
{
- coord mm;
- boolean couldspot = canspotmon(mtmp);
+ coord mm;
+ boolean couldspot = canspotmon(mtmp);
- if (mtmp == u.usteed) {
- /* Keep your steed in sync with you instead */
- mtmp->mx = u.ux;
- mtmp->my = u.uy;
- return;
- }
+ if (mtmp == u.usteed) {
+ /* Keep your steed in sync with you instead */
+ mtmp->mx = u.ux;
+ mtmp->my = u.uy;
+ return;
+ }
- if(!enexto(&mm, u.ux, u.uy, mtmp->data)) return;
- rloc_to(mtmp, mm.x, mm.y);
- if (!in_mklev && (mtmp->mstrategy & STRAT_APPEARMSG)) {
- mtmp->mstrategy &= ~STRAT_APPEARMSG; /* one chance only */
- if (!couldspot && canspotmon(mtmp))
- pline("%s suddenly %s!", Amonnam(mtmp),
- !Blind ? "appears" : "arrives");
- }
- return;
+ if(!enexto(&mm, u.ux, u.uy, mtmp->data)) return;
+ rloc_to(mtmp, mm.x, mm.y);
+ if (!in_mklev && (mtmp->mstrategy & STRAT_APPEARMSG)) {
+ mtmp->mstrategy &= ~STRAT_APPEARMSG; /* one chance only */
+ if (!couldspot && canspotmon(mtmp))
+ pline("%s suddenly %s!", Amonnam(mtmp),
+ !Blind ? "appears" : "arrives");
+ }
+ return;
}
/* like mnexto() but requires destination to be directly accessible */
maybe_mnexto(mtmp)
struct monst *mtmp;
{
- coord mm;
- struct permonst *ptr = mtmp->data;
- boolean diagok = !NODIAG(ptr - mons);
- int tryct = 20;
+ coord mm;
+ struct permonst *ptr = mtmp->data;
+ boolean diagok = !NODIAG(ptr - mons);
+ int tryct = 20;
- do {
- if (!enexto(&mm, u.ux, u.uy, ptr)) return;
- if (couldsee(mm.x, mm.y) &&
- /* don't move grid bugs diagonally */
- (diagok || mm.x == mtmp->mx || mm.y == mtmp->my)) {
- rloc_to(mtmp, mm.x, mm.y);
- return;
- }
- } while (--tryct > 0);
+ do {
+ if (!enexto(&mm, u.ux, u.uy, ptr)) return;
+ if (couldsee(mm.x, mm.y) &&
+ /* don't move grid bugs diagonally */
+ (diagok || mm.x == mtmp->mx || mm.y == mtmp->my)) {
+ rloc_to(mtmp, mm.x, mm.y);
+ return;
+ }
+ } while (--tryct > 0);
}
/* mnearto()
xchar x, y;
boolean move_other; /* make sure mtmp gets to x, y! so move m_at(x, y) */
{
- struct monst *othermon = (struct monst *)0;
- xchar newx, newy;
- coord mm;
+ struct monst *othermon = (struct monst *)0;
+ xchar newx, newy;
+ coord mm;
- if ((mtmp->mx == x) && (mtmp->my == y)) return(FALSE);
+ if ((mtmp->mx == x) && (mtmp->my == y)) return(FALSE);
- if (move_other && (othermon = m_at(x, y))) {
- if (othermon->wormno)
- remove_worm(othermon);
- else
- remove_monster(x, y);
- }
+ if (move_other && (othermon = m_at(x, y))) {
+ if (othermon->wormno)
+ remove_worm(othermon);
+ else
+ remove_monster(x, y);
+ }
- newx = x;
- newy = y;
+ newx = x;
+ newy = y;
- if (!goodpos(newx, newy, mtmp, 0)) {
- /* actually we have real problems if enexto ever fails.
- * migrating_mons that need to be placed will cause
- * no end of trouble.
- */
- if (!enexto(&mm, newx, newy, mtmp->data)) return(FALSE);
- newx = mm.x; newy = mm.y;
- }
+ if (!goodpos(newx, newy, mtmp, 0)) {
+ /* actually we have real problems if enexto ever fails.
+ * migrating_mons that need to be placed will cause
+ * no end of trouble.
+ */
+ if (!enexto(&mm, newx, newy, mtmp->data)) return(FALSE);
+ newx = mm.x; newy = mm.y;
+ }
- rloc_to(mtmp, newx, newy);
+ rloc_to(mtmp, newx, newy);
- if (move_other && othermon) {
- othermon->mx = othermon->my = 0;
- (void) mnearto(othermon, x, y, FALSE);
- if ((othermon->mx != x) || (othermon->my != y))
- return(TRUE);
- }
+ if (move_other && othermon) {
+ othermon->mx = othermon->my = 0;
+ (void) mnearto(othermon, x, y, FALSE);
+ if ((othermon->mx != x) || (othermon->my != y))
+ return(TRUE);
+ }
- return(FALSE);
+ return(FALSE);
}
/* monster responds to player action; not the same as a passive attack */
register struct monst *mtmp;
{
if(mtmp->data->msound == MS_SHRIEK) {
- if(!Deaf) {
- pline("%s shrieks.", Monnam(mtmp));
- stop_occupation();
- }
- if (!rn2(10)) {
- if (!rn2(13))
- (void) makemon(&mons[PM_PURPLE_WORM], 0, 0, NO_MM_FLAGS);
- else
- (void) makemon((struct permonst *)0, 0, 0, NO_MM_FLAGS);
-
- }
- aggravate();
+ if(!Deaf) {
+ pline("%s shrieks.", Monnam(mtmp));
+ stop_occupation();
+ }
+ if (!rn2(10)) {
+ if (!rn2(13))
+ (void) makemon(&mons[PM_PURPLE_WORM], 0, 0, NO_MM_FLAGS);
+ else
+ (void) makemon((struct permonst *)0, 0, 0, NO_MM_FLAGS);
+
+ }
+ aggravate();
}
if(mtmp->data == &mons[PM_MEDUSA]) {
- register int i;
- for(i = 0; i < NATTK; i++)
- if(mtmp->data->mattk[i].aatyp == AT_GAZE) {
- (void) gazemu(mtmp, &mtmp->data->mattk[i]);
- break;
- }
+ register int i;
+ for(i = 0; i < NATTK; i++)
+ if(mtmp->data->mattk[i].aatyp == AT_GAZE) {
+ (void) gazemu(mtmp, &mtmp->data->mattk[i]);
+ break;
+ }
}
}
setmangry(mtmp)
register struct monst *mtmp;
{
- mtmp->mstrategy &= ~STRAT_WAITMASK;
- if(!mtmp->mpeaceful) return;
- if(mtmp->mtame) return;
- mtmp->mpeaceful = 0;
- if(mtmp->ispriest) {
- if(p_coaligned(mtmp)) adjalign(-5); /* very bad */
- else adjalign(2);
- } else
- adjalign(-1); /* attacking peaceful monsters is bad */
- if (couldsee(mtmp->mx, mtmp->my)) {
- if (humanoid(mtmp->data) || mtmp->isshk || mtmp->isgd)
- pline("%s gets angry!", Monnam(mtmp));
- else if (flags.verbose && !Deaf) growl(mtmp);
- }
-
- /* attacking your own quest leader will anger his or her guardians */
- if (!context.mon_moving && /* should always be the case here */
- mtmp->data == &mons[quest_info(MS_LEADER)]) {
- struct monst *mon;
- struct permonst *q_guardian = &mons[quest_info(MS_GUARDIAN)];
- int got_mad = 0;
-
- /* guardians will sense this attack even if they can't see it */
- for (mon = fmon; mon; mon = mon->nmon) {
- if (DEADMONSTER(mon)) continue;
- if (mon->data == q_guardian && mon->mpeaceful) {
- mon->mpeaceful = 0;
- if (canseemon(mon)) ++got_mad;
- }
- }
- if (got_mad && !Hallucination)
- pline_The("%s appear%s to be angry too...",
- got_mad == 1 ? q_guardian->mname :
- makeplural(q_guardian->mname),
- got_mad == 1 ? "s" : "");
- }
+ mtmp->mstrategy &= ~STRAT_WAITMASK;
+ if(!mtmp->mpeaceful) return;
+ if(mtmp->mtame) return;
+ mtmp->mpeaceful = 0;
+ if(mtmp->ispriest) {
+ if(p_coaligned(mtmp)) adjalign(-5); /* very bad */
+ else adjalign(2);
+ } else
+ adjalign(-1); /* attacking peaceful monsters is bad */
+ if (couldsee(mtmp->mx, mtmp->my)) {
+ if (humanoid(mtmp->data) || mtmp->isshk || mtmp->isgd)
+ pline("%s gets angry!", Monnam(mtmp));
+ else if (flags.verbose && !Deaf) growl(mtmp);
+ }
+
+ /* attacking your own quest leader will anger his or her guardians */
+ if (!context.mon_moving && /* should always be the case here */
+ mtmp->data == &mons[quest_info(MS_LEADER)]) {
+ struct monst *mon;
+ struct permonst *q_guardian = &mons[quest_info(MS_GUARDIAN)];
+ int got_mad = 0;
+
+ /* guardians will sense this attack even if they can't see it */
+ for (mon = fmon; mon; mon = mon->nmon) {
+ if (DEADMONSTER(mon)) continue;
+ if (mon->data == q_guardian && mon->mpeaceful) {
+ mon->mpeaceful = 0;
+ if (canseemon(mon)) ++got_mad;
+ }
+ }
+ if (got_mad && !Hallucination)
+ pline_The("%s appear%s to be angry too...",
+ got_mad == 1 ? q_guardian->mname :
+ makeplural(q_guardian->mname),
+ got_mad == 1 ? "s" : "");
+ }
}
void
wakeup(mtmp)
register struct monst *mtmp;
{
- mtmp->msleeping = 0;
- finish_meating(mtmp);
- setmangry(mtmp);
- if (mtmp->m_ap_type) {
- seemimic(mtmp);
- } else if (context.forcefight && !context.mon_moving &&
- mtmp->mundetected) {
- mtmp->mundetected = 0;
- newsym(mtmp->mx, mtmp->my);
- }
+ mtmp->msleeping = 0;
+ finish_meating(mtmp);
+ setmangry(mtmp);
+ if (mtmp->m_ap_type) {
+ seemimic(mtmp);
+ } else if (context.forcefight && !context.mon_moving &&
+ mtmp->mundetected) {
+ mtmp->mundetected = 0;
+ newsym(mtmp->mx, mtmp->my);
+ }
}
/* Wake up nearby monsters without angering them. */
void
wake_nearby()
{
- register struct monst *mtmp;
+ register struct monst *mtmp;
- for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- if (distu(mtmp->mx,mtmp->my) < u.ulevel * 20) {
- mtmp->msleeping = 0;
- mtmp->mstrategy &= ~STRAT_WAITMASK;
- if (mtmp->mtame && !mtmp->isminion)
- EDOG(mtmp)->whistletime = moves;
- }
- }
+ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ if (distu(mtmp->mx,mtmp->my) < u.ulevel * 20) {
+ mtmp->msleeping = 0;
+ mtmp->mstrategy &= ~STRAT_WAITMASK;
+ if (mtmp->mtame && !mtmp->isminion)
+ EDOG(mtmp)->whistletime = moves;
+ }
+ }
}
/* Wake up monsters near some particular location. */
wake_nearto(x, y, distance)
register int x, y, distance;
{
- register struct monst *mtmp;
+ register struct monst *mtmp;
- for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- if (distance == 0 || dist2(mtmp->mx, mtmp->my, x, y) < distance) {
- mtmp->msleeping = 0;
- mtmp->mstrategy &= ~STRAT_WAITMASK;
- }
- }
+ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ if (distance == 0 || dist2(mtmp->mx, mtmp->my, x, y) < distance) {
+ mtmp->msleeping = 0;
+ mtmp->mstrategy &= ~STRAT_WAITMASK;
+ }
+ }
}
/* NOTE: we must check for mimicry before calling this routine */
seemimic(mtmp)
register struct monst *mtmp;
{
- unsigned old_app = mtmp->mappearance;
- uchar old_ap_type = mtmp->m_ap_type;
+ unsigned old_app = mtmp->mappearance;
+ uchar old_ap_type = mtmp->m_ap_type;
- if (has_mcorpsenm(mtmp)) freemcorpsenm(mtmp);
+ if (has_mcorpsenm(mtmp)) freemcorpsenm(mtmp);
- mtmp->m_ap_type = M_AP_NOTHING;
- mtmp->mappearance = 0;
+ mtmp->m_ap_type = M_AP_NOTHING;
+ mtmp->mappearance = 0;
- /*
- * Discovered mimics don't block light.
- */
- if (((old_ap_type == M_AP_FURNITURE &&
- (old_app == S_hcdoor || old_app == S_vcdoor)) ||
- (old_ap_type == M_AP_OBJECT && old_app == BOULDER)) &&
- !does_block(mtmp->mx, mtmp->my, &levl[mtmp->mx][mtmp->my]))
- unblock_point(mtmp->mx, mtmp->my);
+ /*
+ * Discovered mimics don't block light.
+ */
+ if (((old_ap_type == M_AP_FURNITURE &&
+ (old_app == S_hcdoor || old_app == S_vcdoor)) ||
+ (old_ap_type == M_AP_OBJECT && old_app == BOULDER)) &&
+ !does_block(mtmp->mx, mtmp->my, &levl[mtmp->mx][mtmp->my]))
+ unblock_point(mtmp->mx, mtmp->my);
- newsym(mtmp->mx,mtmp->my);
+ newsym(mtmp->mx,mtmp->my);
}
/* force all chameleons to become normal */
void
rescham()
{
- register struct monst *mtmp;
- int mcham;
-
- for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- mcham = (int) mtmp->cham;
- if (mcham >= LOW_PM) {
- (void) newcham(mtmp, &mons[mcham],
- FALSE, FALSE);
- mtmp->cham = NON_PM;
- }
- if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
- new_were(mtmp);
- if(mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my)) {
- seemimic(mtmp);
- /* we pretend that the mimic doesn't */
- /* know that it has been unmasked. */
- mtmp->msleeping = 1;
- }
- }
+ register struct monst *mtmp;
+ int mcham;
+
+ for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ mcham = (int) mtmp->cham;
+ if (mcham >= LOW_PM) {
+ (void) newcham(mtmp, &mons[mcham],
+ FALSE, FALSE);
+ mtmp->cham = NON_PM;
+ }
+ if(is_were(mtmp->data) && mtmp->data->mlet != S_HUMAN)
+ new_were(mtmp);
+ if(mtmp->m_ap_type && cansee(mtmp->mx, mtmp->my)) {
+ seemimic(mtmp);
+ /* we pretend that the mimic doesn't */
+ /* know that it has been unmasked. */
+ mtmp->msleeping = 1;
+ }
+ }
}
/* Let the chameleons change again -dgk */
void
restartcham()
{
- register struct monst *mtmp;
+ register struct monst *mtmp;
- for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- mtmp->cham = pm_to_cham(monsndx(mtmp->data));
- if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping &&
- cansee(mtmp->mx, mtmp->my)) {
- set_mimic_sym(mtmp);
- newsym(mtmp->mx,mtmp->my);
- }
- }
+ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ mtmp->cham = pm_to_cham(monsndx(mtmp->data));
+ if (mtmp->data->mlet == S_MIMIC && mtmp->msleeping &&
+ cansee(mtmp->mx, mtmp->my)) {
+ set_mimic_sym(mtmp);
+ newsym(mtmp->mx,mtmp->my);
+ }
+ }
}
/* called when restoring a monster from a saved level; protection
restore_cham(mon)
struct monst *mon;
{
- int mcham;
-
- if (Protection_from_shape_changers) {
- mcham = (int) mon->cham;
- if (mcham >= LOW_PM) {
- mon->cham = NON_PM;
- (void) newcham(mon, &mons[mcham], FALSE, FALSE);
- } else if (is_were(mon->data) && !is_human(mon->data)) {
- new_were(mon);
- }
- } else if (mon->cham == NON_PM) {
- mon->cham = pm_to_cham(monsndx(mon->data));
- }
+ int mcham;
+
+ if (Protection_from_shape_changers) {
+ mcham = (int) mon->cham;
+ if (mcham >= LOW_PM) {
+ mon->cham = NON_PM;
+ (void) newcham(mon, &mons[mcham], FALSE, FALSE);
+ } else if (is_were(mon->data) && !is_human(mon->data)) {
+ new_were(mon);
+ }
+ } else if (mon->cham == NON_PM) {
+ mon->cham = pm_to_cham(monsndx(mon->data));
+ }
}
/* unwatched hiders may hide again; if so, a 1 is returned. */
restrap(mtmp)
register struct monst *mtmp;
{
- struct trap *t;
+ struct trap *t;
- if (mtmp->mcan || mtmp->m_ap_type ||
- cansee(mtmp->mx, mtmp->my) || rn2(3) || (mtmp == u.ustuck) ||
- /* can't hide while trapped except in pits */
- (mtmp->mtrapped && (t = t_at(mtmp->mx, mtmp->my)) != 0 &&
- !(t->ttyp == PIT || t->ttyp == SPIKED_PIT)) ||
- (sensemon(mtmp) && distu(mtmp->mx, mtmp->my) <= 2))
- return(FALSE);
+ if (mtmp->mcan || mtmp->m_ap_type ||
+ cansee(mtmp->mx, mtmp->my) || rn2(3) || (mtmp == u.ustuck) ||
+ /* can't hide while trapped except in pits */
+ (mtmp->mtrapped && (t = t_at(mtmp->mx, mtmp->my)) != 0 &&
+ !(t->ttyp == PIT || t->ttyp == SPIKED_PIT)) ||
+ (sensemon(mtmp) && distu(mtmp->mx, mtmp->my) <= 2))
+ return(FALSE);
- if(mtmp->data->mlet == S_MIMIC) {
- set_mimic_sym(mtmp);
- return(TRUE);
- } else
- if(levl[mtmp->mx][mtmp->my].typ == ROOM) {
- mtmp->mundetected = 1;
- return(TRUE);
- }
+ if(mtmp->data->mlet == S_MIMIC) {
+ set_mimic_sym(mtmp);
+ return(TRUE);
+ } else
+ if(levl[mtmp->mx][mtmp->my].typ == ROOM) {
+ mtmp->mundetected = 1;
+ return(TRUE);
+ }
- return(FALSE);
+ return(FALSE);
}
/* monster/hero tries to hide under something at the current location */
hideunder(mtmp)
struct monst *mtmp;
{
- struct trap *t;
- boolean undetected = FALSE,
- is_u = (mtmp == &youmonst);
- xchar x = is_u ? u.ux : mtmp->mx,
- y = is_u ? u.uy : mtmp->my;
-
- if (mtmp == u.ustuck) {
- ; /* can't hide if holding you or held by you */
- } else if (is_u ? (u.utrap && u.utraptype != TT_PIT) :
- (mtmp->mtrapped && (t = t_at(x, y)) != 0 &&
- !(t->ttyp == PIT || t->ttyp == SPIKED_PIT))) {
- ; /* can't hide while stuck in a non-pit trap */
- } else if (mtmp->data->mlet == S_EEL) {
- undetected = (is_pool(x, y) && !Is_waterlevel(&u.uz));
- } else if (hides_under(mtmp->data) && OBJ_AT(x, y)) {
- struct obj *otmp = level.objects[x][y];
-
- /* most monsters won't hide under cockatrice corpse */
- if (otmp->nexthere || otmp->otyp != CORPSE ||
- (mtmp == &youmonst ? Stone_resistance : resists_ston(mtmp)) ||
- !touch_petrifies(&mons[otmp->corpsenm]))
- undetected = TRUE;
- }
-
- if (is_u) u.uundetected = undetected;
- else mtmp->mundetected = undetected;
- return undetected;
+ struct trap *t;
+ boolean undetected = FALSE,
+ is_u = (mtmp == &youmonst);
+ xchar x = is_u ? u.ux : mtmp->mx,
+ y = is_u ? u.uy : mtmp->my;
+
+ if (mtmp == u.ustuck) {
+ ; /* can't hide if holding you or held by you */
+ } else if (is_u ? (u.utrap && u.utraptype != TT_PIT) :
+ (mtmp->mtrapped && (t = t_at(x, y)) != 0 &&
+ !(t->ttyp == PIT || t->ttyp == SPIKED_PIT))) {
+ ; /* can't hide while stuck in a non-pit trap */
+ } else if (mtmp->data->mlet == S_EEL) {
+ undetected = (is_pool(x, y) && !Is_waterlevel(&u.uz));
+ } else if (hides_under(mtmp->data) && OBJ_AT(x, y)) {
+ struct obj *otmp = level.objects[x][y];
+
+ /* most monsters won't hide under cockatrice corpse */
+ if (otmp->nexthere || otmp->otyp != CORPSE ||
+ (mtmp == &youmonst ? Stone_resistance : resists_ston(mtmp)) ||
+ !touch_petrifies(&mons[otmp->corpsenm]))
+ undetected = TRUE;
+ }
+
+ if (is_u) u.uundetected = undetected;
+ else mtmp->mundetected = undetected;
+ return undetected;
}
/* called when returning to a previously visited level */
boolean hider_under = hides_under(mon->data) || mon->data->mlet == S_EEL;
if ((is_hider(mon->data) || hider_under) &&
- !(mon->mundetected || mon->m_ap_type)) {
- xchar x = mon->mx, y = mon->my;
- char save_viz = viz_array[y][x];
-
- /* override vision, forcing hero to be unable to see monster's spot */
- viz_array[y][x] &= ~(IN_SIGHT | COULD_SEE);
- if (is_hider(mon->data)) (void)restrap(mon);
- /* try again if mimic missed its 1/3 chance to hide */
- if (mon->data->mlet == S_MIMIC && !mon->m_ap_type) (void)restrap(mon);
- if (hider_under) (void)hideunder(mon);
- viz_array[y][x] = save_viz;
+ !(mon->mundetected || mon->m_ap_type)) {
+ xchar x = mon->mx, y = mon->my;
+ char save_viz = viz_array[y][x];
+
+ /* override vision, forcing hero to be unable to see monster's spot */
+ viz_array[y][x] &= ~(IN_SIGHT | COULD_SEE);
+ if (is_hider(mon->data)) (void)restrap(mon);
+ /* try again if mimic missed its 1/3 chance to hide */
+ if (mon->data->mlet == S_MIMIC && !mon->m_ap_type) (void)restrap(mon);
+ if (hider_under) (void)hideunder(mon);
+ viz_array[y][x] = save_viz;
}
}
mon_animal_list(construct)
boolean construct;
{
- if (construct) {
- short animal_temp[SPECIAL_PM];
- int i, n;
+ if (construct) {
+ short animal_temp[SPECIAL_PM];
+ int i, n;
- /* if (animal_list) impossible("animal_list already exists"); */
+ /* if (animal_list) impossible("animal_list already exists"); */
- for (n = 0, i = LOW_PM; i < SPECIAL_PM; i++)
- if (is_animal(&mons[i])) animal_temp[n++] = i;
- /* if (n == 0) animal_temp[n++] = NON_PM; */
+ for (n = 0, i = LOW_PM; i < SPECIAL_PM; i++)
+ if (is_animal(&mons[i])) animal_temp[n++] = i;
+ /* if (n == 0) animal_temp[n++] = NON_PM; */
- animal_list = (short *)alloc(n * sizeof *animal_list);
- (void) memcpy((genericptr_t)animal_list,
- (genericptr_t)animal_temp,
- n * sizeof *animal_list);
- animal_list_count = n;
- } else { /* release */
- if (animal_list) free((genericptr_t)animal_list), animal_list = 0;
- animal_list_count = 0;
- }
+ animal_list = (short *)alloc(n * sizeof *animal_list);
+ (void) memcpy((genericptr_t)animal_list,
+ (genericptr_t)animal_temp,
+ n * sizeof *animal_list);
+ animal_list_count = n;
+ } else { /* release */
+ if (animal_list) free((genericptr_t)animal_list), animal_list = 0;
+ animal_list_count = 0;
+ }
}
STATIC_OVL int
pick_animal()
{
- if (!animal_list) mon_animal_list(TRUE);
+ if (!animal_list) mon_animal_list(TRUE);
- return animal_list[rn2(animal_list_count)];
+ return animal_list[rn2(animal_list_count)];
}
void
struct monst *mon;
int shiftflags;
{
- struct permonst *ptr;
- unsigned was_female = mon->female;
- boolean msg = FALSE;
+ struct permonst *ptr;
+ unsigned was_female = mon->female;
+ boolean msg = FALSE;
- if ((shiftflags & SHIFT_MSG) ||
- ((shiftflags & SHIFT_SEENMSG) && sensemon(mon))) msg = TRUE;
+ if ((shiftflags & SHIFT_MSG) ||
+ ((shiftflags & SHIFT_SEENMSG) && sensemon(mon))) msg = TRUE;
- if (is_vampshifter(mon)) {
- /* The vampire has to be in good health (mhp) to maintain
- * its shifted form.
+ if (is_vampshifter(mon)) {
+ /* The vampire has to be in good health (mhp) to maintain
+ * its shifted form.
*
- * If we're shifted and getting low on hp, maybe shift back.
- * If we're not already shifted and in good health, maybe shift.
- */
- if ((mon->mhp <= mon->mhpmax / 6) &&
- rn2(4) && (mon->cham >= LOW_PM))
- (void) newcham(mon, &mons[mon->cham], FALSE, msg);
- } else if (mon->data->mlet == S_VAMPIRE && mon->cham == NON_PM &&
- !rn2(6) && (mon->mhp > mon->mhpmax - ((mon->mhpmax / 10) + 1))) {
- (void) newcham(mon, (struct permonst *)0, FALSE, msg);
- }
- /* override the 10% chance for sex change */
- ptr = mon->data;
- if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
- mon->female = was_female;
+ * If we're shifted and getting low on hp, maybe shift back.
+ * If we're not already shifted and in good health, maybe shift.
+ */
+ if ((mon->mhp <= mon->mhpmax / 6) &&
+ rn2(4) && (mon->cham >= LOW_PM))
+ (void) newcham(mon, &mons[mon->cham], FALSE, msg);
+ } else if (mon->data->mlet == S_VAMPIRE && mon->cham == NON_PM &&
+ !rn2(6) && (mon->mhp > mon->mhpmax - ((mon->mhpmax / 10) + 1))) {
+ (void) newcham(mon, (struct permonst *)0, FALSE, msg);
+ }
+ /* override the 10% chance for sex change */
+ ptr = mon->data;
+ if (!is_male(ptr) && !is_female(ptr) && !is_neuter(ptr))
+ mon->female = was_female;
}
STATIC_OVL int
pickvampshape(mon)
struct monst *mon;
{
- int mndx = mon->cham;
-
- switch (mndx) {
- case PM_VLAD_THE_IMPALER:
- /* ensure Vlad can keep carrying the Candelabrum */
- if (mon_has_special(mon)) break; /* leave mndx as is */
- /*FALLTHRU*/
- case PM_VAMPIRE_LORD: /* vampire lord or Vlad can become wolf */
- if (!rn2(10)) {
- mndx = PM_WOLF;
- break;
- }
- /*FALLTHRU*/
- case PM_VAMPIRE: /* any vampire can become fog or bat */
- mndx = !rn2(4) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT;
- break;
- }
- return mndx;
+ int mndx = mon->cham;
+
+ switch (mndx) {
+ case PM_VLAD_THE_IMPALER:
+ /* ensure Vlad can keep carrying the Candelabrum */
+ if (mon_has_special(mon)) break; /* leave mndx as is */
+ /*FALLTHRU*/
+ case PM_VAMPIRE_LORD: /* vampire lord or Vlad can become wolf */
+ if (!rn2(10)) {
+ mndx = PM_WOLF;
+ break;
+ }
+ /*FALLTHRU*/
+ case PM_VAMPIRE: /* any vampire can become fog or bat */
+ mndx = !rn2(4) ? PM_FOG_CLOUD : PM_VAMPIRE_BAT;
+ break;
+ }
+ return mndx;
}
/* nonshapechangers who warrant special polymorph handling */
isspecmon(mon)
struct monst *mon;
{
- return (mon->isshk || mon->ispriest || mon->isgd ||
- mon->m_id == quest_status.leader_m_id);
+ return (mon->isshk || mon->ispriest || mon->isgd ||
+ mon->m_id == quest_status.leader_m_id);
}
/* restrict certain special monsters (shopkeepers, aligned priests,
struct monst *mon;
int mndx;
{
- if (mndx == NON_PM) return TRUE; /* caller wants random */
+ if (mndx == NON_PM) return TRUE; /* caller wants random */
- if (!accept_newcham_form(mndx)) return FALSE; /* geno'd or !polyok */
+ if (!accept_newcham_form(mndx)) return FALSE; /* geno'd or !polyok */
- if (isspecmon(mon)) {
- struct permonst *ptr = &mons[mndx];
+ if (isspecmon(mon)) {
+ struct permonst *ptr = &mons[mndx];
- /* reject notake because object manipulation is expected
- and nohead because speech capability is expected */
- if (notake(ptr) || !has_head(ptr)) return FALSE;
- /* [should we check ptr->msound here too?] */
- }
- return TRUE; /* potential new form is ok */
+ /* reject notake because object manipulation is expected
+ and nohead because speech capability is expected */
+ if (notake(ptr) || !has_head(ptr)) return FALSE;
+ /* [should we check ptr->msound here too?] */
+ }
+ return TRUE; /* potential new form is ok */
}
/* prevent wizard mode user from specifying invalid vampshifter shape */
struct monst *mon;
int *mndx_p, monclass;
{
- /* simplify caller's usage */
- if (!is_vampshifter(mon)) return validspecmon(mon, *mndx_p);
-
- if (*mndx_p == PM_VAMPIRE || *mndx_p == PM_VAMPIRE_LORD ||
- *mndx_p == PM_VLAD_THE_IMPALER) {
- /* player picked some type of vampire; use mon's self */
- *mndx_p = mon->cham;
- return TRUE;
- }
- if (mon->cham == PM_VLAD_THE_IMPALER && mon_has_special(mon)) {
- /* Vlad with Candelabrum; override choice, then accept it */
- *mndx_p = PM_VLAD_THE_IMPALER;
- return TRUE;
- }
- /* basic vampires can't become wolves; any can become fog or bat */
- if (*mndx_p == PM_WOLF) return (mon->cham != PM_VAMPIRE);
- if (*mndx_p == PM_FOG_CLOUD || *mndx_p == PM_VAMPIRE_BAT) return TRUE;
-
- /* if we get here, specific type was no good; try by class */
- switch (monclass) {
- case S_VAMPIRE: *mndx_p = mon->cham; break;
- case S_BAT: *mndx_p = PM_VAMPIRE_BAT; break;
- case S_VORTEX: *mndx_p = PM_FOG_CLOUD; break;
- case S_DOG: if (mon->cham != PM_VAMPIRE) {
- *mndx_p = PM_WOLF;
- break;
- }
- /*FALLTHRU*/
- default: *mndx_p = NON_PM; break;
- }
- return (*mndx_p != NON_PM);
+ /* simplify caller's usage */
+ if (!is_vampshifter(mon)) return validspecmon(mon, *mndx_p);
+
+ if (*mndx_p == PM_VAMPIRE || *mndx_p == PM_VAMPIRE_LORD ||
+ *mndx_p == PM_VLAD_THE_IMPALER) {
+ /* player picked some type of vampire; use mon's self */
+ *mndx_p = mon->cham;
+ return TRUE;
+ }
+ if (mon->cham == PM_VLAD_THE_IMPALER && mon_has_special(mon)) {
+ /* Vlad with Candelabrum; override choice, then accept it */
+ *mndx_p = PM_VLAD_THE_IMPALER;
+ return TRUE;
+ }
+ /* basic vampires can't become wolves; any can become fog or bat */
+ if (*mndx_p == PM_WOLF) return (mon->cham != PM_VAMPIRE);
+ if (*mndx_p == PM_FOG_CLOUD || *mndx_p == PM_VAMPIRE_BAT) return TRUE;
+
+ /* if we get here, specific type was no good; try by class */
+ switch (monclass) {
+ case S_VAMPIRE: *mndx_p = mon->cham; break;
+ case S_BAT: *mndx_p = PM_VAMPIRE_BAT; break;
+ case S_VORTEX: *mndx_p = PM_FOG_CLOUD; break;
+ case S_DOG: if (mon->cham != PM_VAMPIRE) {
+ *mndx_p = PM_WOLF;
+ break;
+ }
+ /*FALLTHRU*/
+ default: *mndx_p = NON_PM; break;
+ }
+ return (*mndx_p != NON_PM);
}
int
select_newcham_form(mon)
struct monst *mon;
{
- int mndx = NON_PM, tryct;
-
- switch (mon->cham) {
- case PM_SANDESTIN:
- if (rn2(7)) mndx = pick_nasty();
- break;
- case PM_DOPPELGANGER:
- if (!rn2(7)) {
- mndx = pick_nasty();
- } else if (rn2(3)) { /* role monsters */
- mndx = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1,
- PM_ARCHEOLOGIST);
- } else if (!rn2(3)) { /* quest guardians */
- mndx = rn1(PM_APPRENTICE - PM_STUDENT + 1,
- PM_STUDENT);
- /* avoid own role's guardian */
- if (mndx == urole.guardnum) mndx = NON_PM;
- } else { /* general humanoids */
- tryct = 5;
- do {
- mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
- if (humanoid(&mons[mndx]) && polyok(&mons[mndx])) break;
- } while (--tryct > 0);
- if (!tryct) mndx = NON_PM;
- }
- break;
- case PM_CHAMELEON:
- if (!rn2(3)) mndx = pick_animal();
- break;
- case PM_VLAD_THE_IMPALER:
- case PM_VAMPIRE_LORD:
- case PM_VAMPIRE:
- mndx = pickvampshape(mon);
- break;
- case NON_PM: /* ordinary */
- {
- struct obj *m_armr = which_armor(mon, W_ARM);
-
- if (m_armr && Is_dragon_scales(m_armr))
- mndx = (int)(Dragon_scales_to_pm(m_armr) - mons);
- else if (m_armr && Is_dragon_mail(m_armr))
- mndx = (int)(Dragon_mail_to_pm(m_armr) - mons);
- }
- break;
- }
- /* for debugging: allow control of polymorphed monster */
- if (wizard && iflags.mon_polycontrol) {
- char pprompt[BUFSZ], buf[BUFSZ];
- int monclass;
-
- Sprintf(pprompt,
- "Change %s @ <%d,%d> into what kind of monster?",
- noit_mon_nam(mon), (int)mon->mx, (int)mon->my);
- tryct = 5;
- do {
- monclass = 0;
- getlin(pprompt, buf);
- mungspaces(buf);
- /* for ESC, take form selected above (might be NON_PM) */
- if (*buf == '\033') break;
- /* for "*", use NON_PM to pick an arbitrary shape below */
- if (!strcmp(buf, "*") || !strcmp(buf, "random")) {
- mndx = NON_PM;
- break;
- }
- mndx = name_to_mon(buf);
- if (mndx == NON_PM) {
- /* didn't get a type, so check whether it's a class
- (single letter or text match with def_monsyms[]) */
- monclass = name_to_monclass(buf, &mndx);
- if (monclass && mndx == NON_PM)
- mndx = mkclass_poly(monclass);
- }
- if (mndx >= LOW_PM) {
- /* got a specific type of monster; use it if we can */
- if (validvamp(mon, &mndx, monclass)) break;
- /* can't; revert to random in case we exhaust tryct */
- mndx = NON_PM;
- }
-
- pline("It can't become that.");
- } while (--tryct > 0);
- if (!tryct) pline1(thats_enough_tries);
- if (is_vampshifter(mon) && !validvamp(mon, &mndx, monclass))
- mndx = pickvampshape(mon); /* don't resort to arbitrary */
- }
-
- /* if no form was specified above, pick one at random now */
- if (mndx == NON_PM) {
- tryct = 50;
- do {
- mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
- } while (--tryct > 0 && !validspecmon(mon, mndx));
- }
- return mndx;
+ int mndx = NON_PM, tryct;
+
+ switch (mon->cham) {
+ case PM_SANDESTIN:
+ if (rn2(7)) mndx = pick_nasty();
+ break;
+ case PM_DOPPELGANGER:
+ if (!rn2(7)) {
+ mndx = pick_nasty();
+ } else if (rn2(3)) { /* role monsters */
+ mndx = rn1(PM_WIZARD - PM_ARCHEOLOGIST + 1,
+ PM_ARCHEOLOGIST);
+ } else if (!rn2(3)) { /* quest guardians */
+ mndx = rn1(PM_APPRENTICE - PM_STUDENT + 1,
+ PM_STUDENT);
+ /* avoid own role's guardian */
+ if (mndx == urole.guardnum) mndx = NON_PM;
+ } else { /* general humanoids */
+ tryct = 5;
+ do {
+ mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
+ if (humanoid(&mons[mndx]) && polyok(&mons[mndx])) break;
+ } while (--tryct > 0);
+ if (!tryct) mndx = NON_PM;
+ }
+ break;
+ case PM_CHAMELEON:
+ if (!rn2(3)) mndx = pick_animal();
+ break;
+ case PM_VLAD_THE_IMPALER:
+ case PM_VAMPIRE_LORD:
+ case PM_VAMPIRE:
+ mndx = pickvampshape(mon);
+ break;
+ case NON_PM: /* ordinary */
+ {
+ struct obj *m_armr = which_armor(mon, W_ARM);
+
+ if (m_armr && Is_dragon_scales(m_armr))
+ mndx = (int)(Dragon_scales_to_pm(m_armr) - mons);
+ else if (m_armr && Is_dragon_mail(m_armr))
+ mndx = (int)(Dragon_mail_to_pm(m_armr) - mons);
+ }
+ break;
+ }
+ /* for debugging: allow control of polymorphed monster */
+ if (wizard && iflags.mon_polycontrol) {
+ char pprompt[BUFSZ], buf[BUFSZ];
+ int monclass;
+
+ Sprintf(pprompt,
+ "Change %s @ <%d,%d> into what kind of monster?",
+ noit_mon_nam(mon), (int)mon->mx, (int)mon->my);
+ tryct = 5;
+ do {
+ monclass = 0;
+ getlin(pprompt, buf);
+ mungspaces(buf);
+ /* for ESC, take form selected above (might be NON_PM) */
+ if (*buf == '\033') break;
+ /* for "*", use NON_PM to pick an arbitrary shape below */
+ if (!strcmp(buf, "*") || !strcmp(buf, "random")) {
+ mndx = NON_PM;
+ break;
+ }
+ mndx = name_to_mon(buf);
+ if (mndx == NON_PM) {
+ /* didn't get a type, so check whether it's a class
+ (single letter or text match with def_monsyms[]) */
+ monclass = name_to_monclass(buf, &mndx);
+ if (monclass && mndx == NON_PM)
+ mndx = mkclass_poly(monclass);
+ }
+ if (mndx >= LOW_PM) {
+ /* got a specific type of monster; use it if we can */
+ if (validvamp(mon, &mndx, monclass)) break;
+ /* can't; revert to random in case we exhaust tryct */
+ mndx = NON_PM;
+ }
+
+ pline("It can't become that.");
+ } while (--tryct > 0);
+ if (!tryct) pline1(thats_enough_tries);
+ if (is_vampshifter(mon) && !validvamp(mon, &mndx, monclass))
+ mndx = pickvampshape(mon); /* don't resort to arbitrary */
+ }
+
+ /* if no form was specified above, pick one at random now */
+ if (mndx == NON_PM) {
+ tryct = 50;
+ do {
+ mndx = rn1(SPECIAL_PM - LOW_PM, LOW_PM);
+ } while (--tryct > 0 && !validspecmon(mon, mndx));
+ }
+ return mndx;
}
/* this used to be inline within newcham() but monpolycontrol needs it too */
accept_newcham_form(mndx)
int mndx;
{
- struct permonst *mdat;
+ struct permonst *mdat;
- if (mndx == NON_PM) return 0;
- mdat = &mons[mndx];
- if ((mvitals[mndx].mvflags & G_GENOD) != 0) return 0;
- if (is_placeholder(mdat)) return 0;
- /* select_newcham_form() might deliberately pick a player
- character type (random selection never does) which
- polyok() rejects, so we need a special case here */
- if (is_mplayer(mdat)) return mdat;
- /* polyok() rules out M2_PNAME, M2_WERE, and all humans except Kops */
- return polyok(mdat) ? mdat : 0;
+ if (mndx == NON_PM) return 0;
+ mdat = &mons[mndx];
+ if ((mvitals[mndx].mvflags & G_GENOD) != 0) return 0;
+ if (is_placeholder(mdat)) return 0;
+ /* select_newcham_form() might deliberately pick a player
+ character type (random selection never does) which
+ polyok() rejects, so we need a special case here */
+ if (is_mplayer(mdat)) return mdat;
+ /* polyok() rules out M2_PNAME, M2_WERE, and all humans except Kops */
+ return polyok(mdat) ? mdat : 0;
}
/* make a chameleon take on another shape, or a polymorph target
boolean polyspot; /* change is the result of wand or spell of polymorph */
boolean msg; /* "The oldmon turns into a newmon!" */
{
- int hpn, hpd;
- int mndx, tryct;
- struct permonst *olddata = mtmp->data;
- char oldname[BUFSZ], newname[BUFSZ];
-
- /* Riders are immune to polymorph and green slime */
- if (is_rider(mtmp->data)) return 0;
-
- if (msg) {
- /* like Monnam() but never mention saddle */
- Strcpy(oldname, x_monnam(mtmp, ARTICLE_THE, (char *)0,
- SUPPRESS_SADDLE, FALSE));
- oldname[0] = highc(oldname[0]);
- }
-
- /* mdat = 0 -> caller wants a random monster shape */
- if (mdat == 0) {
- /* select_newcham_form() loops when resorting to random but
- it doesn't always pick that so we still retry here too */
- tryct = 20;
- do {
- mndx = select_newcham_form(mtmp);
- mdat = accept_newcham_form(mndx);
- if (mdat) break;
- } while (--tryct > 0);
- if (!tryct) return 0;
- } else if (mvitals[monsndx(mdat)].mvflags & G_GENOD)
- return(0); /* passed in mdat is genocided */
-
- if(is_male(mdat)) {
- if(mtmp->female) mtmp->female = FALSE;
- } else if (is_female(mdat)) {
- if(!mtmp->female) mtmp->female = TRUE;
- } else if (!is_neuter(mdat)) {
- if(!rn2(10)) mtmp->female = !mtmp->female;
- }
-
- if (In_endgame(&u.uz) && is_mplayer(olddata) && has_mname(mtmp)) {
- /* mplayers start out as "Foo the Bar", but some of the
- * titles are inappropriate when polymorphed, particularly
- * into the opposite sex. players don't use ranks when
- * polymorphed, so dropping the rank for mplayers seems
- * reasonable.
- */
- char *p = index(MNAME(mtmp), ' ');
- if (p) {
- *p = '\0';
- }
- }
-
- if(mdat == mtmp->data) return(0); /* still the same monster */
-
- if(mtmp->wormno) { /* throw tail away */
- wormgone(mtmp);
- place_monster(mtmp, mtmp->mx, mtmp->my);
- }
- if (mtmp->m_ap_type && mdat->mlet != S_MIMIC)
- seemimic(mtmp); /* revert to normal monster */
-
- /* (this code used to try to adjust the monster's health based on
- a normal one of its type but there are too many special cases
- which need to handled in order to do that correctly, so just
- give the new form the same proportion of HP as its old one had) */
- hpn = mtmp->mhp;
- hpd = mtmp->mhpmax;
- /* set level and hit points */
- newmonhp(mtmp, monsndx(mdat));
- /* new hp: same fraction of max as before */
+ int hpn, hpd;
+ int mndx, tryct;
+ struct permonst *olddata = mtmp->data;
+ char oldname[BUFSZ], newname[BUFSZ];
+
+ /* Riders are immune to polymorph and green slime */
+ if (is_rider(mtmp->data)) return 0;
+
+ if (msg) {
+ /* like Monnam() but never mention saddle */
+ Strcpy(oldname, x_monnam(mtmp, ARTICLE_THE, (char *)0,
+ SUPPRESS_SADDLE, FALSE));
+ oldname[0] = highc(oldname[0]);
+ }
+
+ /* mdat = 0 -> caller wants a random monster shape */
+ if (mdat == 0) {
+ /* select_newcham_form() loops when resorting to random but
+ it doesn't always pick that so we still retry here too */
+ tryct = 20;
+ do {
+ mndx = select_newcham_form(mtmp);
+ mdat = accept_newcham_form(mndx);
+ if (mdat) break;
+ } while (--tryct > 0);
+ if (!tryct) return 0;
+ } else if (mvitals[monsndx(mdat)].mvflags & G_GENOD)
+ return(0); /* passed in mdat is genocided */
+
+ if(is_male(mdat)) {
+ if(mtmp->female) mtmp->female = FALSE;
+ } else if (is_female(mdat)) {
+ if(!mtmp->female) mtmp->female = TRUE;
+ } else if (!is_neuter(mdat)) {
+ if(!rn2(10)) mtmp->female = !mtmp->female;
+ }
+
+ if (In_endgame(&u.uz) && is_mplayer(olddata) && has_mname(mtmp)) {
+ /* mplayers start out as "Foo the Bar", but some of the
+ * titles are inappropriate when polymorphed, particularly
+ * into the opposite sex. players don't use ranks when
+ * polymorphed, so dropping the rank for mplayers seems
+ * reasonable.
+ */
+ char *p = index(MNAME(mtmp), ' ');
+ if (p) {
+ *p = '\0';
+ }
+ }
+
+ if(mdat == mtmp->data) return(0); /* still the same monster */
+
+ if(mtmp->wormno) { /* throw tail away */
+ wormgone(mtmp);
+ place_monster(mtmp, mtmp->mx, mtmp->my);
+ }
+ if (mtmp->m_ap_type && mdat->mlet != S_MIMIC)
+ seemimic(mtmp); /* revert to normal monster */
+
+ /* (this code used to try to adjust the monster's health based on
+ a normal one of its type but there are too many special cases
+ which need to handled in order to do that correctly, so just
+ give the new form the same proportion of HP as its old one had) */
+ hpn = mtmp->mhp;
+ hpd = mtmp->mhpmax;
+ /* set level and hit points */
+ newmonhp(mtmp, monsndx(mdat));
+ /* new hp: same fraction of max as before */
#ifndef LINT
- mtmp->mhp = (int)(((long)hpn * (long)mtmp->mhp) / (long)hpd);
+ mtmp->mhp = (int)(((long)hpn * (long)mtmp->mhp) / (long)hpd);
#endif
- /* sanity check (potentional overflow) */
- if (mtmp->mhp < 0 || mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
- /* unlikely but not impossible; a 1HD creature with 1HP that changes
- into a 0HD creature will require this statement */
- if (!mtmp->mhp) mtmp->mhp = 1;
-
- /* take on the new form... */
- set_mon_data(mtmp, mdat, 0);
-
- if (emits_light(olddata) != emits_light(mtmp->data)) {
- /* used to give light, now doesn't, or vice versa,
- or light's range has changed */
- if (emits_light(olddata))
- del_light_source(LS_MONSTER, monst_to_any(mtmp));
- if (emits_light(mtmp->data))
- new_light_source(mtmp->mx, mtmp->my, emits_light(mtmp->data),
- LS_MONSTER, monst_to_any(mtmp));
- }
- if (!mtmp->perminvis || pm_invisible(olddata))
- mtmp->perminvis = pm_invisible(mdat);
- mtmp->minvis = mtmp->invis_blkd ? 0 : mtmp->perminvis;
- if (mtmp->mundetected) (void) hideunder(mtmp);
- if (u.ustuck == mtmp) {
- if(u.uswallow) {
- if(!attacktype(mdat,AT_ENGL)) {
- /* Does mdat care? */
- if (!noncorporeal(mdat) && !amorphous(mdat) &&
- !is_whirly(mdat) &&
- (mdat != &mons[PM_YELLOW_LIGHT])) {
- You("break out of %s%s!", mon_nam(mtmp),
- (is_animal(mdat)?
- "'s stomach" : ""));
- mtmp->mhp = 1; /* almost dead */
- }
- expels(mtmp, olddata, FALSE);
- } else {
- /* update swallow glyphs for new monster */
- swallowed(0);
- }
- } else if (!sticks(mdat) && !sticks(youmonst.data))
- unstuck(mtmp);
- }
+ /* sanity check (potentional overflow) */
+ if (mtmp->mhp < 0 || mtmp->mhp > mtmp->mhpmax) mtmp->mhp = mtmp->mhpmax;
+ /* unlikely but not impossible; a 1HD creature with 1HP that changes
+ into a 0HD creature will require this statement */
+ if (!mtmp->mhp) mtmp->mhp = 1;
+
+ /* take on the new form... */
+ set_mon_data(mtmp, mdat, 0);
+
+ if (emits_light(olddata) != emits_light(mtmp->data)) {
+ /* used to give light, now doesn't, or vice versa,
+ or light's range has changed */
+ if (emits_light(olddata))
+ del_light_source(LS_MONSTER, monst_to_any(mtmp));
+ if (emits_light(mtmp->data))
+ new_light_source(mtmp->mx, mtmp->my, emits_light(mtmp->data),
+ LS_MONSTER, monst_to_any(mtmp));
+ }
+ if (!mtmp->perminvis || pm_invisible(olddata))
+ mtmp->perminvis = pm_invisible(mdat);
+ mtmp->minvis = mtmp->invis_blkd ? 0 : mtmp->perminvis;
+ if (mtmp->mundetected) (void) hideunder(mtmp);
+ if (u.ustuck == mtmp) {
+ if(u.uswallow) {
+ if(!attacktype(mdat,AT_ENGL)) {
+ /* Does mdat care? */
+ if (!noncorporeal(mdat) && !amorphous(mdat) &&
+ !is_whirly(mdat) &&
+ (mdat != &mons[PM_YELLOW_LIGHT])) {
+ You("break out of %s%s!", mon_nam(mtmp),
+ (is_animal(mdat)?
+ "'s stomach" : ""));
+ mtmp->mhp = 1; /* almost dead */
+ }
+ expels(mtmp, olddata, FALSE);
+ } else {
+ /* update swallow glyphs for new monster */
+ swallowed(0);
+ }
+ } else if (!sticks(mdat) && !sticks(youmonst.data))
+ unstuck(mtmp);
+ }
#ifndef DCC30_BUG
- if (mdat == &mons[PM_LONG_WORM] && (mtmp->wormno = get_wormno()) != 0) {
+ if (mdat == &mons[PM_LONG_WORM] && (mtmp->wormno = get_wormno()) != 0) {
#else
- /* DICE 3.0 doesn't like assigning and comparing mtmp->wormno in the
- * same expression.
- */
- if (mdat == &mons[PM_LONG_WORM] &&
- (mtmp->wormno = get_wormno(), mtmp->wormno != 0)) {
+ /* DICE 3.0 doesn't like assigning and comparing mtmp->wormno in the
+ * same expression.
+ */
+ if (mdat == &mons[PM_LONG_WORM] &&
+ (mtmp->wormno = get_wormno(), mtmp->wormno != 0)) {
#endif
- /* we can now create worms with tails - 11/91 */
- initworm(mtmp, rn2(5));
- if (count_wsegs(mtmp))
- place_worm_tail_randomly(mtmp, mtmp->mx, mtmp->my);
- }
-
- newsym(mtmp->mx,mtmp->my);
-
- if (msg) {
- char *save_mname = 0;
-
- if (has_mname(mtmp)) {
- save_mname = MNAME(mtmp);
- MNAME(mtmp) = (char *)0;
- }
- Strcpy(newname,
- (mdat == &mons[PM_GREEN_SLIME]) ? "slime" :
- x_monnam(mtmp, ARTICLE_A, (char *)0,SUPPRESS_SADDLE, FALSE));
- if (!strcmpi(oldname,"it") && !strcmpi(newname,"it"))
- (void) usmellmon(mdat);
- else
- pline("%s turns into %s!", oldname, newname);
- if (save_mname) MNAME(mtmp) = save_mname;
- }
-
- possibly_unwield(mtmp, polyspot); /* might lose use of weapon */
- mon_break_armor(mtmp, polyspot);
- if (!(mtmp->misc_worn_check & W_ARMG))
- mselftouch(mtmp, "No longer petrify-resistant, ",
- !context.mon_moving);
- m_dowear(mtmp, FALSE);
-
- /* This ought to re-test can_carry() on each item in the inventory
- * rather than just checking ex-giants & boulders, but that'd be
- * pretty expensive to perform. If implemented, then perhaps
- * minvent should be sorted in order to drop heaviest items first.
- */
- /* former giants can't continue carrying boulders */
- if (mtmp->minvent && !throws_rocks(mdat)) {
- register struct obj *otmp, *otmp2;
-
- for (otmp = mtmp->minvent; otmp; otmp = otmp2) {
- otmp2 = otmp->nobj;
- if (otmp->otyp == BOULDER) {
- /* this keeps otmp from being polymorphed in the
- same zap that the monster that held it is polymorphed */
- if (polyspot) bypass_obj(otmp);
- obj_extract_self(otmp);
- /* probably ought to give some "drop" message here */
- if (flooreffects(otmp, mtmp->mx, mtmp->my, "")) continue;
- place_object(otmp, mtmp->mx, mtmp->my);
- }
- }
- }
-
- return(1);
+ /* we can now create worms with tails - 11/91 */
+ initworm(mtmp, rn2(5));
+ if (count_wsegs(mtmp))
+ place_worm_tail_randomly(mtmp, mtmp->mx, mtmp->my);
+ }
+
+ newsym(mtmp->mx,mtmp->my);
+
+ if (msg) {
+ char *save_mname = 0;
+
+ if (has_mname(mtmp)) {
+ save_mname = MNAME(mtmp);
+ MNAME(mtmp) = (char *)0;
+ }
+ Strcpy(newname,
+ (mdat == &mons[PM_GREEN_SLIME]) ? "slime" :
+ x_monnam(mtmp, ARTICLE_A, (char *)0,SUPPRESS_SADDLE, FALSE));
+ if (!strcmpi(oldname,"it") && !strcmpi(newname,"it"))
+ (void) usmellmon(mdat);
+ else
+ pline("%s turns into %s!", oldname, newname);
+ if (save_mname) MNAME(mtmp) = save_mname;
+ }
+
+ possibly_unwield(mtmp, polyspot); /* might lose use of weapon */
+ mon_break_armor(mtmp, polyspot);
+ if (!(mtmp->misc_worn_check & W_ARMG))
+ mselftouch(mtmp, "No longer petrify-resistant, ",
+ !context.mon_moving);
+ m_dowear(mtmp, FALSE);
+
+ /* This ought to re-test can_carry() on each item in the inventory
+ * rather than just checking ex-giants & boulders, but that'd be
+ * pretty expensive to perform. If implemented, then perhaps
+ * minvent should be sorted in order to drop heaviest items first.
+ */
+ /* former giants can't continue carrying boulders */
+ if (mtmp->minvent && !throws_rocks(mdat)) {
+ register struct obj *otmp, *otmp2;
+
+ for (otmp = mtmp->minvent; otmp; otmp = otmp2) {
+ otmp2 = otmp->nobj;
+ if (otmp->otyp == BOULDER) {
+ /* this keeps otmp from being polymorphed in the
+ same zap that the monster that held it is polymorphed */
+ if (polyspot) bypass_obj(otmp);
+ obj_extract_self(otmp);
+ /* probably ought to give some "drop" message here */
+ if (flooreffects(otmp, mtmp->mx, mtmp->my, "")) continue;
+ place_object(otmp, mtmp->mx, mtmp->my);
+ }
+ }
+ }
+
+ return(1);
}
/* sometimes an egg will be special */
* grow into queen bees. Ditto for [winged-]gargoyles.
*/
if (mnum == PM_KILLER_BEE || mnum == PM_GARGOYLE ||
- (lays_eggs(&mons[mnum]) && (BREEDER_EGG ||
- (mnum != PM_QUEEN_BEE && mnum != PM_WINGED_GARGOYLE))))
- return mnum;
+ (lays_eggs(&mons[mnum]) && (BREEDER_EGG ||
+ (mnum != PM_QUEEN_BEE && mnum != PM_WINGED_GARGOYLE))))
+ return mnum;
return NON_PM;
}
boolean force_ordinary;
{
if (force_ordinary || !BREEDER_EGG) {
- if (mnum == PM_QUEEN_BEE) mnum = PM_KILLER_BEE;
- else if (mnum == PM_WINGED_GARGOYLE) mnum = PM_GARGOYLE;
+ if (mnum == PM_QUEEN_BEE) mnum = PM_KILLER_BEE;
+ else if (mnum == PM_WINGED_GARGOYLE) mnum = PM_GARGOYLE;
}
return mnum;
}
int m_idx;
boolean egg;
{
- /*
- * For monsters with both baby and adult forms, genociding either
- * form kills all eggs of that monster. Monsters with more than
- * two forms (small->large->giant mimics) are more or less ignored;
- * fortunately, none of them have eggs. Species extinction due to
- * overpopulation does not kill eggs.
- */
- return (boolean)
- (m_idx >= LOW_PM &&
- ((mvitals[m_idx].mvflags & G_GENOD) != 0 ||
- (egg &&
- (mvitals[big_to_little(m_idx)].mvflags & G_GENOD) != 0)));
+ /*
+ * For monsters with both baby and adult forms, genociding either
+ * form kills all eggs of that monster. Monsters with more than
+ * two forms (small->large->giant mimics) are more or less ignored;
+ * fortunately, none of them have eggs. Species extinction due to
+ * overpopulation does not kill eggs.
+ */
+ return (boolean)
+ (m_idx >= LOW_PM &&
+ ((mvitals[m_idx].mvflags & G_GENOD) != 0 ||
+ (egg &&
+ (mvitals[big_to_little(m_idx)].mvflags & G_GENOD) != 0)));
}
/* kill off any eggs of genocided monsters */
kill_eggs(obj_list)
struct obj *obj_list;
{
- struct obj *otmp;
-
- for (otmp = obj_list; otmp; otmp = otmp->nobj)
- if (otmp->otyp == EGG) {
- if (dead_species(otmp->corpsenm, TRUE)) {
- /*
- * It seems we could also just catch this when
- * it attempted to hatch, so we wouldn't have to
- * search all of the objlists.. or stop all
- * hatch timers based on a corpsenm.
- */
- kill_egg(otmp);
- }
+ struct obj *otmp;
+
+ for (otmp = obj_list; otmp; otmp = otmp->nobj)
+ if (otmp->otyp == EGG) {
+ if (dead_species(otmp->corpsenm, TRUE)) {
+ /*
+ * It seems we could also just catch this when
+ * it attempted to hatch, so we wouldn't have to
+ * search all of the objlists.. or stop all
+ * hatch timers based on a corpsenm.
+ */
+ kill_egg(otmp);
+ }
#if 0 /* not used */
- } else if (otmp->otyp == TIN) {
- if (dead_species(otmp->corpsenm, FALSE))
- otmp->corpsenm = NON_PM; /* empty tin */
- } else if (otmp->otyp == CORPSE) {
- if (dead_species(otmp->corpsenm, FALSE))
- ; /* not yet implemented... */
+ } else if (otmp->otyp == TIN) {
+ if (dead_species(otmp->corpsenm, FALSE))
+ otmp->corpsenm = NON_PM; /* empty tin */
+ } else if (otmp->otyp == CORPSE) {
+ if (dead_species(otmp->corpsenm, FALSE))
+ ; /* not yet implemented... */
#endif
- } else if (Has_contents(otmp)) {
- kill_eggs(otmp->cobj);
- }
+ } else if (Has_contents(otmp)) {
+ kill_eggs(otmp->cobj);
+ }
}
/* kill all members of genocided species */
void
kill_genocided_monsters()
{
- struct monst *mtmp, *mtmp2;
- boolean kill_cham;
- int mndx;
-
- /*
- * Called during genocide, and again upon level change. The latter
- * catches up with any migrating monsters as they finally arrive at
- * their intended destinations, so possessions get deposited there.
- *
- * Chameleon handling:
- * 1) if chameleons have been genocided, destroy them
- * regardless of current form;
- * 2) otherwise, force every chameleon which is imitating
- * any genocided species to take on a new form.
- */
- for (mtmp = fmon; mtmp; mtmp = mtmp2) {
- mtmp2 = mtmp->nmon;
- if (DEADMONSTER(mtmp)) continue;
- mndx = monsndx(mtmp->data);
- kill_cham = (mtmp->cham >= LOW_PM &&
- (mvitals[mtmp->cham].mvflags & G_GENOD));
- if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham) {
- if (mtmp->cham >= LOW_PM && !kill_cham)
- (void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
- else
- mondead(mtmp);
- }
- if (mtmp->minvent) kill_eggs(mtmp->minvent);
- }
-
- kill_eggs(invent);
- kill_eggs(fobj);
- kill_eggs(migrating_objs);
- kill_eggs(level.buriedobjlist);
+ struct monst *mtmp, *mtmp2;
+ boolean kill_cham;
+ int mndx;
+
+ /*
+ * Called during genocide, and again upon level change. The latter
+ * catches up with any migrating monsters as they finally arrive at
+ * their intended destinations, so possessions get deposited there.
+ *
+ * Chameleon handling:
+ * 1) if chameleons have been genocided, destroy them
+ * regardless of current form;
+ * 2) otherwise, force every chameleon which is imitating
+ * any genocided species to take on a new form.
+ */
+ for (mtmp = fmon; mtmp; mtmp = mtmp2) {
+ mtmp2 = mtmp->nmon;
+ if (DEADMONSTER(mtmp)) continue;
+ mndx = monsndx(mtmp->data);
+ kill_cham = (mtmp->cham >= LOW_PM &&
+ (mvitals[mtmp->cham].mvflags & G_GENOD));
+ if ((mvitals[mndx].mvflags & G_GENOD) || kill_cham) {
+ if (mtmp->cham >= LOW_PM && !kill_cham)
+ (void) newcham(mtmp, (struct permonst *)0, FALSE, FALSE);
+ else
+ mondead(mtmp);
+ }
+ if (mtmp->minvent) kill_eggs(mtmp->minvent);
+ }
+
+ kill_eggs(invent);
+ kill_eggs(fobj);
+ kill_eggs(migrating_objs);
+ kill_eggs(level.buriedobjlist);
}
void
int heal = 0, slow = 0;
if (mon->data == &mons[PM_FLESH_GOLEM]) {
- if (damtype == AD_ELEC) heal = dam / 6;
- else if (damtype == AD_FIRE || damtype == AD_COLD) slow = 1;
+ if (damtype == AD_ELEC) heal = dam / 6;
+ else if (damtype == AD_FIRE || damtype == AD_COLD) slow = 1;
} else if (mon->data == &mons[PM_IRON_GOLEM]) {
- if (damtype == AD_ELEC) slow = 1;
- else if (damtype == AD_FIRE) heal = dam;
+ if (damtype == AD_ELEC) slow = 1;
+ else if (damtype == AD_FIRE) heal = dam;
} else {
- return;
+ return;
}
if (slow) {
- if (mon->mspeed != MSLOW)
- mon_adjust_speed(mon, -1, (struct obj *)0);
+ if (mon->mspeed != MSLOW)
+ mon_adjust_speed(mon, -1, (struct obj *)0);
}
if (heal) {
- if (mon->mhp < mon->mhpmax) {
- mon->mhp += dam;
- if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
- if (cansee(mon->mx, mon->my))
- pline("%s seems healthier.", Monnam(mon));
- }
+ if (mon->mhp < mon->mhpmax) {
+ mon->mhp += dam;
+ if (mon->mhp > mon->mhpmax) mon->mhp = mon->mhpmax;
+ if (cansee(mon->mx, mon->my))
+ pline("%s seems healthier.", Monnam(mon));
+ }
}
}
angry_guards(silent)
register boolean silent;
{
- register struct monst *mtmp;
- register int ct = 0, nct = 0, sct = 0, slct = 0;
-
- for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- if((mtmp->data == &mons[PM_WATCHMAN] ||
- mtmp->data == &mons[PM_WATCH_CAPTAIN])
- && mtmp->mpeaceful) {
- ct++;
- if(cansee(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
- if (distu(mtmp->mx, mtmp->my) == 2) nct++;
- else sct++;
- }
- if (mtmp->msleeping || mtmp->mfrozen) {
- slct++;
- mtmp->msleeping = mtmp->mfrozen = 0;
- }
- mtmp->mpeaceful = 0;
- }
- }
- if(ct) {
- if(!silent) { /* do we want pline msgs? */
- if(slct) pline_The("guard%s wake%s up!",
- slct > 1 ? "s" : "", slct == 1 ? "s" : "");
- if(nct || sct) {
- if(nct) pline_The("guard%s get%s angry!",
- nct == 1 ? "" : "s", nct == 1 ? "s" : "");
- else if(!Blind)
- You_see("%sangry guard%s approaching!",
- sct == 1 ? "an " : "", sct > 1 ? "s" : "");
- } else
- You_hear("the shrill sound of a guard's whistle.");
- }
- return(TRUE);
- }
- return(FALSE);
+ register struct monst *mtmp;
+ register int ct = 0, nct = 0, sct = 0, slct = 0;
+
+ for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ if((mtmp->data == &mons[PM_WATCHMAN] ||
+ mtmp->data == &mons[PM_WATCH_CAPTAIN])
+ && mtmp->mpeaceful) {
+ ct++;
+ if(cansee(mtmp->mx, mtmp->my) && mtmp->mcanmove) {
+ if (distu(mtmp->mx, mtmp->my) == 2) nct++;
+ else sct++;
+ }
+ if (mtmp->msleeping || mtmp->mfrozen) {
+ slct++;
+ mtmp->msleeping = mtmp->mfrozen = 0;
+ }
+ mtmp->mpeaceful = 0;
+ }
+ }
+ if(ct) {
+ if(!silent) { /* do we want pline msgs? */
+ if(slct) pline_The("guard%s wake%s up!",
+ slct > 1 ? "s" : "", slct == 1 ? "s" : "");
+ if(nct || sct) {
+ if(nct) pline_The("guard%s get%s angry!",
+ nct == 1 ? "" : "s", nct == 1 ? "s" : "");
+ else if(!Blind)
+ You_see("%sangry guard%s approaching!",
+ sct == 1 ? "an " : "", sct > 1 ? "s" : "");
+ } else
+ You_hear("the shrill sound of a guard's whistle.");
+ }
+ return(TRUE);
+ }
+ return(FALSE);
}
void
pacify_guards()
{
- register struct monst *mtmp;
+ register struct monst *mtmp;
- for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
- if (DEADMONSTER(mtmp)) continue;
- if (mtmp->data == &mons[PM_WATCHMAN] ||
- mtmp->data == &mons[PM_WATCH_CAPTAIN])
- mtmp->mpeaceful = 1;
- }
+ for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
+ if (DEADMONSTER(mtmp)) continue;
+ if (mtmp->data == &mons[PM_WATCHMAN] ||
+ mtmp->data == &mons[PM_WATCH_CAPTAIN])
+ mtmp->mpeaceful = 1;
+ }
}
void
struct monst *mtmp;
short otyp;
{
- short ap = mtmp->mappearance;
-
- switch(mtmp->m_ap_type) {
- case M_AP_NOTHING:
- case M_AP_FURNITURE:
- case M_AP_MONSTER:
- break;
- case M_AP_OBJECT:
- if (otyp == SPE_HEALING || otyp == SPE_EXTRA_HEALING) {
- pline("%s seems a more vivid %s than before.",
- The(simple_typename(ap)),
- c_obj_colors[objects[ap].oc_color]);
- }
- break;
- }
+ short ap = mtmp->mappearance;
+
+ switch(mtmp->m_ap_type) {
+ case M_AP_NOTHING:
+ case M_AP_FURNITURE:
+ case M_AP_MONSTER:
+ break;
+ case M_AP_OBJECT:
+ if (otyp == SPE_HEALING || otyp == SPE_EXTRA_HEALING) {
+ pline("%s seems a more vivid %s than before.",
+ The(simple_typename(ap)),
+ c_obj_colors[objects[ap].oc_color]);
+ }
+ break;
+ }
}
boolean
usmellmon(mdat)
struct permonst *mdat;
{
- int mndx;
- boolean nonspecific = FALSE;
- boolean msg_given = FALSE;
-
- if (mdat) {
- if (!olfaction(youmonst.data)) return FALSE;
- mndx = monsndx(mdat);
- switch (mndx) {
- case PM_ROTHE:
- case PM_MINOTAUR:
- You("notice a bovine smell.");
- msg_given = TRUE;
- break;
- case PM_CAVEMAN:
- case PM_CAVEWOMAN:
- case PM_BARBARIAN:
- case PM_NEANDERTHAL:
- You("smell body odor.");
- msg_given = TRUE;
- break;
+ int mndx;
+ boolean nonspecific = FALSE;
+ boolean msg_given = FALSE;
+
+ if (mdat) {
+ if (!olfaction(youmonst.data)) return FALSE;
+ mndx = monsndx(mdat);
+ switch (mndx) {
+ case PM_ROTHE:
+ case PM_MINOTAUR:
+ You("notice a bovine smell.");
+ msg_given = TRUE;
+ break;
+ case PM_CAVEMAN:
+ case PM_CAVEWOMAN:
+ case PM_BARBARIAN:
+ case PM_NEANDERTHAL:
+ You("smell body odor.");
+ msg_given = TRUE;
+ break;
/*
- case PM_PESTILENCE:
- case PM_FAMINE:
- case PM_DEATH:
- break;
+ case PM_PESTILENCE:
+ case PM_FAMINE:
+ case PM_DEATH:
+ break;
*/
- case PM_HORNED_DEVIL:
- case PM_BALROG:
- case PM_ASMODEUS:
- case PM_DISPATER:
- case PM_YEENOGHU:
- case PM_ORCUS:
- break;
- case PM_HUMAN_WEREJACKAL:
- case PM_HUMAN_WERERAT:
- case PM_HUMAN_WEREWOLF:
- case PM_WEREJACKAL:
- case PM_WERERAT:
- case PM_WEREWOLF:
- case PM_OWLBEAR:
- You("detect an odor reminiscent of an animal's den.");
- msg_given = TRUE;
- break;
+ case PM_HORNED_DEVIL:
+ case PM_BALROG:
+ case PM_ASMODEUS:
+ case PM_DISPATER:
+ case PM_YEENOGHU:
+ case PM_ORCUS:
+ break;
+ case PM_HUMAN_WEREJACKAL:
+ case PM_HUMAN_WERERAT:
+ case PM_HUMAN_WEREWOLF:
+ case PM_WEREJACKAL:
+ case PM_WERERAT:
+ case PM_WEREWOLF:
+ case PM_OWLBEAR:
+ You("detect an odor reminiscent of an animal's den.");
+ msg_given = TRUE;
+ break;
/*
- case PM_PURPLE_WORM:
- break;
+ case PM_PURPLE_WORM:
+ break;
*/
- case PM_STEAM_VORTEX:
- You("smell steam.");
- msg_given = TRUE;
- break;
- case PM_GREEN_SLIME:
- pline("%s stinks.", Something);
- msg_given = TRUE;
- break;
- case PM_VIOLET_FUNGUS:
- case PM_SHRIEKER:
- You("smell mushrooms.");
- msg_given = TRUE;
- break;
- /* These are here to avoid triggering the
- nonspecific treatment through the default case below*/
- case PM_WHITE_UNICORN:
- case PM_GRAY_UNICORN:
- case PM_BLACK_UNICORN:
- case PM_JELLYFISH:
- break;
- default:
- nonspecific = TRUE;
- break;
- }
-
- if (nonspecific) switch(mdat->mlet) {
- case S_DOG:
- You("notice a dog smell.");
- msg_given = TRUE;
- break;
- case S_DRAGON:
- You("smell a dragon!");
- msg_given = TRUE;
- break;
- case S_FUNGUS:
- pline("%s smells moldy.", Something);
- msg_given = TRUE;
- break;
- case S_UNICORN:
- You("detect a%s odor reminiscent of a stable.",
- (mndx == PM_PONY) ? "n" : " strong");
- msg_given = TRUE;
- break;
- case S_ZOMBIE:
- You("smell rotting flesh.");
- msg_given = TRUE;
- break;
- case S_EEL:
- You("smell fish.");
- msg_given = TRUE;
- break;
- case S_ORC:
- if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC)))
- You("notice an attractive smell.");
- else
- pline(
- "A foul stench makes you feel a little nauseated.");
- msg_given = TRUE;
- break;
- default:
- break;
- }
- }
- return (msg_given) ? TRUE : FALSE;
+ case PM_STEAM_VORTEX:
+ You("smell steam.");
+ msg_given = TRUE;
+ break;
+ case PM_GREEN_SLIME:
+ pline("%s stinks.", Something);
+ msg_given = TRUE;
+ break;
+ case PM_VIOLET_FUNGUS:
+ case PM_SHRIEKER:
+ You("smell mushrooms.");
+ msg_given = TRUE;
+ break;
+ /* These are here to avoid triggering the
+ nonspecific treatment through the default case below*/
+ case PM_WHITE_UNICORN:
+ case PM_GRAY_UNICORN:
+ case PM_BLACK_UNICORN:
+ case PM_JELLYFISH:
+ break;
+ default:
+ nonspecific = TRUE;
+ break;
+ }
+
+ if (nonspecific) switch(mdat->mlet) {
+ case S_DOG:
+ You("notice a dog smell.");
+ msg_given = TRUE;
+ break;
+ case S_DRAGON:
+ You("smell a dragon!");
+ msg_given = TRUE;
+ break;
+ case S_FUNGUS:
+ pline("%s smells moldy.", Something);
+ msg_given = TRUE;
+ break;
+ case S_UNICORN:
+ You("detect a%s odor reminiscent of a stable.",
+ (mndx == PM_PONY) ? "n" : " strong");
+ msg_given = TRUE;
+ break;
+ case S_ZOMBIE:
+ You("smell rotting flesh.");
+ msg_given = TRUE;
+ break;
+ case S_EEL:
+ You("smell fish.");
+ msg_given = TRUE;
+ break;
+ case S_ORC:
+ if (maybe_polyd(is_orc(youmonst.data), Race_if(PM_ORC)))
+ You("notice an attractive smell.");
+ else
+ pline(
+ "A foul stench makes you feel a little nauseated.");
+ msg_given = TRUE;
+ break;
+ default:
+ break;
+ }
+ }
+ return (msg_given) ? TRUE : FALSE;
}
/*mon.c*/
* Puddings
*/
MON("gray ooze", S_PUDDING,
- LVL(3, 1, 8, 0, 0), (G_GENO|2),
+ LVL(3, 1, 8, 0, 0), (G_GENO|G_NOCORPSE|2),
A(ATTK(AT_BITE, AD_RUST, 2, 8),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(500, 250, MS_SILENT, MZ_MEDIUM),
M1_MINDLESS|M1_OMNIVORE|M1_ACID,
M2_HOSTILE|M2_NEUTER, 0, CLR_GRAY),
MON("brown pudding", S_PUDDING,
- LVL(5, 3, 8, 0, 0), (G_GENO|1),
+ LVL(5, 3, 8, 0, 0), (G_GENO|G_NOCORPSE|1),
A(ATTK(AT_BITE, AD_DCAY, 0, 0),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(500, 250, MS_SILENT, MZ_MEDIUM),
M1_MINDLESS|M1_OMNIVORE|M1_ACID,
M2_HOSTILE|M2_NEUTER, 0, CLR_BROWN),
MON("green slime", S_PUDDING,
- LVL(6, 6, 6, 0, 0), (G_HELL|G_GENO|1),
+ LVL(6, 6, 6, 0, 0), (G_HELL|G_GENO|G_NOCORPSE|1),
A(ATTK(AT_TUCH, AD_SLIM, 1, 4), ATTK(AT_NONE, AD_SLIM, 0, 0),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(400, 150, MS_SILENT, MZ_LARGE),
M1_MINDLESS|M1_OMNIVORE|M1_ACID|M1_POIS,
M2_HOSTILE|M2_NEUTER, 0, CLR_GREEN),
MON("black pudding", S_PUDDING,
- LVL(10, 6, 6, 0, 0), (G_GENO|1),
+ LVL(10, 6, 6, 0, 0), (G_GENO|G_NOCORPSE|1),
A(ATTK(AT_BITE, AD_CORR, 3, 8), ATTK(AT_NONE, AD_CORR, 0, 0),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(900, 250, MS_SILENT, MZ_LARGE),
STATIC_DCL char *FDECL(minimal_xname, (struct obj *));
STATIC_DCL void FDECL(add_erosion_words, (struct obj *, char *));
STATIC_DCL boolean FDECL(singplur_lookup, (char *,char *,BOOLEAN_P,
- const char *const *));
+ const char *const *));
STATIC_DCL char *FDECL(singplur_compound, (char *));
struct Jitem {
- int item;
- const char *name;
+ int item;
+ const char *name;
};
#define BSTRCMPI(base,ptr,str) ((ptr) < base || strcmpi((ptr),str))
/* true for gems/rocks that should have " stone" appended to their names */
#define GemStone(typ) (typ == FLINT || \
- (objects[typ].oc_material == GEMSTONE && \
- (typ != DILITHIUM_CRYSTAL && typ != RUBY && \
- typ != DIAMOND && typ != SAPPHIRE && \
- typ != BLACK_OPAL && \
- typ != EMERALD && typ != OPAL)))
+ (objects[typ].oc_material == GEMSTONE && \
+ (typ != DILITHIUM_CRYSTAL && typ != RUBY && \
+ typ != DIAMOND && typ != SAPPHIRE && \
+ typ != BLACK_OPAL && \
+ typ != EMERALD && typ != OPAL)))
STATIC_OVL struct Jitem Japanese_items[] = {
- { SHORT_SWORD, "wakizashi" },
- { BROADSWORD, "ninja-to" },
- { FLAIL, "nunchaku" },
- { GLAIVE, "naginata" },
- { LOCK_PICK, "osaku" },
- { WOODEN_HARP, "koto" },
- { KNIFE, "shito" },
- { PLATE_MAIL, "tanko" },
- { HELMET, "kabuto" },
- { LEATHER_GLOVES, "yugake" },
- { FOOD_RATION, "gunyoki" },
- { POT_BOOZE, "sake" },
- {0, "" }
+ { SHORT_SWORD, "wakizashi" },
+ { BROADSWORD, "ninja-to" },
+ { FLAIL, "nunchaku" },
+ { GLAIVE, "naginata" },
+ { LOCK_PICK, "osaku" },
+ { WOODEN_HARP, "koto" },
+ { KNIFE, "shito" },
+ { PLATE_MAIL, "tanko" },
+ { HELMET, "kabuto" },
+ { LEATHER_GLOVES, "yugake" },
+ { FOOD_RATION, "gunyoki" },
+ { POT_BOOZE, "sake" },
+ {0, "" }
};
STATIC_DCL const char *FDECL(Japanese_item_name,(int i));
register char *s;
register const char *pref;
{
- register int i = (int)strlen(pref);
-
- if(i > PREFIX) {
- impossible("PREFIX too short (for %d).", i);
- return(s);
- }
- s -= i;
- (void) strncpy(s, pref, i); /* do not copy trailing 0 */
- return(s);
+ register int i = (int)strlen(pref);
+
+ if(i > PREFIX) {
+ impossible("PREFIX too short (for %d).", i);
+ return(s);
+ }
+ s -= i;
+ (void) strncpy(s, pref, i); /* do not copy trailing 0 */
+ return(s);
}
/* manage a pool of BUFSZ buffers, so callers don't have to */
STATIC_OVL char *
nextobuf()
{
- obufidx = (obufidx + 1) % NUMOBUF;
- return obufs[obufidx];
+ obufidx = (obufidx + 1) % NUMOBUF;
+ return obufs[obufidx];
}
/* put the most recently allocated buffer back if possible */
releaseobuf(bufp)
char *bufp;
{
- /* caller may not know whether bufp is the most recently allocated
- buffer; if it isn't, do nothing */
- if (bufp == obufs[obufidx])
- obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
+ /* caller may not know whether bufp is the most recently allocated
+ buffer; if it isn't, do nothing */
+ if (bufp == obufs[obufidx])
+ obufidx = (obufidx - 1 + NUMOBUF) % NUMOBUF;
}
char *
obj_typename(otyp)
register int otyp;
{
- char *buf = nextobuf();
- register struct objclass *ocl = &objects[otyp];
- register const char *actualn = OBJ_NAME(*ocl);
- register const char *dn = OBJ_DESCR(*ocl);
- register const char *un = ocl->oc_uname;
- register int nn = ocl->oc_name_known;
-
- if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
- actualn = Japanese_item_name(otyp);
- switch(ocl->oc_class) {
- case COIN_CLASS:
- Strcpy(buf, "coin");
- break;
- case POTION_CLASS:
- Strcpy(buf, "potion");
- break;
- case SCROLL_CLASS:
- Strcpy(buf, "scroll");
- break;
- case WAND_CLASS:
- Strcpy(buf, "wand");
- break;
- case SPBOOK_CLASS:
- Strcpy(buf, "spellbook");
- break;
- case RING_CLASS:
- Strcpy(buf, "ring");
- break;
- case AMULET_CLASS:
- if(nn)
- Strcpy(buf,actualn);
- else
- Strcpy(buf,"amulet");
- if(un)
- Sprintf(eos(buf)," called %s",un);
- if(dn)
- Sprintf(eos(buf)," (%s)",dn);
- return(buf);
- default:
- if(nn) {
- Strcpy(buf, actualn);
- if (GemStone(otyp))
- Strcat(buf, " stone");
- if(un)
- Sprintf(eos(buf), " called %s", un);
- if(dn)
- Sprintf(eos(buf), " (%s)", dn);
- } else {
- Strcpy(buf, dn ? dn : actualn);
- if(ocl->oc_class == GEM_CLASS)
- Strcat(buf, (ocl->oc_material == MINERAL) ?
- " stone" : " gem");
- if(un)
- Sprintf(eos(buf), " called %s", un);
- }
- return(buf);
- }
- /* here for ring/scroll/potion/wand */
- if(nn) {
- if (ocl->oc_unique)
- Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
- else
- Sprintf(eos(buf), " of %s", actualn);
- }
- if(un)
- Sprintf(eos(buf), " called %s", un);
- if(dn)
- Sprintf(eos(buf), " (%s)", dn);
- return(buf);
+ char *buf = nextobuf();
+ register struct objclass *ocl = &objects[otyp];
+ register const char *actualn = OBJ_NAME(*ocl);
+ register const char *dn = OBJ_DESCR(*ocl);
+ register const char *un = ocl->oc_uname;
+ register int nn = ocl->oc_name_known;
+
+ if (Role_if(PM_SAMURAI) && Japanese_item_name(otyp))
+ actualn = Japanese_item_name(otyp);
+ switch(ocl->oc_class) {
+ case COIN_CLASS:
+ Strcpy(buf, "coin");
+ break;
+ case POTION_CLASS:
+ Strcpy(buf, "potion");
+ break;
+ case SCROLL_CLASS:
+ Strcpy(buf, "scroll");
+ break;
+ case WAND_CLASS:
+ Strcpy(buf, "wand");
+ break;
+ case SPBOOK_CLASS:
+ Strcpy(buf, "spellbook");
+ break;
+ case RING_CLASS:
+ Strcpy(buf, "ring");
+ break;
+ case AMULET_CLASS:
+ if(nn)
+ Strcpy(buf,actualn);
+ else
+ Strcpy(buf,"amulet");
+ if(un)
+ Sprintf(eos(buf)," called %s",un);
+ if(dn)
+ Sprintf(eos(buf)," (%s)",dn);
+ return(buf);
+ default:
+ if(nn) {
+ Strcpy(buf, actualn);
+ if (GemStone(otyp))
+ Strcat(buf, " stone");
+ if(un)
+ Sprintf(eos(buf), " called %s", un);
+ if(dn)
+ Sprintf(eos(buf), " (%s)", dn);
+ } else {
+ Strcpy(buf, dn ? dn : actualn);
+ if(ocl->oc_class == GEM_CLASS)
+ Strcat(buf, (ocl->oc_material == MINERAL) ?
+ " stone" : " gem");
+ if(un)
+ Sprintf(eos(buf), " called %s", un);
+ }
+ return(buf);
+ }
+ /* here for ring/scroll/potion/wand */
+ if(nn) {
+ if (ocl->oc_unique)
+ Strcpy(buf, actualn); /* avoid spellbook of Book of the Dead */
+ else
+ Sprintf(eos(buf), " of %s", actualn);
+ }
+ if(un)
+ Sprintf(eos(buf), " called %s", un);
+ if(dn)
+ Sprintf(eos(buf), " (%s)", dn);
+ return(buf);
}
/* less verbose result than obj_typename(); either the actual name
bufp = obj_typename(otyp);
objects[otyp].oc_uname = save_uname;
if ((pp = strstri(bufp, " (")) != 0)
- *pp = '\0'; /* strip the appended description */
+ *pp = '\0'; /* strip the appended description */
return bufp;
}
{
if (!obj->oartifact || !has_oname(obj)) return FALSE;
if (!program_state.gameover && !iflags.override_ID) {
- if (not_fully_identified(obj)) return FALSE;
+ if (not_fully_identified(obj)) return FALSE;
}
return TRUE;
}
register struct obj *obj;
char *FDECL((*func), (OBJ_P));
{
- char *str;
+ char *str;
- long save_Blinded = Blinded;
- Blinded = 1;
- str = (*func)(obj);
- Blinded = save_Blinded;
- return str;
+ long save_Blinded = Blinded;
+ Blinded = 1;
+ str = (*func)(obj);
+ Blinded = save_Blinded;
+ return str;
}
/* convert player specified fruit name into corresponding fruit juice name
const char *fruit_nam = strstri(pl_fruit, " of ");
if (fruit_nam)
- fruit_nam += 4; /* skip past " of " */
+ fruit_nam += 4; /* skip past " of " */
else
- fruit_nam = pl_fruit; /* use it as is */
+ fruit_nam = pl_fruit; /* use it as is */
Sprintf(buf, "%s%s", makesingular(fruit_nam), juice ? " juice" : "");
return buf;
xname(obj)
register struct obj *obj;
{
- register char *buf;
- register int typ = obj->otyp;
- register struct objclass *ocl = &objects[typ];
- int nn = ocl->oc_name_known, omndx = obj->corpsenm;
- const char *actualn = OBJ_NAME(*ocl);
- const char *dn = OBJ_DESCR(*ocl);
- const char *un = ocl->oc_uname;
- boolean pluralize = (obj->quan != 1L);
- boolean known, dknown, bknown;
-
- buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
- if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
- actualn = Japanese_item_name(typ);
-
- buf[0] = '\0';
- /*
- * clean up known when it's tied to oc_name_known, eg after AD_DRIN
- * This is only required for unique objects since the article
- * printed for the object is tied to the combination of the two
- * and printing the wrong article gives away information.
- */
- if (!nn && ocl->oc_uses_known && ocl->oc_unique) obj->known = 0;
- if (!Blind) obj->dknown = TRUE;
- if (Role_if(PM_PRIEST)) obj->bknown = TRUE;
-
- if (iflags.override_ID) {
- known = dknown = bknown = TRUE;
- nn = 1;
- } else {
- known = obj->known;
- dknown = obj->dknown;
- bknown = obj->bknown;
- }
-
- if (obj_is_pname(obj))
- goto nameit;
- switch (obj->oclass) {
- case AMULET_CLASS:
- if (!dknown)
- Strcpy(buf, "amulet");
- else if (typ == AMULET_OF_YENDOR ||
- typ == FAKE_AMULET_OF_YENDOR)
- /* each must be identified individually */
- Strcpy(buf, known ? actualn : dn);
- else if (nn)
- Strcpy(buf, actualn);
- else if (un)
- Sprintf(buf,"amulet called %s", un);
- else
- Sprintf(buf,"%s amulet", dn);
- break;
- case WEAPON_CLASS:
- if (is_poisonable(obj) && obj->opoisoned)
- Strcpy(buf, "poisoned ");
- case VENOM_CLASS:
- case TOOL_CLASS:
- if (typ == LENSES)
- Strcpy(buf, "pair of ");
-
- if (!dknown)
- Strcat(buf, dn ? dn : actualn);
- else if (nn)
- Strcat(buf, actualn);
- else if (un) {
- Strcat(buf, dn ? dn : actualn);
- Strcat(buf, " called ");
- Strcat(buf, un);
- } else
- Strcat(buf, dn ? dn : actualn);
- /* If we use an() here we'd have to remember never to use */
- /* it whenever calling doname() or xname(). */
- if (typ == FIGURINE && omndx != NON_PM)
- Sprintf(eos(buf), " of a%s %s",
- index(vowels, *mons[omndx].mname) ? "n" : "",
- mons[omndx].mname);
- break;
- case ARMOR_CLASS:
- /* depends on order of the dragon scales objects */
- if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
- Sprintf(buf, "set of %s", actualn);
- break;
- }
- if(is_boots(obj) || is_gloves(obj)) Strcpy(buf,"pair of ");
-
- if(obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
- && !dknown) {
- Strcpy(buf, "shield");
- break;
- }
- if(obj->otyp == SHIELD_OF_REFLECTION && !dknown) {
- Strcpy(buf, "smooth shield");
- break;
- }
-
- if(nn) Strcat(buf, actualn);
- else if(un) {
- if(is_boots(obj))
- Strcat(buf,"boots");
- else if(is_gloves(obj))
- Strcat(buf,"gloves");
- else if(is_cloak(obj))
- Strcpy(buf,"cloak");
- else if(is_helmet(obj))
- Strcpy(buf,"helmet");
- else if(is_shield(obj))
- Strcpy(buf,"shield");
- else
- Strcpy(buf,"armor");
- Strcat(buf, " called ");
- Strcat(buf, un);
- } else Strcat(buf, dn);
- break;
- case FOOD_CLASS:
- if (typ == SLIME_MOLD) {
- register struct fruit *f;
-
- for(f=ffruit; f; f = f->nextf) {
- if(f->fid == obj->spe) {
- Strcpy(buf, f->fname);
- break;
- }
- }
- if (!f) {
- impossible("Bad fruit #%d?", obj->spe);
- Strcpy(buf, "fruit");
- } else if (pluralize) {
- /* ick; already pluralized fruit names
- are allowed--we want to try to avoid
- adding a redundant plural suffix */
- Strcpy(buf, makeplural(makesingular(buf)));
- pluralize = FALSE;
- }
- break;
- }
+ register char *buf;
+ register int typ = obj->otyp;
+ register struct objclass *ocl = &objects[typ];
+ int nn = ocl->oc_name_known, omndx = obj->corpsenm;
+ const char *actualn = OBJ_NAME(*ocl);
+ const char *dn = OBJ_DESCR(*ocl);
+ const char *un = ocl->oc_uname;
+ boolean pluralize = (obj->quan != 1L);
+ boolean known, dknown, bknown;
+
+ buf = nextobuf() + PREFIX; /* leave room for "17 -3 " */
+ if (Role_if(PM_SAMURAI) && Japanese_item_name(typ))
+ actualn = Japanese_item_name(typ);
+
+ buf[0] = '\0';
+ /*
+ * clean up known when it's tied to oc_name_known, eg after AD_DRIN
+ * This is only required for unique objects since the article
+ * printed for the object is tied to the combination of the two
+ * and printing the wrong article gives away information.
+ */
+ if (!nn && ocl->oc_uses_known && ocl->oc_unique) obj->known = 0;
+ if (!Blind) obj->dknown = TRUE;
+ if (Role_if(PM_PRIEST)) obj->bknown = TRUE;
+
+ if (iflags.override_ID) {
+ known = dknown = bknown = TRUE;
+ nn = 1;
+ } else {
+ known = obj->known;
+ dknown = obj->dknown;
+ bknown = obj->bknown;
+ }
+
+ if (obj_is_pname(obj))
+ goto nameit;
+ switch (obj->oclass) {
+ case AMULET_CLASS:
+ if (!dknown)
+ Strcpy(buf, "amulet");
+ else if (typ == AMULET_OF_YENDOR ||
+ typ == FAKE_AMULET_OF_YENDOR)
+ /* each must be identified individually */
+ Strcpy(buf, known ? actualn : dn);
+ else if (nn)
+ Strcpy(buf, actualn);
+ else if (un)
+ Sprintf(buf,"amulet called %s", un);
+ else
+ Sprintf(buf,"%s amulet", dn);
+ break;
+ case WEAPON_CLASS:
+ if (is_poisonable(obj) && obj->opoisoned)
+ Strcpy(buf, "poisoned ");
+ case VENOM_CLASS:
+ case TOOL_CLASS:
+ if (typ == LENSES)
+ Strcpy(buf, "pair of ");
+
+ if (!dknown)
+ Strcat(buf, dn ? dn : actualn);
+ else if (nn)
+ Strcat(buf, actualn);
+ else if (un) {
+ Strcat(buf, dn ? dn : actualn);
+ Strcat(buf, " called ");
+ Strcat(buf, un);
+ } else
+ Strcat(buf, dn ? dn : actualn);
+ /* If we use an() here we'd have to remember never to use */
+ /* it whenever calling doname() or xname(). */
+ if (typ == FIGURINE && omndx != NON_PM)
+ Sprintf(eos(buf), " of a%s %s",
+ index(vowels, *mons[omndx].mname) ? "n" : "",
+ mons[omndx].mname);
+ break;
+ case ARMOR_CLASS:
+ /* depends on order of the dragon scales objects */
+ if (typ >= GRAY_DRAGON_SCALES && typ <= YELLOW_DRAGON_SCALES) {
+ Sprintf(buf, "set of %s", actualn);
+ break;
+ }
+ if(is_boots(obj) || is_gloves(obj)) Strcpy(buf,"pair of ");
+
+ if(obj->otyp >= ELVEN_SHIELD && obj->otyp <= ORCISH_SHIELD
+ && !dknown) {
+ Strcpy(buf, "shield");
+ break;
+ }
+ if(obj->otyp == SHIELD_OF_REFLECTION && !dknown) {
+ Strcpy(buf, "smooth shield");
+ break;
+ }
+
+ if(nn) Strcat(buf, actualn);
+ else if(un) {
+ if(is_boots(obj))
+ Strcat(buf,"boots");
+ else if(is_gloves(obj))
+ Strcat(buf,"gloves");
+ else if(is_cloak(obj))
+ Strcpy(buf,"cloak");
+ else if(is_helmet(obj))
+ Strcpy(buf,"helmet");
+ else if(is_shield(obj))
+ Strcpy(buf,"shield");
+ else
+ Strcpy(buf,"armor");
+ Strcat(buf, " called ");
+ Strcat(buf, un);
+ } else Strcat(buf, dn);
+ break;
+ case FOOD_CLASS:
+ if (typ == SLIME_MOLD) {
+ register struct fruit *f;
+
+ for(f=ffruit; f; f = f->nextf) {
+ if(f->fid == obj->spe) {
+ Strcpy(buf, f->fname);
+ break;
+ }
+ }
+ if (!f) {
+ impossible("Bad fruit #%d?", obj->spe);
+ Strcpy(buf, "fruit");
+ } else if (pluralize) {
+ /* ick; already pluralized fruit names
+ are allowed--we want to try to avoid
+ adding a redundant plural suffix */
+ Strcpy(buf, makeplural(makesingular(buf)));
+ pluralize = FALSE;
+ }
+ break;
+ }
if (Is_pudding(obj)) {
Sprintf(buf, "%s%s",
obj->owt < 100 ? "small "
break;
}
- Strcpy(buf, actualn);
- if (typ == TIN && known)
- tin_details(obj, omndx, buf);
- break;
- case COIN_CLASS:
- case CHAIN_CLASS:
- Strcpy(buf, actualn);
- break;
- case ROCK_CLASS:
- if (typ == STATUE && omndx != NON_PM)
- Sprintf(buf, "%s%s of %s%s",
- (Role_if(PM_ARCHEOLOGIST) &&
- (obj->spe & STATUE_HISTORIC)) ? "historic " : "",
- actualn,
- type_is_pname(&mons[omndx]) ? "" :
- the_unique_pm(&mons[omndx]) ? "the " :
- index(vowels, *mons[omndx].mname) ? "an " : "a ",
- mons[omndx].mname);
- else Strcpy(buf, actualn);
- break;
- case BALL_CLASS:
- Sprintf(buf, "%sheavy iron ball",
- (obj->owt > ocl->oc_weight) ? "very " : "");
- break;
- case POTION_CLASS:
- if (dknown && obj->odiluted)
- Strcpy(buf, "diluted ");
- if(nn || un || !dknown) {
- Strcat(buf, "potion");
- if(!dknown) break;
- if(nn) {
- Strcat(buf, " of ");
- if (typ == POT_WATER &&
- bknown && (obj->blessed || obj->cursed)) {
- Strcat(buf, obj->blessed ? "holy " : "unholy ");
- }
- Strcat(buf, actualn);
- } else {
- Strcat(buf, " called ");
- Strcat(buf, un);
- }
- } else {
- Strcat(buf, dn);
- Strcat(buf, " potion");
- }
- break;
- case SCROLL_CLASS:
- Strcpy(buf, "scroll");
- if(!dknown) break;
- if(nn) {
- Strcat(buf, " of ");
- Strcat(buf, actualn);
- } else if(un) {
- Strcat(buf, " called ");
- Strcat(buf, un);
- } else if (ocl->oc_magic) {
- Strcat(buf, " labeled ");
- Strcat(buf, dn);
- } else {
- Strcpy(buf, dn);
- Strcat(buf, " scroll");
- }
- break;
- case WAND_CLASS:
- if(!dknown)
- Strcpy(buf, "wand");
- else if(nn)
- Sprintf(buf, "wand of %s", actualn);
- else if(un)
- Sprintf(buf, "wand called %s", un);
- else
- Sprintf(buf, "%s wand", dn);
- break;
- case SPBOOK_CLASS:
- if (!dknown) {
- Strcpy(buf, "spellbook");
- } else if (nn) {
- if (typ != SPE_BOOK_OF_THE_DEAD)
- Strcpy(buf, "spellbook of ");
- Strcat(buf, actualn);
- } else if (un) {
- Sprintf(buf, "spellbook called %s", un);
- } else
- Sprintf(buf, "%s spellbook", dn);
- break;
- case RING_CLASS:
- if(!dknown)
- Strcpy(buf, "ring");
- else if(nn)
- Sprintf(buf, "ring of %s", actualn);
- else if(un)
- Sprintf(buf, "ring called %s", un);
- else
- Sprintf(buf, "%s ring", dn);
- break;
- case GEM_CLASS:
- {
- const char *rock =
- (ocl->oc_material == MINERAL) ? "stone" : "gem";
- if (!dknown) {
- Strcpy(buf, rock);
- } else if (!nn) {
- if (un) Sprintf(buf,"%s called %s", rock, un);
- else Sprintf(buf, "%s %s", dn, rock);
- } else {
- Strcpy(buf, actualn);
- if (GemStone(typ)) Strcat(buf, " stone");
- }
- break;
- }
- default:
- Sprintf(buf,"glorkum %d %d %d", obj->oclass, typ, obj->spe);
- }
- if (pluralize) Strcpy(buf, makeplural(buf));
-
- if (has_oname(obj) && dknown) {
- Strcat(buf, " named ");
+ Strcpy(buf, actualn);
+ if (typ == TIN && known)
+ tin_details(obj, omndx, buf);
+ break;
+ case COIN_CLASS:
+ case CHAIN_CLASS:
+ Strcpy(buf, actualn);
+ break;
+ case ROCK_CLASS:
+ if (typ == STATUE && omndx != NON_PM)
+ Sprintf(buf, "%s%s of %s%s",
+ (Role_if(PM_ARCHEOLOGIST) &&
+ (obj->spe & STATUE_HISTORIC)) ? "historic " : "",
+ actualn,
+ type_is_pname(&mons[omndx]) ? "" :
+ the_unique_pm(&mons[omndx]) ? "the " :
+ index(vowels, *mons[omndx].mname) ? "an " : "a ",
+ mons[omndx].mname);
+ else Strcpy(buf, actualn);
+ break;
+ case BALL_CLASS:
+ Sprintf(buf, "%sheavy iron ball",
+ (obj->owt > ocl->oc_weight) ? "very " : "");
+ break;
+ case POTION_CLASS:
+ if (dknown && obj->odiluted)
+ Strcpy(buf, "diluted ");
+ if(nn || un || !dknown) {
+ Strcat(buf, "potion");
+ if(!dknown) break;
+ if(nn) {
+ Strcat(buf, " of ");
+ if (typ == POT_WATER &&
+ bknown && (obj->blessed || obj->cursed)) {
+ Strcat(buf, obj->blessed ? "holy " : "unholy ");
+ }
+ Strcat(buf, actualn);
+ } else {
+ Strcat(buf, " called ");
+ Strcat(buf, un);
+ }
+ } else {
+ Strcat(buf, dn);
+ Strcat(buf, " potion");
+ }
+ break;
+ case SCROLL_CLASS:
+ Strcpy(buf, "scroll");
+ if(!dknown) break;
+ if(nn) {
+ Strcat(buf, " of ");
+ Strcat(buf, actualn);
+ } else if(un) {
+ Strcat(buf, " called ");
+ Strcat(buf, un);
+ } else if (ocl->oc_magic) {
+ Strcat(buf, " labeled ");
+ Strcat(buf, dn);
+ } else {
+ Strcpy(buf, dn);
+ Strcat(buf, " scroll");
+ }
+ break;
+ case WAND_CLASS:
+ if(!dknown)
+ Strcpy(buf, "wand");
+ else if(nn)
+ Sprintf(buf, "wand of %s", actualn);
+ else if(un)
+ Sprintf(buf, "wand called %s", un);
+ else
+ Sprintf(buf, "%s wand", dn);
+ break;
+ case SPBOOK_CLASS:
+ if (!dknown) {
+ Strcpy(buf, "spellbook");
+ } else if (nn) {
+ if (typ != SPE_BOOK_OF_THE_DEAD)
+ Strcpy(buf, "spellbook of ");
+ Strcat(buf, actualn);
+ } else if (un) {
+ Sprintf(buf, "spellbook called %s", un);
+ } else
+ Sprintf(buf, "%s spellbook", dn);
+ break;
+ case RING_CLASS:
+ if(!dknown)
+ Strcpy(buf, "ring");
+ else if(nn)
+ Sprintf(buf, "ring of %s", actualn);
+ else if(un)
+ Sprintf(buf, "ring called %s", un);
+ else
+ Sprintf(buf, "%s ring", dn);
+ break;
+ case GEM_CLASS:
+ {
+ const char *rock =
+ (ocl->oc_material == MINERAL) ? "stone" : "gem";
+ if (!dknown) {
+ Strcpy(buf, rock);
+ } else if (!nn) {
+ if (un) Sprintf(buf,"%s called %s", rock, un);
+ else Sprintf(buf, "%s %s", dn, rock);
+ } else {
+ Strcpy(buf, actualn);
+ if (GemStone(typ)) Strcat(buf, " stone");
+ }
+ break;
+ }
+ default:
+ Sprintf(buf,"glorkum %d %d %d", obj->oclass, typ, obj->spe);
+ }
+ if (pluralize) Strcpy(buf, makeplural(buf));
+
+ if (has_oname(obj) && dknown) {
+ Strcat(buf, " named ");
nameit:
- Strcat(buf, ONAME(obj));
- }
+ Strcat(buf, ONAME(obj));
+ }
- if (!strncmpi(buf, "the ", 4)) buf += 4;
- return(buf);
+ if (!strncmpi(buf, "the ", 4)) buf += 4;
+ return(buf);
}
/* similar to simple_typename but minimal_xname operates on a particular
object rather than its general type; it formats the most basic info:
- potion -- if description not known
- brown potion -- if oc_name_known not set
- potion of object detection -- if discovered
+ potion -- if description not known
+ brown potion -- if oc_name_known not set
+ potion of object detection -- if discovered
*/
static char *
minimal_xname(obj)
bareobj.dknown = obj->dknown;
/* suppress known except for amulets (needed for fakes and real A-of-Y) */
bareobj.known = (obj->oclass == AMULET_CLASS) ? obj->known :
- /* default is "on" for types which don't use it */
- !objects[otyp].oc_uses_known;
+ /* default is "on" for types which don't use it */
+ !objects[otyp].oc_uses_known;
bareobj.quan = 1L; /* don't want plural */
bareobj.corpsenm = NON_PM; /* suppress statue and figurine details */
bufp = distant_name(&bareobj, xname); /* xname(&bareobj) */
char *onm = xname(obj);
if (m_shot.n > 1 && m_shot.o == obj->otyp) {
- /* copy xname's result so that we can reuse its return buffer */
- Strcpy(tmpbuf, onm);
- /* "the Nth arrow"; value will eventually be passed to an() or
- The(), both of which correctly handle this "the " prefix */
- Sprintf(onm, "the %d%s %s", m_shot.i, ordin(m_shot.i), tmpbuf);
+ /* copy xname's result so that we can reuse its return buffer */
+ Strcpy(tmpbuf, onm);
+ /* "the Nth arrow"; value will eventually be passed to an() or
+ The(), both of which correctly handle this "the " prefix */
+ Sprintf(onm, "the %d%s %s", m_shot.i, ordin(m_shot.i), tmpbuf);
}
return onm;
{
boolean known = (obj->known || iflags.override_ID);
if (!obj->dknown && !iflags.override_ID)
- return FALSE;
+ return FALSE;
else if (obj->otyp == FAKE_AMULET_OF_YENDOR && !known)
- return TRUE; /* lie */
+ return TRUE; /* lie */
else
- return (boolean)(objects[obj->otyp].oc_unique &&
- (known || obj->otyp == AMULET_OF_YENDOR));
+ return (boolean)(objects[obj->otyp].oc_unique &&
+ (known || obj->otyp == AMULET_OF_YENDOR));
}
/* should monster type be prefixed with "the"? (mostly used for corpses) */
the_unique_pm(ptr)
struct permonst *ptr;
{
- boolean uniq;
-
- /* even though monsters with personal names are unique, we want to
- describe them as "Name" rather than "the Name" */
- if (type_is_pname(ptr)) return FALSE;
-
- uniq = (ptr->geno & G_UNIQ) ? TRUE : FALSE;
- /* high priest is unique if it includes "of <deity>", otherwise not
- (caller needs to handle the 1st possibility; we assume the 2nd);
- worm tail should be irrelevant but is included for completeness */
- if (ptr == &mons[PM_HIGH_PRIEST] || ptr == &mons[PM_LONG_WORM_TAIL])
- uniq = FALSE;
- /* Wizard no longer needs this; he's flagged as unique these days */
- if (ptr == &mons[PM_WIZARD_OF_YENDOR])
- uniq = TRUE;
- return uniq;
+ boolean uniq;
+
+ /* even though monsters with personal names are unique, we want to
+ describe them as "Name" rather than "the Name" */
+ if (type_is_pname(ptr)) return FALSE;
+
+ uniq = (ptr->geno & G_UNIQ) ? TRUE : FALSE;
+ /* high priest is unique if it includes "of <deity>", otherwise not
+ (caller needs to handle the 1st possibility; we assume the 2nd);
+ worm tail should be irrelevant but is included for completeness */
+ if (ptr == &mons[PM_HIGH_PRIEST] || ptr == &mons[PM_LONG_WORM_TAIL])
+ uniq = FALSE;
+ /* Wizard no longer needs this; he's flagged as unique these days */
+ if (ptr == &mons[PM_WIZARD_OF_YENDOR])
+ uniq = TRUE;
+ return uniq;
}
STATIC_OVL void
struct obj *obj;
char *prefix;
{
- boolean iscrys = (obj->otyp == CRYSKNIFE);
- boolean rknown;
-
- rknown = (iflags.override_ID == 0) ? obj->rknown : TRUE;
-
- if (!is_damageable(obj) && !iscrys) return;
-
- /* The only cases where any of these bits do double duty are for
- * rotted food and diluted potions, which are all not is_damageable().
- */
- if (obj->oeroded && !iscrys) {
- switch (obj->oeroded) {
- case 2: Strcat(prefix, "very "); break;
- case 3: Strcat(prefix, "thoroughly "); break;
- }
- Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
- }
- if (obj->oeroded2 && !iscrys) {
- switch (obj->oeroded2) {
- case 2: Strcat(prefix, "very "); break;
- case 3: Strcat(prefix, "thoroughly "); break;
- }
- Strcat(prefix, is_corrodeable(obj) ? "corroded " :
- "rotted ");
- }
- if (rknown && obj->oerodeproof)
- Strcat(prefix,
- iscrys ? "fixed " :
- is_rustprone(obj) ? "rustproof " :
- is_corrodeable(obj) ? "corrodeproof " : /* "stainless"? */
- is_flammable(obj) ? "fireproof " : "");
+ boolean iscrys = (obj->otyp == CRYSKNIFE);
+ boolean rknown;
+
+ rknown = (iflags.override_ID == 0) ? obj->rknown : TRUE;
+
+ if (!is_damageable(obj) && !iscrys) return;
+
+ /* The only cases where any of these bits do double duty are for
+ * rotted food and diluted potions, which are all not is_damageable().
+ */
+ if (obj->oeroded && !iscrys) {
+ switch (obj->oeroded) {
+ case 2: Strcat(prefix, "very "); break;
+ case 3: Strcat(prefix, "thoroughly "); break;
+ }
+ Strcat(prefix, is_rustprone(obj) ? "rusty " : "burnt ");
+ }
+ if (obj->oeroded2 && !iscrys) {
+ switch (obj->oeroded2) {
+ case 2: Strcat(prefix, "very "); break;
+ case 3: Strcat(prefix, "thoroughly "); break;
+ }
+ Strcat(prefix, is_corrodeable(obj) ? "corroded " :
+ "rotted ");
+ }
+ if (rknown && obj->oerodeproof)
+ Strcat(prefix,
+ iscrys ? "fixed " :
+ is_rustprone(obj) ? "rustproof " :
+ is_corrodeable(obj) ? "corrodeproof " : /* "stainless"? */
+ is_flammable(obj) ? "fireproof " : "");
}
char *
doname(obj)
register struct obj *obj;
{
- boolean ispoisoned = FALSE;
- boolean known, cknown, bknown, lknown;
- int omndx = obj->corpsenm;
- char prefix[PREFIX];
- char tmpbuf[PREFIX+1];
- /* when we have to add something at the start of prefix instead of the
- * end (Strcat is used on the end)
- */
- register char *bp = xname(obj);
-
- if (iflags.override_ID) known = cknown = bknown = lknown = TRUE;
- else {
- known = obj->known;
- cknown = obj->cknown;
- bknown = obj->bknown;
- lknown = obj->lknown;
- }
-
- /* When using xname, we want "poisoned arrow", and when using
- * doname, we want "poisoned +0 arrow". This kludge is about the only
- * way to do it, at least until someone overhauls xname() and doname(),
- * combining both into one function taking a parameter.
- */
- /* must check opoisoned--someone can have a weirdly-named fruit */
- if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
- bp += 9;
- ispoisoned = TRUE;
- }
-
- if(obj->quan != 1L)
- Sprintf(prefix, "%ld ", obj->quan);
- else if (obj->otyp == CORPSE)
- /* skip article prefix for corpses [else corpse_xname()
- would have to be taught how to strip it off again] */
- *prefix = '\0';
- else if (obj_is_pname(obj) || the_unique_obj(obj)) {
- if (!strncmpi(bp, "the ", 4))
- bp += 4;
- Strcpy(prefix, "the ");
- } else
- Strcpy(prefix, "a ");
-
- /* "empty" goes at the beginning, but item count goes at the end */
- if (cknown &&
- (Is_container(obj) || obj->otyp == STATUE) && !Has_contents(obj))
- Strcat(prefix, "empty ");
-
- if (bknown &&
- obj->oclass != COIN_CLASS &&
- (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
- || (!obj->cursed && !obj->blessed))) {
- /* allow 'blessed clear potion' if we don't know it's holy water;
- * always allow "uncursed potion of water"
- */
- if (obj->cursed)
- Strcat(prefix, "cursed ");
- else if (obj->blessed)
- Strcat(prefix, "blessed ");
- else if ((!known || !objects[obj->otyp].oc_charged ||
- (obj->oclass == ARMOR_CLASS ||
- obj->oclass == RING_CLASS))
- /* For most items with charges or +/-, if you know how many
- * charges are left or what the +/- is, then you must have
- * totally identified the item, so "uncursed" is unneccesary,
- * because an identified object not described as "blessed" or
- * "cursed" must be uncursed.
- *
- * If the charges or +/- is not known, "uncursed" must be
- * printed to avoid ambiguity between an item whose curse
- * status is unknown, and an item known to be uncursed.
- */
+ boolean ispoisoned = FALSE;
+ boolean known, cknown, bknown, lknown;
+ int omndx = obj->corpsenm;
+ char prefix[PREFIX];
+ char tmpbuf[PREFIX+1];
+ /* when we have to add something at the start of prefix instead of the
+ * end (Strcat is used on the end)
+ */
+ register char *bp = xname(obj);
+
+ if (iflags.override_ID) known = cknown = bknown = lknown = TRUE;
+ else {
+ known = obj->known;
+ cknown = obj->cknown;
+ bknown = obj->bknown;
+ lknown = obj->lknown;
+ }
+
+ /* When using xname, we want "poisoned arrow", and when using
+ * doname, we want "poisoned +0 arrow". This kludge is about the only
+ * way to do it, at least until someone overhauls xname() and doname(),
+ * combining both into one function taking a parameter.
+ */
+ /* must check opoisoned--someone can have a weirdly-named fruit */
+ if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) {
+ bp += 9;
+ ispoisoned = TRUE;
+ }
+
+ if(obj->quan != 1L)
+ Sprintf(prefix, "%ld ", obj->quan);
+ else if (obj->otyp == CORPSE)
+ /* skip article prefix for corpses [else corpse_xname()
+ would have to be taught how to strip it off again] */
+ *prefix = '\0';
+ else if (obj_is_pname(obj) || the_unique_obj(obj)) {
+ if (!strncmpi(bp, "the ", 4))
+ bp += 4;
+ Strcpy(prefix, "the ");
+ } else
+ Strcpy(prefix, "a ");
+
+ /* "empty" goes at the beginning, but item count goes at the end */
+ if (cknown &&
+ (Is_container(obj) || obj->otyp == STATUE) && !Has_contents(obj))
+ Strcat(prefix, "empty ");
+
+ if (bknown &&
+ obj->oclass != COIN_CLASS &&
+ (obj->otyp != POT_WATER || !objects[POT_WATER].oc_name_known
+ || (!obj->cursed && !obj->blessed))) {
+ /* allow 'blessed clear potion' if we don't know it's holy water;
+ * always allow "uncursed potion of water"
+ */
+ if (obj->cursed)
+ Strcat(prefix, "cursed ");
+ else if (obj->blessed)
+ Strcat(prefix, "blessed ");
+ else if ((!known || !objects[obj->otyp].oc_charged ||
+ (obj->oclass == ARMOR_CLASS ||
+ obj->oclass == RING_CLASS))
+ /* For most items with charges or +/-, if you know how many
+ * charges are left or what the +/- is, then you must have
+ * totally identified the item, so "uncursed" is unneccesary,
+ * because an identified object not described as "blessed" or
+ * "cursed" must be uncursed.
+ *
+ * If the charges or +/- is not known, "uncursed" must be
+ * printed to avoid ambiguity between an item whose curse
+ * status is unknown, and an item known to be uncursed.
+ */
#ifdef MAIL
- && obj->otyp != SCR_MAIL
+ && obj->otyp != SCR_MAIL
#endif
- && obj->otyp != FAKE_AMULET_OF_YENDOR
- && obj->otyp != AMULET_OF_YENDOR
- && !Role_if(PM_PRIEST))
- Strcat(prefix, "uncursed ");
- }
-
- if (lknown && Is_box(obj)) {
- if (obj->obroken)
- Strcat(prefix, "unlockable ");
- else if (obj->olocked)
- Strcat(prefix, "locked ");
- else
- Strcat(prefix, "unlocked ");
- }
-
- if (obj->greased) Strcat(prefix, "greased ");
-
- if (cknown && Has_contents(obj)) {
- /* we count all objects (obj->quantity); perhaps we should
- count seperate stacks instead (or even introduce a user
- preference option to choose between the two alternatives)
- since it's somewhat odd so see "containing 1002 items"
- when there are 2 scrolls plus 1000 gold pieces */
- long itemcount = count_contents(obj, FALSE, TRUE, TRUE);
-
- Sprintf(eos(bp), " containing %ld item%s",
- itemcount, plur(itemcount));
- }
-
- switch(obj->oclass) {
- case AMULET_CLASS:
- if(obj->owornmask & W_AMUL)
- Strcat(bp, " (being worn)");
- break;
- case WEAPON_CLASS:
- if(ispoisoned)
- Strcat(prefix, "poisoned ");
+ && obj->otyp != FAKE_AMULET_OF_YENDOR
+ && obj->otyp != AMULET_OF_YENDOR
+ && !Role_if(PM_PRIEST))
+ Strcat(prefix, "uncursed ");
+ }
+
+ if (lknown && Is_box(obj)) {
+ if (obj->obroken)
+ Strcat(prefix, "unlockable ");
+ else if (obj->olocked)
+ Strcat(prefix, "locked ");
+ else
+ Strcat(prefix, "unlocked ");
+ }
+
+ if (obj->greased) Strcat(prefix, "greased ");
+
+ if (cknown && Has_contents(obj)) {
+ /* we count all objects (obj->quantity); perhaps we should
+ count seperate stacks instead (or even introduce a user
+ preference option to choose between the two alternatives)
+ since it's somewhat odd so see "containing 1002 items"
+ when there are 2 scrolls plus 1000 gold pieces */
+ long itemcount = count_contents(obj, FALSE, TRUE, TRUE);
+
+ Sprintf(eos(bp), " containing %ld item%s",
+ itemcount, plur(itemcount));
+ }
+
+ switch(obj->oclass) {
+ case AMULET_CLASS:
+ if(obj->owornmask & W_AMUL)
+ Strcat(bp, " (being worn)");
+ break;
+ case WEAPON_CLASS:
+ if(ispoisoned)
+ Strcat(prefix, "poisoned ");
plus:
- add_erosion_words(obj, prefix);
- if(known) {
- Strcat(prefix, sitoa(obj->spe));
- Strcat(prefix, " ");
- }
- break;
- case ARMOR_CLASS:
- if(obj->owornmask & W_ARMOR)
- Strcat(bp, (obj == uskin) ? " (embedded in your skin)" :
- " (being worn)");
- goto plus;
- case TOOL_CLASS:
- /* weptools already get this done when we go to the +n code */
- if (!is_weptool(obj))
- add_erosion_words(obj, prefix);
- if(obj->owornmask & (W_TOOL /* blindfold */ | W_SADDLE)) {
- Strcat(bp, " (being worn)");
- break;
- }
- if (obj->otyp == LEASH && obj->leashmon != 0) {
- Strcat(bp, " (in use)");
- break;
- }
- if (is_weptool(obj))
- goto plus;
- if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
- if (!obj->spe)
- Strcpy(tmpbuf, "no");
- else
- Sprintf(tmpbuf, "%d", obj->spe);
- Sprintf(eos(bp), " (%s candle%s%s)",
- tmpbuf, plur(obj->spe),
- !obj->lamplit ? " attached" : ", lit");
- break;
- } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
- obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
- if (Is_candle(obj) &&
- obj->age < 20L * (long)objects[obj->otyp].oc_cost)
- Strcat(prefix, "partly used ");
- if(obj->lamplit)
- Strcat(bp, " (lit)");
- break;
- }
- if(objects[obj->otyp].oc_charged)
- goto charges;
- break;
- case WAND_CLASS:
- add_erosion_words(obj, prefix);
+ add_erosion_words(obj, prefix);
+ if(known) {
+ Strcat(prefix, sitoa(obj->spe));
+ Strcat(prefix, " ");
+ }
+ break;
+ case ARMOR_CLASS:
+ if(obj->owornmask & W_ARMOR)
+ Strcat(bp, (obj == uskin) ? " (embedded in your skin)" :
+ " (being worn)");
+ goto plus;
+ case TOOL_CLASS:
+ /* weptools already get this done when we go to the +n code */
+ if (!is_weptool(obj))
+ add_erosion_words(obj, prefix);
+ if(obj->owornmask & (W_TOOL /* blindfold */ | W_SADDLE)) {
+ Strcat(bp, " (being worn)");
+ break;
+ }
+ if (obj->otyp == LEASH && obj->leashmon != 0) {
+ Strcat(bp, " (in use)");
+ break;
+ }
+ if (is_weptool(obj))
+ goto plus;
+ if (obj->otyp == CANDELABRUM_OF_INVOCATION) {
+ if (!obj->spe)
+ Strcpy(tmpbuf, "no");
+ else
+ Sprintf(tmpbuf, "%d", obj->spe);
+ Sprintf(eos(bp), " (%s candle%s%s)",
+ tmpbuf, plur(obj->spe),
+ !obj->lamplit ? " attached" : ", lit");
+ break;
+ } else if (obj->otyp == OIL_LAMP || obj->otyp == MAGIC_LAMP ||
+ obj->otyp == BRASS_LANTERN || Is_candle(obj)) {
+ if (Is_candle(obj) &&
+ obj->age < 20L * (long)objects[obj->otyp].oc_cost)
+ Strcat(prefix, "partly used ");
+ if(obj->lamplit)
+ Strcat(bp, " (lit)");
+ break;
+ }
+ if(objects[obj->otyp].oc_charged)
+ goto charges;
+ break;
+ case WAND_CLASS:
+ add_erosion_words(obj, prefix);
charges:
- if(known)
- Sprintf(eos(bp), " (%d:%d)", (int)obj->recharged, obj->spe);
- break;
- case POTION_CLASS:
- if (obj->otyp == POT_OIL && obj->lamplit)
- Strcat(bp, " (lit)");
- break;
- case RING_CLASS:
- add_erosion_words(obj, prefix);
+ if(known)
+ Sprintf(eos(bp), " (%d:%d)", (int)obj->recharged, obj->spe);
+ break;
+ case POTION_CLASS:
+ if (obj->otyp == POT_OIL && obj->lamplit)
+ Strcat(bp, " (lit)");
+ break;
+ case RING_CLASS:
+ add_erosion_words(obj, prefix);
ring:
- if(obj->owornmask & W_RINGR) Strcat(bp, " (on right ");
- if(obj->owornmask & W_RINGL) Strcat(bp, " (on left ");
- if(obj->owornmask & W_RING) {
- Strcat(bp, body_part(HAND));
- Strcat(bp, ")");
- }
- if(known && objects[obj->otyp].oc_charged) {
- Strcat(prefix, sitoa(obj->spe));
- Strcat(prefix, " ");
- }
- break;
- case FOOD_CLASS:
- if (obj->oeaten)
- Strcat(prefix, "partly eaten ");
- if (obj->otyp == CORPSE) {
- Sprintf(prefix, "%s ",
- corpse_xname(obj, prefix,
- CXN_ARTICLE|CXN_NOCORPSE));
- } else if (obj->otyp == EGG) {
+ if(obj->owornmask & W_RINGR) Strcat(bp, " (on right ");
+ if(obj->owornmask & W_RINGL) Strcat(bp, " (on left ");
+ if(obj->owornmask & W_RING) {
+ Strcat(bp, body_part(HAND));
+ Strcat(bp, ")");
+ }
+ if(known && objects[obj->otyp].oc_charged) {
+ Strcat(prefix, sitoa(obj->spe));
+ Strcat(prefix, " ");
+ }
+ break;
+ case FOOD_CLASS:
+ if (obj->oeaten)
+ Strcat(prefix, "partly eaten ");
+ if (obj->otyp == CORPSE) {
+ Sprintf(prefix, "%s ",
+ corpse_xname(obj, prefix,
+ CXN_ARTICLE|CXN_NOCORPSE));
+ } else if (obj->otyp == EGG) {
#if 0 /* corpses don't tell if they're stale either */
- if (known && stale_egg(obj))
- Strcat(prefix, "stale ");
+ if (known && stale_egg(obj))
+ Strcat(prefix, "stale ");
#endif
- if (omndx >= LOW_PM && (known ||
- (mvitals[omndx].mvflags & MV_KNOWS_EGG))) {
- Strcat(prefix, mons[omndx].mname);
- Strcat(prefix, " ");
- if (obj->spe)
- Strcat(bp, " (laid by you)");
- }
- }
- if (obj->otyp == MEAT_RING) goto ring;
- break;
- case BALL_CLASS:
- case CHAIN_CLASS:
- add_erosion_words(obj, prefix);
- if(obj->owornmask & W_BALL)
- Strcat(bp, " (chained to you)");
- break;
- }
-
- if((obj->owornmask & W_WEP) && !mrg_to_wielded) {
- if (obj->quan != 1L) {
- Strcat(bp, " (wielded)");
- } else {
- const char *hand_s = body_part(HAND);
-
- if (bimanual(obj)) hand_s = makeplural(hand_s);
- Sprintf(eos(bp), " (weapon in %s)", hand_s);
- }
- }
- if(obj->owornmask & W_SWAPWEP) {
- if (u.twoweap)
- Sprintf(eos(bp), " (wielded in other %s)",
- body_part(HAND));
- else
- Strcat(bp, " (alternate weapon; not wielded)");
- }
- if(obj->owornmask & W_QUIVER){
- switch(obj->oclass){
- case WEAPON_CLASS:
- if(is_ammo(obj)){
- if(objects[obj->otyp].oc_skill == -P_BOW){
- /* Ammo for a bow */
- Strcat(bp, " (in quiver)");
- break;
- } else {
- /* Ammo not for a bow */
- Strcat(bp, " (in quiver pouch)");
- break;
- }
- } else {
- /* Weapons not considered ammo */
- Strcat(bp, " (at the ready)");
- break;
- }
-
- /* Small things and ammo not for a bow */
- case RING_CLASS:
- case AMULET_CLASS:
- case WAND_CLASS:
- case COIN_CLASS:
- case GEM_CLASS:
- Strcat(bp, " (in quiver pouch)");
- break;
- default: /* odd things */
- Strcat(bp, " (at the ready)");
- }
- }
- if (!iflags.suppress_price && is_unpaid(obj)) {
- long quotedprice = unpaid_cost(obj, TRUE);
-
- Sprintf(eos(bp), " (%s, %ld %s)",
- obj->unpaid ? "unpaid" : "contents",
- quotedprice, currency(quotedprice));
- }
- if (!strncmp(prefix, "a ", 2) &&
- index(vowels, *(prefix+2) ? *(prefix+2) : *bp)
- && (*(prefix+2) || (strncmp(bp, "uranium", 7)
- && strncmp(bp, "unicorn", 7)
- && strncmp(bp, "eucalyptus", 10)))) {
- Strcpy(tmpbuf, prefix);
- Strcpy(prefix, "an ");
- Strcpy(prefix+3, tmpbuf+2);
- }
- bp = strprepend(bp, prefix);
- return(bp);
+ if (omndx >= LOW_PM && (known ||
+ (mvitals[omndx].mvflags & MV_KNOWS_EGG))) {
+ Strcat(prefix, mons[omndx].mname);
+ Strcat(prefix, " ");
+ if (obj->spe)
+ Strcat(bp, " (laid by you)");
+ }
+ }
+ if (wizard) {
+ Sprintf(eos(bp), " (%d aum)", obj->owt);
+ }
+ if (obj->otyp == MEAT_RING) goto ring;
+ break;
+ case BALL_CLASS:
+ case CHAIN_CLASS:
+ add_erosion_words(obj, prefix);
+ if(obj->owornmask & W_BALL)
+ Strcat(bp, " (chained to you)");
+ break;
+ }
+
+ if((obj->owornmask & W_WEP) && !mrg_to_wielded) {
+ if (obj->quan != 1L) {
+ Strcat(bp, " (wielded)");
+ } else {
+ const char *hand_s = body_part(HAND);
+
+ if (bimanual(obj)) hand_s = makeplural(hand_s);
+ Sprintf(eos(bp), " (weapon in %s)", hand_s);
+ }
+ }
+ if(obj->owornmask & W_SWAPWEP) {
+ if (u.twoweap)
+ Sprintf(eos(bp), " (wielded in other %s)",
+ body_part(HAND));
+ else
+ Strcat(bp, " (alternate weapon; not wielded)");
+ }
+ if(obj->owornmask & W_QUIVER){
+ switch(obj->oclass){
+ case WEAPON_CLASS:
+ if(is_ammo(obj)){
+ if(objects[obj->otyp].oc_skill == -P_BOW){
+ /* Ammo for a bow */
+ Strcat(bp, " (in quiver)");
+ break;
+ } else {
+ /* Ammo not for a bow */
+ Strcat(bp, " (in quiver pouch)");
+ break;
+ }
+ } else {
+ /* Weapons not considered ammo */
+ Strcat(bp, " (at the ready)");
+ break;
+ }
+
+ /* Small things and ammo not for a bow */
+ case RING_CLASS:
+ case AMULET_CLASS:
+ case WAND_CLASS:
+ case COIN_CLASS:
+ case GEM_CLASS:
+ Strcat(bp, " (in quiver pouch)");
+ break;
+ default: /* odd things */
+ Strcat(bp, " (at the ready)");
+ }
+ }
+ if (!iflags.suppress_price && is_unpaid(obj)) {
+ long quotedprice = unpaid_cost(obj, TRUE);
+
+ Sprintf(eos(bp), " (%s, %ld %s)",
+ obj->unpaid ? "unpaid" : "contents",
+ quotedprice, currency(quotedprice));
+ }
+ if (!strncmp(prefix, "a ", 2) &&
+ index(vowels, *(prefix+2) ? *(prefix+2) : *bp)
+ && (*(prefix+2) || (strncmp(bp, "uranium", 7)
+ && strncmp(bp, "unicorn", 7)
+ && strncmp(bp, "eucalyptus", 10)))) {
+ Strcpy(tmpbuf, prefix);
+ Strcpy(prefix, "an ");
+ Strcpy(prefix+3, tmpbuf+2);
+ }
+ bp = strprepend(bp, prefix);
+ return(bp);
}
/* used from invent.c */
/* check fundamental ID hallmarks first */
if (!otmp->known || !otmp->dknown ||
#ifdef MAIL
- (!otmp->bknown && otmp->otyp != SCR_MAIL) ||
+ (!otmp->bknown && otmp->otyp != SCR_MAIL) ||
#else
- !otmp->bknown ||
+ !otmp->bknown ||
#endif
- !objects[otmp->otyp].oc_name_known)
- return TRUE;
+ !objects[otmp->otyp].oc_name_known)
+ return TRUE;
if ((!otmp->cknown && (Is_container(otmp) || otmp->otyp == STATUE)) ||
- (!otmp->lknown && Is_box(otmp)))
- return TRUE;
+ (!otmp->lknown && Is_box(otmp)))
+ return TRUE;
if (otmp->oartifact && undiscovered_artifact(otmp->oartifact))
- return TRUE;
+ return TRUE;
/* otmp->rknown is the only item of interest if we reach here */
/*
- * Note: if a revision ever allows scrolls to become fireproof or
- * rings to become shockproof, this checking will need to be revised.
- * `rknown' ID only matters if xname() will provide the info about it.
- */
+ * Note: if a revision ever allows scrolls to become fireproof or
+ * rings to become shockproof, this checking will need to be revised.
+ * `rknown' ID only matters if xname() will provide the info about it.
+ */
if (otmp->rknown || (otmp->oclass != ARMOR_CLASS &&
- otmp->oclass != WEAPON_CLASS &&
- !is_weptool(otmp) && /* (redunant) */
- otmp->oclass != BALL_CLASS)) /* (useless) */
- return FALSE;
+ otmp->oclass != WEAPON_CLASS &&
+ !is_weptool(otmp) && /* (redunant) */
+ otmp->oclass != BALL_CLASS)) /* (useless) */
+ return FALSE;
else /* lack of `rknown' only matters for vulnerable objects */
- return (boolean)(is_rustprone(otmp) ||
- is_corrodeable(otmp) ||
- is_flammable(otmp));
+ return (boolean)(is_rustprone(otmp) ||
+ is_corrodeable(otmp) ||
+ is_flammable(otmp));
}
char *
const char *adjective;
unsigned cxn_flags; /* bitmask of CXN_xxx values */
{
- char *nambuf = nextobuf();
- int omndx = otmp->corpsenm;
- boolean ignore_quan = (cxn_flags & CXN_SINGULAR) != 0,
- /* suppress "the" from "the unique monster corpse" */
- no_prefix = (cxn_flags & CXN_NO_PFX) != 0,
- /* include "the" for "the woodchuck corpse */
- the_prefix = (cxn_flags & CXN_PFX_THE) != 0,
- /* include "an" for "an ogre corpse */
- any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
- /* leave off suffix (do_name() appends "corpse" itself) */
- omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
- possessive = FALSE;
- const char *mname;
-
- if (omndx == NON_PM) { /* paranoia */
- mname = "thing";
- /* [Possible enhancement: check whether corpse has monster traits
- attached in order to use priestname() for priests and minions.] */
- } else if (omndx == PM_ALIGNED_PRIEST) {
- /* avoid "aligned priest"; it just exposes internal details */
- mname = "priest";
- } else {
- mname = mons[omndx].mname;
- if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) {
- mname = s_suffix(mname);
- possessive = TRUE;
- /* don't precede personal name like "Medusa" with an article */
- if (type_is_pname(&mons[omndx]))
- no_prefix = TRUE;
- /* always precede non-personal unique monster name like
- "Oracle" with "the" unless explicitly overridden */
- else if (the_unique_pm(&mons[omndx]) && !no_prefix)
- the_prefix = TRUE;
- }
- }
- if (no_prefix) the_prefix = any_prefix = FALSE;
- else if (the_prefix) any_prefix = FALSE; /* mutually exclusive */
-
- *nambuf = '\0';
- /* can't use the() the way we use an() below because any capitalized
- Name causes it to assume a personal name and return Name as-is;
- that's usually the behavior wanted, but here we need to force "the"
- to precede capitalized unique monsters (pnames are handled above) */
- if (the_prefix) Strcat(nambuf, "the ");
-
- if (!adjective || !*adjective) {
- /* normal case: newt corpse */
- Strcat(nambuf, mname);
- } else {
- /* adjective positioning depends upon format of monster name */
- if (possessive) /* Medusa's cursed partly eaten corpse */
- Sprintf(eos(nambuf), "%s %s", mname, adjective);
- else /* cursed partly eaten troll corpse */
- Sprintf(eos(nambuf), "%s %s", adjective, mname);
- /* in case adjective has a trailing space, squeeze it out */
- mungspaces(nambuf);
- /* doname() might include a count in the adjective argument;
- if so, don't prepend an article */
- if (digit(*adjective)) any_prefix = FALSE;
- }
-
- if (!omit_corpse) {
- Strcat(nambuf, " corpse");
- /* makeplural(nambuf) => append "s" to "corpse" */
- if (otmp->quan > 1L && !ignore_quan) {
- Strcat(nambuf, "s");
- any_prefix = FALSE; /* avoid "a newt corpses" */
- }
- }
-
- /* it's safe to overwrite our nambuf after an() has copied
- its old value into another buffer */
- if (any_prefix) Strcpy(nambuf, an(nambuf));
-
- return nambuf;
+ char *nambuf = nextobuf();
+ int omndx = otmp->corpsenm;
+ boolean ignore_quan = (cxn_flags & CXN_SINGULAR) != 0,
+ /* suppress "the" from "the unique monster corpse" */
+ no_prefix = (cxn_flags & CXN_NO_PFX) != 0,
+ /* include "the" for "the woodchuck corpse */
+ the_prefix = (cxn_flags & CXN_PFX_THE) != 0,
+ /* include "an" for "an ogre corpse */
+ any_prefix = (cxn_flags & CXN_ARTICLE) != 0,
+ /* leave off suffix (do_name() appends "corpse" itself) */
+ omit_corpse = (cxn_flags & CXN_NOCORPSE) != 0,
+ possessive = FALSE;
+ const char *mname;
+
+ if (omndx == NON_PM) { /* paranoia */
+ mname = "thing";
+ /* [Possible enhancement: check whether corpse has monster traits
+ attached in order to use priestname() for priests and minions.] */
+ } else if (omndx == PM_ALIGNED_PRIEST) {
+ /* avoid "aligned priest"; it just exposes internal details */
+ mname = "priest";
+ } else {
+ mname = mons[omndx].mname;
+ if (the_unique_pm(&mons[omndx]) || type_is_pname(&mons[omndx])) {
+ mname = s_suffix(mname);
+ possessive = TRUE;
+ /* don't precede personal name like "Medusa" with an article */
+ if (type_is_pname(&mons[omndx]))
+ no_prefix = TRUE;
+ /* always precede non-personal unique monster name like
+ "Oracle" with "the" unless explicitly overridden */
+ else if (the_unique_pm(&mons[omndx]) && !no_prefix)
+ the_prefix = TRUE;
+ }
+ }
+ if (no_prefix) the_prefix = any_prefix = FALSE;
+ else if (the_prefix) any_prefix = FALSE; /* mutually exclusive */
+
+ *nambuf = '\0';
+ /* can't use the() the way we use an() below because any capitalized
+ Name causes it to assume a personal name and return Name as-is;
+ that's usually the behavior wanted, but here we need to force "the"
+ to precede capitalized unique monsters (pnames are handled above) */
+ if (the_prefix) Strcat(nambuf, "the ");
+
+ if (!adjective || !*adjective) {
+ /* normal case: newt corpse */
+ Strcat(nambuf, mname);
+ } else {
+ /* adjective positioning depends upon format of monster name */
+ if (possessive) /* Medusa's cursed partly eaten corpse */
+ Sprintf(eos(nambuf), "%s %s", mname, adjective);
+ else /* cursed partly eaten troll corpse */
+ Sprintf(eos(nambuf), "%s %s", adjective, mname);
+ /* in case adjective has a trailing space, squeeze it out */
+ mungspaces(nambuf);
+ /* doname() might include a count in the adjective argument;
+ if so, don't prepend an article */
+ if (digit(*adjective)) any_prefix = FALSE;
+ }
+
+ if (!omit_corpse) {
+ Strcat(nambuf, " corpse");
+ /* makeplural(nambuf) => append "s" to "corpse" */
+ if (otmp->quan > 1L && !ignore_quan) {
+ Strcat(nambuf, "s");
+ any_prefix = FALSE; /* avoid "a newt corpses" */
+ }
+ }
+
+ /* it's safe to overwrite our nambuf after an() has copied
+ its old value into another buffer */
+ if (any_prefix) Strcpy(nambuf, an(nambuf));
+
+ return nambuf;
}
/* xname doesn't include monster type for "corpse"; cxname does */
cxname(obj)
struct obj *obj;
{
- if (obj->otyp == CORPSE)
- return corpse_xname(obj, (const char *)0, CXN_NORMAL);
- return xname(obj);
+ if (obj->otyp == CORPSE)
+ return corpse_xname(obj, (const char *)0, CXN_NORMAL);
+ return xname(obj);
}
/* treat an object as fully ID'd when it might be used as reason for death */
/* format the object */
if (obj->otyp == CORPSE) {
- buf = nextobuf();
- Strcpy(buf, corpse_xname(obj, (const char *)0, CXN_NORMAL));
+ buf = nextobuf();
+ Strcpy(buf, corpse_xname(obj, (const char *)0, CXN_NORMAL));
} else if (obj->otyp == SLIME_MOLD) {
- /* concession to "most unique deaths competition" in the annual
- devnull tournament, suppress player supplied fruit names because
- those can be used to fake other objects and dungeon features */
- buf = nextobuf();
- Sprintf(buf, "deadly slime mold%s", plur(obj->quan));
+ /* concession to "most unique deaths competition" in the annual
+ devnull tournament, suppress player supplied fruit names because
+ those can be used to fake other objects and dungeon features */
+ buf = nextobuf();
+ Sprintf(buf, "deadly slime mold%s", plur(obj->quan));
} else {
- buf = xname(obj);
+ buf = xname(obj);
}
/* apply an article if appropriate; caller should always use KILLED_BY */
if (obj->quan == 1L && !strstri(buf, "'s ") && !strstri(buf, "s' "))
- buf = (obj_is_pname(obj) || the_unique_obj(obj)) ? the(buf) : an(buf);
+ buf = (obj_is_pname(obj) || the_unique_obj(obj)) ? the(buf) : an(buf);
objects[obj->otyp].oc_name_known = save_ocknown;
objects[obj->otyp].oc_uname = save_ocuname;
{
struct obj save_obj;
char unamebuf[12], onamebuf[12],
- *save_oname, *save_uname, *outbuf;
+ *save_oname, *save_uname, *outbuf;
outbuf = (*func)(obj);
if ((unsigned)strlen(outbuf) <= lenlimit) return outbuf;
/* shorten called string to fairly small amount */
save_uname = objects[obj->otyp].oc_uname;
if (save_uname && strlen(save_uname) >= sizeof unamebuf) {
- (void) strncpy(unamebuf, save_uname, sizeof unamebuf - 4);
- Strcpy(unamebuf + sizeof unamebuf - 4, "...");
- objects[obj->otyp].oc_uname = unamebuf;
- releaseobuf(outbuf);
- outbuf = (*func)(obj);
- objects[obj->otyp].oc_uname = save_uname; /* restore called string */
- if ((unsigned)strlen(outbuf) <= lenlimit) return outbuf;
+ (void) strncpy(unamebuf, save_uname, sizeof unamebuf - 4);
+ Strcpy(unamebuf + sizeof unamebuf - 4, "...");
+ objects[obj->otyp].oc_uname = unamebuf;
+ releaseobuf(outbuf);
+ outbuf = (*func)(obj);
+ objects[obj->otyp].oc_uname = save_uname; /* restore called string */
+ if ((unsigned)strlen(outbuf) <= lenlimit) return outbuf;
}
/* shorten named string to fairly small amount */
save_oname = has_oname(obj) ? ONAME(obj) : 0;
if (save_oname && strlen(save_oname) >= sizeof onamebuf) {
- (void) strncpy(onamebuf, save_oname, sizeof onamebuf - 4);
- Strcpy(onamebuf + sizeof onamebuf - 4, "...");
- ONAME(obj) = onamebuf;
- releaseobuf(outbuf);
- outbuf = (*func)(obj);
- ONAME(obj) = save_oname; /* restore named string */
- if ((unsigned)strlen(outbuf) <= lenlimit) return outbuf;
+ (void) strncpy(onamebuf, save_oname, sizeof onamebuf - 4);
+ Strcpy(onamebuf + sizeof onamebuf - 4, "...");
+ ONAME(obj) = onamebuf;
+ releaseobuf(outbuf);
+ outbuf = (*func)(obj);
+ ONAME(obj) = save_oname; /* restore named string */
+ if ((unsigned)strlen(outbuf) <= lenlimit) return outbuf;
}
/* shorten both called and named strings;
unamebuf and onamebuf have both already been populated */
if (save_uname && strlen(save_uname) >= sizeof unamebuf &&
- save_oname && strlen(save_oname) >= sizeof onamebuf) {
- objects[obj->otyp].oc_uname = unamebuf;
- ONAME(obj) = onamebuf;
- releaseobuf(outbuf);
- outbuf = (*func)(obj);
- if ((unsigned)strlen(outbuf) <= lenlimit) {
- objects[obj->otyp].oc_uname = save_uname;
- ONAME(obj) = save_oname;
- return outbuf;
- }
+ save_oname && strlen(save_oname) >= sizeof onamebuf) {
+ objects[obj->otyp].oc_uname = unamebuf;
+ ONAME(obj) = onamebuf;
+ releaseobuf(outbuf);
+ outbuf = (*func)(obj);
+ if ((unsigned)strlen(outbuf) <= lenlimit) {
+ objects[obj->otyp].oc_uname = save_uname;
+ ONAME(obj) = save_oname;
+ return outbuf;
+ }
}
/* still long; strip several name-lengthening attributes;
releaseobuf(outbuf);
outbuf = (*func)(obj);
if (altfunc && (unsigned)strlen(outbuf) > lenlimit) {
- /* still long; use the alternate function (usually one of
- the jackets around minimal_xname()) */
- releaseobuf(outbuf);
- outbuf = (*altfunc)(obj);
+ /* still long; use the alternate function (usually one of
+ the jackets around minimal_xname()) */
+ releaseobuf(outbuf);
+ outbuf = (*altfunc)(obj);
}
/* restore the object */
*obj = save_obj;
register struct obj *otmp;
char *FDECL((*func), (OBJ_P));
{
- long savequan;
- char *nam;
+ long savequan;
+ char *nam;
- /* using xname for corpses does not give the monster type */
- if (otmp->otyp == CORPSE && func == xname) func = cxname;
+ /* using xname for corpses does not give the monster type */
+ if (otmp->otyp == CORPSE && func == xname) func = cxname;
- savequan = otmp->quan;
- otmp->quan = 1L;
- nam = (*func)(otmp);
- otmp->quan = savequan;
- return nam;
+ savequan = otmp->quan;
+ otmp->quan = 1L;
+ nam = (*func)(otmp);
+ otmp->quan = savequan;
+ return nam;
}
char *
an(str)
register const char *str;
{
- char *buf = nextobuf();
-
- buf[0] = '\0';
-
- if (strncmpi(str, "the ", 4) &&
- strcmp(str, "molten lava") &&
- strcmp(str, "iron bars") &&
- strcmp(str, "ice")) {
- if (index(vowels, *str) &&
- strncmp(str, "one-", 4) &&
- strncmp(str, "useful", 6) &&
- strncmp(str, "unicorn", 7) &&
- strncmp(str, "uranium", 7) &&
- strncmp(str, "eucalyptus", 10))
- Strcpy(buf, "an ");
- else
- Strcpy(buf, "a ");
- }
-
- Strcat(buf, str);
- return buf;
+ char *buf = nextobuf();
+
+ buf[0] = '\0';
+
+ if (strncmpi(str, "the ", 4) &&
+ strcmp(str, "molten lava") &&
+ strcmp(str, "iron bars") &&
+ strcmp(str, "ice")) {
+ if (index(vowels, *str) &&
+ strncmp(str, "one-", 4) &&
+ strncmp(str, "useful", 6) &&
+ strncmp(str, "unicorn", 7) &&
+ strncmp(str, "uranium", 7) &&
+ strncmp(str, "eucalyptus", 10))
+ Strcpy(buf, "an ");
+ else
+ Strcpy(buf, "a ");
+ }
+
+ Strcat(buf, str);
+ return buf;
}
char *
An(str)
const char *str;
{
- register char *tmp = an(str);
- *tmp = highc(*tmp);
- return tmp;
+ register char *tmp = an(str);
+ *tmp = highc(*tmp);
+ return tmp;
}
/*
the(str)
const char *str;
{
- char *buf = nextobuf();
- boolean insert_the = FALSE;
-
- if (!strncmpi(str, "the ", 4)) {
- buf[0] = lowc(*str);
- Strcpy(&buf[1], str+1);
- return buf;
- } else if (*str < 'A' || *str > 'Z') {
- /* not a proper name, needs an article */
- insert_the = TRUE;
- } else {
- /* Probably a proper name, might not need an article */
- register char *tmp, *named, *called;
- int l;
-
- /* some objects have capitalized adjectives in their names */
- if(((tmp = rindex(str, ' ')) || (tmp = rindex(str, '-'))) &&
- (tmp[1] < 'A' || tmp[1] > 'Z'))
- insert_the = TRUE;
- else if (tmp && index(str, ' ') < tmp) { /* has spaces */
- /* it needs an article if the name contains "of" */
- tmp = strstri(str, " of ");
- named = strstri(str, " named ");
- called = strstri(str, " called ");
- if (called && (!named || called < named)) named = called;
-
- if (tmp && (!named || tmp < named)) /* found an "of" */
- insert_the = TRUE;
- /* stupid special case: lacks "of" but needs "the" */
- else if (!named && (l = strlen(str)) >= 31 &&
- !strcmp(&str[l - 31], "Platinum Yendorian Express Card"))
- insert_the = TRUE;
- }
- }
- if (insert_the)
- Strcpy(buf, "the ");
- else
- buf[0] = '\0';
- Strcat(buf, str);
-
- return buf;
+ char *buf = nextobuf();
+ boolean insert_the = FALSE;
+
+ if (!strncmpi(str, "the ", 4)) {
+ buf[0] = lowc(*str);
+ Strcpy(&buf[1], str+1);
+ return buf;
+ } else if (*str < 'A' || *str > 'Z') {
+ /* not a proper name, needs an article */
+ insert_the = TRUE;
+ } else {
+ /* Probably a proper name, might not need an article */
+ register char *tmp, *named, *called;
+ int l;
+
+ /* some objects have capitalized adjectives in their names */
+ if(((tmp = rindex(str, ' ')) || (tmp = rindex(str, '-'))) &&
+ (tmp[1] < 'A' || tmp[1] > 'Z'))
+ insert_the = TRUE;
+ else if (tmp && index(str, ' ') < tmp) { /* has spaces */
+ /* it needs an article if the name contains "of" */
+ tmp = strstri(str, " of ");
+ named = strstri(str, " named ");
+ called = strstri(str, " called ");
+ if (called && (!named || called < named)) named = called;
+
+ if (tmp && (!named || tmp < named)) /* found an "of" */
+ insert_the = TRUE;
+ /* stupid special case: lacks "of" but needs "the" */
+ else if (!named && (l = strlen(str)) >= 31 &&
+ !strcmp(&str[l - 31], "Platinum Yendorian Express Card"))
+ insert_the = TRUE;
+ }
+ }
+ if (insert_the)
+ Strcpy(buf, "the ");
+ else
+ buf[0] = '\0';
+ Strcat(buf, str);
+
+ return buf;
}
char *
register struct obj *otmp;
register const char *verb;
{
- register char *bp = cxname(otmp);
- char prefix[PREFIX];
-
- if(otmp->quan != 1L) {
- Sprintf(prefix, "%ld ", otmp->quan);
- bp = strprepend(bp, prefix);
- }
-
- if(verb) {
- Strcat(bp, " ");
- Strcat(bp, otense(otmp, verb));
- }
- return(bp);
+ register char *bp = cxname(otmp);
+ char prefix[PREFIX];
+
+ if(otmp->quan != 1L) {
+ Sprintf(prefix, "%ld ", otmp->quan);
+ bp = strprepend(bp, prefix);
+ }
+
+ if(verb) {
+ Strcat(bp, " ");
+ Strcat(bp, otense(otmp, verb));
+ }
+ return(bp);
}
/* combine yname and aobjnam eg "your count cxname(otmp)" */
struct obj *obj;
const char *verb;
{
- char *s = aobjnam(obj, verb);
+ char *s = aobjnam(obj, verb);
- /* leave off "your" for most of your artifacts, but prepend
- * "your" for unique objects and "foo of bar" quest artifacts */
- if (!carried(obj) || !obj_is_pname(obj) ||
- obj->oartifact >= ART_ORB_OF_DETECTION) {
- char *outbuf = shk_your(nextobuf(), obj);
- int space_left = BUFSZ - 1 - strlen(outbuf);
+ /* leave off "your" for most of your artifacts, but prepend
+ * "your" for unique objects and "foo of bar" quest artifacts */
+ if (!carried(obj) || !obj_is_pname(obj) ||
+ obj->oartifact >= ART_ORB_OF_DETECTION) {
+ char *outbuf = shk_your(nextobuf(), obj);
+ int space_left = BUFSZ - 1 - strlen(outbuf);
- s = strncat(outbuf, s, space_left);
- }
+ s = strncat(outbuf, s, space_left);
+ }
- return s;
+ return s;
}
/* combine Yname2 and aobjnam eg "Your count cxname(otmp)" */
struct obj *obj;
const char *verb;
{
- register char *s = yobjnam(obj,verb);
+ register char *s = yobjnam(obj,verb);
- *s = highc(*s);
- return(s);
+ *s = highc(*s);
+ return(s);
}
/* like aobjnam, but prepend "The", not count, and use xname */
register struct obj *otmp;
register const char *verb;
{
- char *bp = The(xname(otmp));
+ char *bp = The(xname(otmp));
- if(verb) {
- Strcat(bp, " ");
- Strcat(bp, otense(otmp, verb));
- }
- return(bp);
+ if(verb) {
+ Strcat(bp, " ");
+ Strcat(bp, otense(otmp, verb));
+ }
+ return(bp);
}
/* capitalized variant of doname() */
Doname2(obj)
register struct obj *obj;
{
- register char *s = doname(obj);
+ register char *s = doname(obj);
- *s = highc(*s);
- return(s);
+ *s = highc(*s);
+ return(s);
}
/* returns "[your ]xname(obj)" or "Foobar's xname(obj)" or "the xname(obj)" */
yname(obj)
struct obj *obj;
{
- char *s = cxname(obj);
+ char *s = cxname(obj);
- /* leave off "your" for most of your artifacts, but prepend
- * "your" for unique objects and "foo of bar" quest artifacts */
- if (!carried(obj) || !obj_is_pname(obj) ||
- obj->oartifact >= ART_ORB_OF_DETECTION) {
- char *outbuf = shk_your(nextobuf(), obj);
- int space_left = BUFSZ - 1 - strlen(outbuf);
+ /* leave off "your" for most of your artifacts, but prepend
+ * "your" for unique objects and "foo of bar" quest artifacts */
+ if (!carried(obj) || !obj_is_pname(obj) ||
+ obj->oartifact >= ART_ORB_OF_DETECTION) {
+ char *outbuf = shk_your(nextobuf(), obj);
+ int space_left = BUFSZ - 1 - strlen(outbuf);
- s = strncat(outbuf, s, space_left);
- }
+ s = strncat(outbuf, s, space_left);
+ }
- return s;
+ return s;
}
/* capitalized variant of yname() */
Yname2(obj)
struct obj *obj;
{
- char *s = yname(obj);
+ char *s = yname(obj);
- *s = highc(*s);
- return s;
+ *s = highc(*s);
+ return s;
}
/* returns "your minimal_xname(obj)"
ysimple_name(obj)
struct obj *obj;
{
- char *outbuf = nextobuf();
- char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
- int space_left = BUFSZ - 1 - strlen(s);
+ char *outbuf = nextobuf();
+ char *s = shk_your(outbuf, obj); /* assert( s == outbuf ); */
+ int space_left = BUFSZ - 1 - strlen(s);
- return strncat(s, minimal_xname(obj), space_left);
+ return strncat(s, minimal_xname(obj), space_left);
}
/* capitalized variant of ysimple_name() */
Ysimple_name2(obj)
struct obj *obj;
{
- char *s = ysimple_name(obj);
+ char *s = ysimple_name(obj);
- *s = highc(*s);
- return s;
+ *s = highc(*s);
+ return s;
}
/* "scroll" or "scrolls" */
simpleonames(obj)
struct obj *obj;
{
- char *simpleoname = minimal_xname(obj);
+ char *simpleoname = minimal_xname(obj);
- if (obj->quan != 1L) simpleoname = makeplural(simpleoname);
- return simpleoname;
+ if (obj->quan != 1L) simpleoname = makeplural(simpleoname);
+ return simpleoname;
}
/* "a scroll" or "scrolls"; "a silver bell" or "the Bell of Opening" */
ansimpleoname(obj)
struct obj *obj;
{
- char *simpleoname = simpleonames(obj);
- int otyp = obj->otyp;
-
- /* prefix with "the" if a unique item, or a fake one imitating same,
- has been formatted with its actual name (we let typename() handle
- any `known' and `dknown' checking necessary) */
- if (otyp == FAKE_AMULET_OF_YENDOR) otyp = AMULET_OF_YENDOR;
- if (objects[otyp].oc_unique &&
- !strcmp(simpleoname, OBJ_NAME(objects[otyp])))
- return the(simpleoname);
-
- /* simpleoname is singular if quan==1, plural otherwise */
- if (obj->quan == 1L) simpleoname = an(simpleoname);
- return simpleoname;
+ char *simpleoname = simpleonames(obj);
+ int otyp = obj->otyp;
+
+ /* prefix with "the" if a unique item, or a fake one imitating same,
+ has been formatted with its actual name (we let typename() handle
+ any `known' and `dknown' checking necessary) */
+ if (otyp == FAKE_AMULET_OF_YENDOR) otyp = AMULET_OF_YENDOR;
+ if (objects[otyp].oc_unique &&
+ !strcmp(simpleoname, OBJ_NAME(objects[otyp])))
+ return the(simpleoname);
+
+ /* simpleoname is singular if quan==1, plural otherwise */
+ if (obj->quan == 1L) simpleoname = an(simpleoname);
+ return simpleoname;
}
/* "the scroll" or "the scrolls" */
thesimpleoname(obj)
struct obj *obj;
{
- char *simpleoname = simpleonames(obj);
+ char *simpleoname = simpleonames(obj);
- return the(simpleoname);
+ return the(simpleoname);
}
/* artifact's name without any object type or known/dknown/&c feedback */
bare_artifactname(obj)
struct obj *obj;
{
- char *outbuf;
-
- if (obj->oartifact) {
- outbuf = nextobuf();
- Strcpy(outbuf, artiname(obj->oartifact));
- if (!strncmp(outbuf, "The ", 4)) outbuf[0] = lowc(outbuf[0]);
- } else {
- outbuf = xname(obj);
- }
- return outbuf;
+ char *outbuf;
+
+ if (obj->oartifact) {
+ outbuf = nextobuf();
+ Strcpy(outbuf, artiname(obj->oartifact));
+ if (!strncmp(outbuf, "The ", 4)) outbuf[0] = lowc(outbuf[0]);
+ } else {
+ outbuf = xname(obj);
+ }
+ return outbuf;
}
static const char *wrp[] = {
- "wand", "ring", "potion", "scroll", "gem", "amulet",
- "spellbook", "spell book",
- /* for non-specific wishes */
- "weapon", "armor", "tool", "food", "comestible",
+ "wand", "ring", "potion", "scroll", "gem", "amulet",
+ "spellbook", "spell book",
+ /* for non-specific wishes */
+ "weapon", "armor", "tool", "food", "comestible",
};
static const char wrpsym[] = {
- WAND_CLASS, RING_CLASS, POTION_CLASS, SCROLL_CLASS, GEM_CLASS,
- AMULET_CLASS, SPBOOK_CLASS, SPBOOK_CLASS,
- WEAPON_CLASS, ARMOR_CLASS, TOOL_CLASS, FOOD_CLASS,
- FOOD_CLASS
+ WAND_CLASS, RING_CLASS, POTION_CLASS, SCROLL_CLASS, GEM_CLASS,
+ AMULET_CLASS, SPBOOK_CLASS, SPBOOK_CLASS,
+ WEAPON_CLASS, ARMOR_CLASS, TOOL_CLASS, FOOD_CLASS,
+ FOOD_CLASS
};
/* return form of the verb (input plural) if xname(otmp) were the subject */
* recomputing xname(otmp) at this time.
*/
if (!is_plural(otmp))
- return vtense((char *)0, verb);
+ return vtense((char *)0, verb);
buf = nextobuf();
Strcpy(buf, verb);
/* various singular words that vtense would otherwise categorize as plural;
also used by makesingular() to catch some special cases */
static const char * const special_subjs[] = {
- "erinys",
- "manes", /* this one is ambiguous */
- "Cyclops",
- "Hippocrates",
- "Pelias",
- "aklys",
- "amnesia",
- "detect monsters",
- "paralysis",
- "shape changers",
- "nemesis",
- 0
- /* note: "detect monsters" and "shape changers" are normally
- caught via "<something>(s) of <whatever>", but they can be
- wished for using the shorter form, so we include them here
- to accomodate usage by makesingular during wishing */
+ "erinys",
+ "manes", /* this one is ambiguous */
+ "Cyclops",
+ "Hippocrates",
+ "Pelias",
+ "aklys",
+ "amnesia",
+ "detect monsters",
+ "paralysis",
+ "shape changers",
+ "nemesis",
+ 0
+ /* note: "detect monsters" and "shape changers" are normally
+ caught via "<something>(s) of <whatever>", but they can be
+ wished for using the shorter form, so we include them here
+ to accomodate usage by makesingular during wishing */
};
/* return form of the verb (input plural) for present tense 3rd person subj */
* present tense form so we don't duplicate this code elsewhere.
*/
if (subj) {
- if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
- goto sing;
- spot = (const char *)0;
- for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
- if (!strncmpi(sp, " of ", 4) ||
- !strncmpi(sp, " from ", 6) ||
- !strncmpi(sp, " called ", 8) ||
- !strncmpi(sp, " named ", 7) ||
- !strncmpi(sp, " labeled ", 9)) {
- if (sp != subj) spot = sp - 1;
- break;
- }
- }
- len = (int) strlen(subj);
- if (!spot) spot = subj + len - 1;
-
- /*
- * plural: anything that ends in 's', but not '*us' or '*ss'.
- * Guess at a few other special cases that makeplural creates.
- */
- if ((lowc(*spot) == 's' && spot != subj &&
- !index("us", lowc(*(spot-1)))) ||
- !BSTRNCMPI(subj, spot-3, "eeth", 4) ||
- !BSTRNCMPI(subj, spot-3, "feet", 4) ||
- !BSTRNCMPI(subj, spot-1, "ia", 2) ||
- !BSTRNCMPI(subj, spot-1, "ae", 2)) {
- /* check for special cases to avoid false matches */
- len = (int)(spot - subj) + 1;
- for (spec = special_subjs; *spec; spec++) {
- ltmp = strlen(*spec);
- if (len == ltmp && !strncmpi(*spec, subj, len)) goto sing;
- /* also check for <prefix><space><special_subj>
- to catch things like "the invisible erinys" */
- if (len > ltmp && *(spot - ltmp) == ' ' &&
- !strncmpi(*spec, spot - ltmp + 1, ltmp)) goto sing;
- }
-
- return strcpy(buf, verb);
- }
- /*
- * 3rd person plural doesn't end in telltale 's';
- * 2nd person singular behaves as if plural.
- */
- if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
- return strcpy(buf, verb);
+ if (!strncmpi(subj, "a ", 2) || !strncmpi(subj, "an ", 3))
+ goto sing;
+ spot = (const char *)0;
+ for (sp = subj; (sp = index(sp, ' ')) != 0; ++sp) {
+ if (!strncmpi(sp, " of ", 4) ||
+ !strncmpi(sp, " from ", 6) ||
+ !strncmpi(sp, " called ", 8) ||
+ !strncmpi(sp, " named ", 7) ||
+ !strncmpi(sp, " labeled ", 9)) {
+ if (sp != subj) spot = sp - 1;
+ break;
+ }
+ }
+ len = (int) strlen(subj);
+ if (!spot) spot = subj + len - 1;
+
+ /*
+ * plural: anything that ends in 's', but not '*us' or '*ss'.
+ * Guess at a few other special cases that makeplural creates.
+ */
+ if ((lowc(*spot) == 's' && spot != subj &&
+ !index("us", lowc(*(spot-1)))) ||
+ !BSTRNCMPI(subj, spot-3, "eeth", 4) ||
+ !BSTRNCMPI(subj, spot-3, "feet", 4) ||
+ !BSTRNCMPI(subj, spot-1, "ia", 2) ||
+ !BSTRNCMPI(subj, spot-1, "ae", 2)) {
+ /* check for special cases to avoid false matches */
+ len = (int)(spot - subj) + 1;
+ for (spec = special_subjs; *spec; spec++) {
+ ltmp = strlen(*spec);
+ if (len == ltmp && !strncmpi(*spec, subj, len)) goto sing;
+ /* also check for <prefix><space><special_subj>
+ to catch things like "the invisible erinys" */
+ if (len > ltmp && *(spot - ltmp) == ' ' &&
+ !strncmpi(*spec, spot - ltmp + 1, ltmp)) goto sing;
+ }
+
+ return strcpy(buf, verb);
+ }
+ /*
+ * 3rd person plural doesn't end in telltale 's';
+ * 2nd person singular behaves as if plural.
+ */
+ if (!strcmpi(subj, "they") || !strcmpi(subj, "you"))
+ return strcpy(buf, verb);
}
sing:
bspot = buf + len - 1;
if (!strcmpi(buf, "are")) {
- Strcasecpy(buf, "is");
+ Strcasecpy(buf, "is");
} else if (!strcmpi(buf, "have")) {
- Strcasecpy(bspot-1, "s");
+ Strcasecpy(bspot-1, "s");
} else if (index("zxs", lowc(*bspot)) ||
- (len >= 2 && lowc(*bspot) == 'h' &&
- index("cs", lowc(*(bspot-1)))) ||
- (len == 2 && lowc(*bspot) == 'o')) {
- /* Ends in z, x, s, ch, sh; add an "es" */
- Strcasecpy(bspot+1, "es");
+ (len >= 2 && lowc(*bspot) == 'h' &&
+ index("cs", lowc(*(bspot-1)))) ||
+ (len == 2 && lowc(*bspot) == 'o')) {
+ /* Ends in z, x, s, ch, sh; add an "es" */
+ Strcasecpy(bspot+1, "es");
} else if (lowc(*bspot) == 'y' && !index(vowels, lowc(*(bspot-1)))) {
- /* like "y" case in makeplural */
- Strcasecpy(bspot, "ies");
+ /* like "y" case in makeplural */
+ Strcasecpy(bspot, "ies");
} else {
- Strcasecpy(bspot+1, "s");
+ Strcasecpy(bspot+1, "s");
}
return buf;
}
struct sing_plur {
- const char *sing, *plur;
+ const char *sing, *plur;
};
/* word pairs that don't fit into formula-based transformations;
also some suffices which have very few--often one--matches or
which aren't systematically reversible (knives, staves) */
static struct sing_plur one_off[] = {
- { "child", "children" }, /* (for wise guys who give their food funny names) */
- { "cubus", "cubi" }, /* in-/suc-cubus */
- { "culus", "culi" }, /* homunculus */
- { "djinni", "djinn" },
- { "erinys", "erinyes" },
- { "foot", "feet" },
- { "fungus", "fungi" },
- { "knife", "knives" },
- { "labrum", "labra" }, /* candelabrum */
- { "louse", "lice" },
- { "mouse", "mice" },
- { "mumak", "mumakil" },
- { "nemesis", "nemeses" },
- { "rtex", "rtices" }, /* vortex */
- { "tooth", "teeth" },
- { "staff", "staves" },
- { 0, 0 }
+ { "child", "children" }, /* (for wise guys who give their food funny names) */
+ { "cubus", "cubi" }, /* in-/suc-cubus */
+ { "culus", "culi" }, /* homunculus */
+ { "djinni", "djinn" },
+ { "erinys", "erinyes" },
+ { "foot", "feet" },
+ { "fungus", "fungi" },
+ { "knife", "knives" },
+ { "labrum", "labra" }, /* candelabrum */
+ { "louse", "lice" },
+ { "mouse", "mice" },
+ { "mumak", "mumakil" },
+ { "nemesis", "nemeses" },
+ { "rtex", "rtices" }, /* vortex */
+ { "tooth", "teeth" },
+ { "staff", "staves" },
+ { 0, 0 }
};
static const char *const as_is[] = {
- /* makesingular() leaves these plural due to how they're used */
- "boots", "shoes",
- "gloves", "lenses", "scales",
- "gauntlets",
- "iron bars",
- /* both singular and plural are spelled the same */
- "deer", "fish", "tuna", "yaki", "-hai",
- "krill", "manes", "ninja", "sheep", "ronin", "roshi", "shito", "tengu",
- "ki-rin", "Nazgul",
- "gunyoki", "piranha", "samurai",
- "shuriken",
- 0,
- /* Note: "fish" and "piranha" are collective plurals, suitable
- for "wiped out all <foo>". For "3 <foo>", they should be
- "fishes" and "piranhas" instead. We settle for collective
- variant instead of attempting to support both. */
+ /* makesingular() leaves these plural due to how they're used */
+ "boots", "shoes",
+ "gloves", "lenses", "scales",
+ "gauntlets",
+ "iron bars",
+ /* both singular and plural are spelled the same */
+ "deer", "fish", "tuna", "yaki", "-hai",
+ "krill", "manes", "ninja", "sheep", "ronin", "roshi", "shito", "tengu",
+ "ki-rin", "Nazgul",
+ "gunyoki", "piranha", "samurai",
+ "shuriken",
+ 0,
+ /* Note: "fish" and "piranha" are collective plurals, suitable
+ for "wiped out all <foo>". For "3 <foo>", they should be
+ "fishes" and "piranhas" instead. We settle for collective
+ variant instead of attempting to support both. */
};
/* singularize/pluralize decisiions common to both makesingular & makeplural */
boolean to_plural; /* true => makeplural, false => makesingular */
const char *const *alt_as_is; /* another set like as_is[] */
{
- const struct sing_plur *sp;
- const char *same, *other, *const *as;
- int al;
-
- for (as = as_is; *as; ++as) {
- al = (int)strlen(*as);
- if (!BSTRCMPI(basestr, endstring - al, *as))
- return TRUE;
- }
- if (alt_as_is) {
- for (as = alt_as_is; *as; ++as) {
- al = (int)strlen(*as);
- if (!BSTRCMPI(basestr, endstring - al, *as))
- return TRUE;
- }
- }
-
- for (sp = one_off; sp->sing; sp++) {
- /* check whether endstring already matches */
- same = to_plural ? sp->plur : sp->sing;
- al = (int)strlen(same);
- if (!BSTRCMPI(basestr, endstring - al, same))
- return TRUE; /* use as-is */
- /* check whether it matches the inverse; if so, transform it */
- other = to_plural ? sp->sing : sp->plur;
- al = (int)strlen(other);
- if (!BSTRCMPI(basestr, endstring - al, other)) {
- Strcasecpy(endstring - al, same);
- return TRUE; /* one_off[] transformation */
- }
- }
- return FALSE;
+ const struct sing_plur *sp;
+ const char *same, *other, *const *as;
+ int al;
+
+ for (as = as_is; *as; ++as) {
+ al = (int)strlen(*as);
+ if (!BSTRCMPI(basestr, endstring - al, *as))
+ return TRUE;
+ }
+ if (alt_as_is) {
+ for (as = alt_as_is; *as; ++as) {
+ al = (int)strlen(*as);
+ if (!BSTRCMPI(basestr, endstring - al, *as))
+ return TRUE;
+ }
+ }
+
+ for (sp = one_off; sp->sing; sp++) {
+ /* check whether endstring already matches */
+ same = to_plural ? sp->plur : sp->sing;
+ al = (int)strlen(same);
+ if (!BSTRCMPI(basestr, endstring - al, same))
+ return TRUE; /* use as-is */
+ /* check whether it matches the inverse; if so, transform it */
+ other = to_plural ? sp->sing : sp->plur;
+ al = (int)strlen(other);
+ if (!BSTRCMPI(basestr, endstring - al, other)) {
+ Strcasecpy(endstring - al, same);
+ return TRUE; /* one_off[] transformation */
+ }
+ }
+ return FALSE;
}
/* searches for common compounds, ex. lump of royal jelly */
{
/* if new entries are added, be sure to keep compound_start[] in sync */
static const char *const compounds[] = {
- " of ",
- " labeled ",
- " called ",
- " named ",
- " above", /* lurkers above */
- " versus ",
- " from ",
- " in ",
- " on ",
- " a la ",
- " with", /* " with "? */
- " de ",
- " d'",
- " du ",
- "-in-",
- "-at-",
- 0
+ " of ",
+ " labeled ",
+ " called ",
+ " named ",
+ " above", /* lurkers above */
+ " versus ",
+ " from ",
+ " in ",
+ " on ",
+ " a la ",
+ " with", /* " with "? */
+ " de ",
+ " d'",
+ " du ",
+ "-in-",
+ "-at-",
+ 0
}, /* list of first characters for all compounds[] entries */
- compound_start[] = " -";
+ compound_start[] = " -";
const char *const *cmpd;
char *p;
for (p = str; *p; ++p) {
- /* substring starting at p can only match if *p is found
- within compound_start[] */
- if (!index(compound_start, *p)) continue;
+ /* substring starting at p can only match if *p is found
+ within compound_start[] */
+ if (!index(compound_start, *p)) continue;
- /* check current substring against all words in the compound[] list */
- for (cmpd = compounds; *cmpd; ++cmpd)
- if (!strncmpi(p, *cmpd, (int)strlen(*cmpd))) return p;
+ /* check current substring against all words in the compound[] list */
+ for (cmpd = compounds; *cmpd; ++cmpd)
+ if (!strncmpi(p, *cmpd, (int)strlen(*cmpd))) return p;
}
/* wasn't recognized as a compound phrase */
return 0;
makeplural(oldstr)
const char *oldstr;
{
- register char *spot;
- char lo_c, *str = nextobuf();
- const char *excess = (char *)0;
- int len;
-
- if (oldstr) while (*oldstr == ' ') oldstr++;
- if (!oldstr || !*oldstr) {
- impossible("plural of null?");
- Strcpy(str, "s");
- return str;
- }
- Strcpy(str, oldstr);
-
- /*
- * Skip changing "pair of" to "pairs of". According to Webster, usual
- * English usage is use pairs for humans, e.g. 3 pairs of dancers,
- * and pair for objects and non-humans, e.g. 3 pair of boots. We don't
- * refer to pairs of humans in this game so just skip to the bottom.
- */
- if (!strncmpi(str, "pair of ", 8))
- goto bottom;
-
- /* look for "foo of bar" so that we can focus on "foo" */
- if ((spot = singplur_compound(str)) != 0) {
- excess = oldstr + (int)(spot - str);
- *spot = '\0';
- } else
- spot = eos(str);
-
- spot--;
- while (spot > str && *spot == ' ') spot--; /* Strip blanks from end */
- *(spot+1) = 0;
- /* Now spot is the last character of the string */
-
- len = strlen(str);
-
- /* Single letters */
- if (len==1 || !letter(*spot)) {
- Strcpy(spot+1, "'s");
- goto bottom;
- }
-
- /* dispense with some words which don't need pluralization */
+ register char *spot;
+ char lo_c, *str = nextobuf();
+ const char *excess = (char *)0;
+ int len;
+
+ if (oldstr) while (*oldstr == ' ') oldstr++;
+ if (!oldstr || !*oldstr) {
+ impossible("plural of null?");
+ Strcpy(str, "s");
+ return str;
+ }
+ Strcpy(str, oldstr);
+
+ /*
+ * Skip changing "pair of" to "pairs of". According to Webster, usual
+ * English usage is use pairs for humans, e.g. 3 pairs of dancers,
+ * and pair for objects and non-humans, e.g. 3 pair of boots. We don't
+ * refer to pairs of humans in this game so just skip to the bottom.
+ */
+ if (!strncmpi(str, "pair of ", 8))
+ goto bottom;
+
+ /* look for "foo of bar" so that we can focus on "foo" */
+ if ((spot = singplur_compound(str)) != 0) {
+ excess = oldstr + (int)(spot - str);
+ *spot = '\0';
+ } else
+ spot = eos(str);
+
+ spot--;
+ while (spot > str && *spot == ' ') spot--; /* Strip blanks from end */
+ *(spot+1) = 0;
+ /* Now spot is the last character of the string */
+
+ len = strlen(str);
+
+ /* Single letters */
+ if (len==1 || !letter(*spot)) {
+ Strcpy(spot+1, "'s");
+ goto bottom;
+ }
+
+ /* dispense with some words which don't need pluralization */
{
- static const char *const already_plural[] = {
- "ae", /* algae, larvae, &c */
- "men", /* also catches women, watchmen */
- "matzot",
- 0,
- };
-
- /* spot+1: synch up with makesingular's usage */
- if (singplur_lookup(str, spot + 1, TRUE, already_plural))
- goto bottom;
-
- /* more of same, but not suitable for blanket loop checking */
- if ((len == 2 && !strcmpi(str, "ya")) ||
- (len >= 3 && !strcmpi(spot-2, " ya")))
- goto bottom;
- }
-
- /* man/men ("Wiped out all cavemen.") */
- if (len >= 3 && !strcmpi(spot-2, "man") &&
- /* exclude shamans and humans */
- (len < 6 || strcmpi(spot-5, "shaman")) &&
- (len < 5 || strcmpi(spot-4, "human"))) {
- Strcasecpy(spot-1, "en");
- goto bottom;
- }
- if (lowc(*spot) == 'f') { /* (staff handled via one_off[]) */
- lo_c = lowc(*(spot-1));
- if (len >= 3 && !strcmpi(spot-2, "erf")) {
- /* avoid "nerf" -> "nerves", "serf" -> "serves" */
- ; /* fall through to default (append 's') */
- } else if (index("lr", lo_c) || index(vowels, lo_c)) {
- /* [aeioulr]f to [aeioulr]ves */
- Strcasecpy(spot, "ves");
- goto bottom;
- }
- }
- /* ium/ia (mycelia, baluchitheria) */
- if (len >= 3 && !strcmpi(spot-2, "ium")) {
- Strcasecpy(spot-2, "ia");
- goto bottom;
- }
- /* algae, larvae, hyphae (another fungus part) */
- if ((len >= 4 && !strcmpi(spot-3, "alga")) ||
- (len >= 5 && (!strcmpi(spot-4, "hypha") ||
- !strcmpi(spot-4, "larva"))) ||
- (len >= 6 && !strcmpi(spot-5, "amoeba")) ||
- (len >= 8 && (!strcmpi(spot-7, "vertebra")))) {
- /* a to ae */
- Strcasecpy(spot+1, "e");
- goto bottom;
- }
- /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
- if (len > 3 && !strcmpi(spot-1, "us") &&
- !((len >= 5 && !strcmpi(spot-4, "lotus")) ||
- (len >= 6 && !strcmpi(spot-5, "wumpus")))) {
- Strcasecpy(spot-1, "i");
- goto bottom;
- }
- /* sis/ses (nemesis) */
- if (len >= 3 && !strcmpi(spot-2, "sis")) {
- Strcasecpy(spot-1, "es");
- goto bottom;
- }
- /* matzoh/matzot, possible food name */
- if (len >= 6 && (!strcmpi(spot-5, "matzoh") ||
- !strcmpi(spot-5, "matzah"))) {
- Strcasecpy(spot-1, "ot"); /* oh/ah -> ot */
- goto bottom;
- }
- if (len >= 5 && (!strcmpi(spot-4, "matzo") ||
- !strcmpi(spot-4, "matza"))) {
- Strcasecpy(spot, "ot"); /* o/a -> ot */
- goto bottom;
- }
-
- /* note: -eau/-eaux (gateau, bordeau...) */
- /* note: ox/oxen, VAX/VAXen, goose/geese */
-
- lo_c = lowc(*spot);
-
- /* Ends in z, x, s, ch, sh; add an "es" */
- if (index("zxs", lo_c) ||
- (len >= 2 && lo_c == 'h' && index("cs", lowc(*(spot-1)))) ||
- /* Kludge to get "tomatoes" and "potatoes" right */
- (len >= 4 && !strcmpi(spot-2, "ato")) ||
- (len >= 5 && !strcmpi(spot-4, "dingo"))) {
- Strcasecpy(spot+1, "es"); /* append es */
- goto bottom;
- }
- /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
- if (lo_c == 'y' &&
- !index(vowels, lowc(*(spot-1)))) {
- Strcasecpy(spot, "ies"); /* y -> ies */
- goto bottom;
- }
- /* Default: append an 's' */
- Strcasecpy(spot+1, "s");
+ static const char *const already_plural[] = {
+ "ae", /* algae, larvae, &c */
+ "men", /* also catches women, watchmen */
+ "matzot",
+ 0,
+ };
+
+ /* spot+1: synch up with makesingular's usage */
+ if (singplur_lookup(str, spot + 1, TRUE, already_plural))
+ goto bottom;
+
+ /* more of same, but not suitable for blanket loop checking */
+ if ((len == 2 && !strcmpi(str, "ya")) ||
+ (len >= 3 && !strcmpi(spot-2, " ya")))
+ goto bottom;
+ }
+
+ /* man/men ("Wiped out all cavemen.") */
+ if (len >= 3 && !strcmpi(spot-2, "man") &&
+ /* exclude shamans and humans */
+ (len < 6 || strcmpi(spot-5, "shaman")) &&
+ (len < 5 || strcmpi(spot-4, "human"))) {
+ Strcasecpy(spot-1, "en");
+ goto bottom;
+ }
+ if (lowc(*spot) == 'f') { /* (staff handled via one_off[]) */
+ lo_c = lowc(*(spot-1));
+ if (len >= 3 && !strcmpi(spot-2, "erf")) {
+ /* avoid "nerf" -> "nerves", "serf" -> "serves" */
+ ; /* fall through to default (append 's') */
+ } else if (index("lr", lo_c) || index(vowels, lo_c)) {
+ /* [aeioulr]f to [aeioulr]ves */
+ Strcasecpy(spot, "ves");
+ goto bottom;
+ }
+ }
+ /* ium/ia (mycelia, baluchitheria) */
+ if (len >= 3 && !strcmpi(spot-2, "ium")) {
+ Strcasecpy(spot-2, "ia");
+ goto bottom;
+ }
+ /* algae, larvae, hyphae (another fungus part) */
+ if ((len >= 4 && !strcmpi(spot-3, "alga")) ||
+ (len >= 5 && (!strcmpi(spot-4, "hypha") ||
+ !strcmpi(spot-4, "larva"))) ||
+ (len >= 6 && !strcmpi(spot-5, "amoeba")) ||
+ (len >= 8 && (!strcmpi(spot-7, "vertebra")))) {
+ /* a to ae */
+ Strcasecpy(spot+1, "e");
+ goto bottom;
+ }
+ /* fungus/fungi, homunculus/homunculi, but buses, lotuses, wumpuses */
+ if (len > 3 && !strcmpi(spot-1, "us") &&
+ !((len >= 5 && !strcmpi(spot-4, "lotus")) ||
+ (len >= 6 && !strcmpi(spot-5, "wumpus")))) {
+ Strcasecpy(spot-1, "i");
+ goto bottom;
+ }
+ /* sis/ses (nemesis) */
+ if (len >= 3 && !strcmpi(spot-2, "sis")) {
+ Strcasecpy(spot-1, "es");
+ goto bottom;
+ }
+ /* matzoh/matzot, possible food name */
+ if (len >= 6 && (!strcmpi(spot-5, "matzoh") ||
+ !strcmpi(spot-5, "matzah"))) {
+ Strcasecpy(spot-1, "ot"); /* oh/ah -> ot */
+ goto bottom;
+ }
+ if (len >= 5 && (!strcmpi(spot-4, "matzo") ||
+ !strcmpi(spot-4, "matza"))) {
+ Strcasecpy(spot, "ot"); /* o/a -> ot */
+ goto bottom;
+ }
+
+ /* note: -eau/-eaux (gateau, bordeau...) */
+ /* note: ox/oxen, VAX/VAXen, goose/geese */
+
+ lo_c = lowc(*spot);
+
+ /* Ends in z, x, s, ch, sh; add an "es" */
+ if (index("zxs", lo_c) ||
+ (len >= 2 && lo_c == 'h' && index("cs", lowc(*(spot-1)))) ||
+ /* Kludge to get "tomatoes" and "potatoes" right */
+ (len >= 4 && !strcmpi(spot-2, "ato")) ||
+ (len >= 5 && !strcmpi(spot-4, "dingo"))) {
+ Strcasecpy(spot+1, "es"); /* append es */
+ goto bottom;
+ }
+ /* Ends in y preceded by consonant (note: also "qu") change to "ies" */
+ if (lo_c == 'y' &&
+ !index(vowels, lowc(*(spot-1)))) {
+ Strcasecpy(spot, "ies"); /* y -> ies */
+ goto bottom;
+ }
+ /* Default: append an 's' */
+ Strcasecpy(spot+1, "s");
bottom:
- if (excess) Strcat(str, excess);
- return str;
+ if (excess) Strcat(str, excess);
+ return str;
}
/*
makesingular(oldstr)
const char *oldstr;
{
- register char *p, *bp;
- const char *excess = 0;
- char *str = nextobuf();
-
- if (oldstr) while (*oldstr == ' ') oldstr++;
- if (!oldstr || !*oldstr) {
- impossible("singular of null?");
- str[0] = '\0';
- return str;
- }
-
- bp = strcpy(str, oldstr);
-
- /* check for "foo of bar" so that we can focus on "foo" */
- if ((p = singplur_compound(bp)) != 0) {
- excess = oldstr + (int)(p - bp);
- *p = '\0';
- } else
- p = eos(bp);
-
- /* dispense with some words which don't need singularization */
- if (singplur_lookup(bp, p, FALSE, special_subjs))
- goto bottom;
-
- /* remove -s or -es (boxes) or -ies (rubies) */
- if (p >= bp+1 && lowc(p[-1]) == 's') {
- if (p >= bp+2 && lowc(p[-2]) == 'e') {
- if (p >= bp+3 && lowc(p[-3]) == 'i') { /* "ies" */
- if (!BSTRCMPI(bp, p-7, "cookies") ||
- !BSTRCMPI(bp, p-4, "pies") ||
- !BSTRCMPI(bp, p-5, "mbies") || /* zombie */
- !BSTRCMPI(bp, p-5, "yries")) /* valkyrie */
- goto mins;
- Strcasecpy(p-3, "y"); /* ies -> y */
- goto bottom;
- }
- /* wolves, but f to ves isn't fully reversible */
- if (p-4 >= bp && (index("lr", lowc(*(p-4))) ||
- index(vowels, lowc(*(p-4)))) &&
- !BSTRCMPI(bp, p-3, "ves")) {
- if (!BSTRCMPI(bp, p-6, "cloves") ||
- !BSTRCMPI(bp, p-6, "nerves")) goto mins;
- Strcasecpy(p-3, "f"); /* ves -> f */
- goto bottom;
- }
- /* note: nurses, axes but boxes, wumpuses */
- if (!BSTRCMPI(bp, p-4, "eses") ||
- !BSTRCMPI(bp, p-4, "oxes") || /* boxes, foxes */
- !BSTRCMPI(bp, p-4, "nxes") || /* lynxes */
- !BSTRCMPI(bp, p-4, "ches") ||
- !BSTRCMPI(bp, p-4, "uses") || /* lotuses */
- !BSTRCMPI(bp, p-4, "sses") || /* priestesses */
- !BSTRCMPI(bp, p-5, "atoes") || /* tomatoes */
- !BSTRCMPI(bp, p-7, "dingoes") ||
- !BSTRCMPI(bp, p-7, "Aleaxes")) {
- *(p-2) = '\0'; /* drop es */
- goto bottom;
- } /* else fall through to mins */
-
- /* ends in 's' but not 'es' */
- } else if (!BSTRCMPI(bp, p-2, "us")) { /* lotus, fungus... */
- if (BSTRCMPI(bp, p-6, "tengus") && /* but not these... */
- BSTRCMPI(bp, p-7, "hezrous"))
- goto bottom;
- } else if (!BSTRCMPI(bp, p-2, "ss") ||
- !BSTRCMPI(bp, p-5, " lens") ||
- (p-4 == bp && !strcmpi(p-4, "lens"))) {
- goto bottom;
- }
- mins:
- *(p-1) = '\0'; /* drop s */
-
- } else { /* input doesn't end in 's' */
-
- if (!BSTRCMPI(bp, p-3, "men")) {
- Strcasecpy(p-2, "an");
- goto bottom;
- }
- /* matzot -> matzo, algae -> alga */
- if (!BSTRCMPI(bp, p-6, "matzot") ||
- !BSTRCMPI(bp, p-2, "ae")) {
- *(p-1) = '\0'; /* drop t/e */
- goto bottom;
- }
- /* balactheria -> balactherium */
- if (p-4 >= bp && !strcmpi(p-2, "ia") &&
- index("lr", lowc(*(p-3))) && lowc(*(p-4)) == 'e') {
- Strcasecpy(p-1, "um"); /* a -> um */
- }
-
- /* here we cannot find the plural suffix */
- }
+ register char *p, *bp;
+ const char *excess = 0;
+ char *str = nextobuf();
+
+ if (oldstr) while (*oldstr == ' ') oldstr++;
+ if (!oldstr || !*oldstr) {
+ impossible("singular of null?");
+ str[0] = '\0';
+ return str;
+ }
+
+ bp = strcpy(str, oldstr);
+
+ /* check for "foo of bar" so that we can focus on "foo" */
+ if ((p = singplur_compound(bp)) != 0) {
+ excess = oldstr + (int)(p - bp);
+ *p = '\0';
+ } else
+ p = eos(bp);
+
+ /* dispense with some words which don't need singularization */
+ if (singplur_lookup(bp, p, FALSE, special_subjs))
+ goto bottom;
+
+ /* remove -s or -es (boxes) or -ies (rubies) */
+ if (p >= bp+1 && lowc(p[-1]) == 's') {
+ if (p >= bp+2 && lowc(p[-2]) == 'e') {
+ if (p >= bp+3 && lowc(p[-3]) == 'i') { /* "ies" */
+ if (!BSTRCMPI(bp, p-7, "cookies") ||
+ !BSTRCMPI(bp, p-4, "pies") ||
+ !BSTRCMPI(bp, p-5, "mbies") || /* zombie */
+ !BSTRCMPI(bp, p-5, "yries")) /* valkyrie */
+ goto mins;
+ Strcasecpy(p-3, "y"); /* ies -> y */
+ goto bottom;
+ }
+ /* wolves, but f to ves isn't fully reversible */
+ if (p-4 >= bp && (index("lr", lowc(*(p-4))) ||
+ index(vowels, lowc(*(p-4)))) &&
+ !BSTRCMPI(bp, p-3, "ves")) {
+ if (!BSTRCMPI(bp, p-6, "cloves") ||
+ !BSTRCMPI(bp, p-6, "nerves")) goto mins;
+ Strcasecpy(p-3, "f"); /* ves -> f */
+ goto bottom;
+ }
+ /* note: nurses, axes but boxes, wumpuses */
+ if (!BSTRCMPI(bp, p-4, "eses") ||
+ !BSTRCMPI(bp, p-4, "oxes") || /* boxes, foxes */
+ !BSTRCMPI(bp, p-4, "nxes") || /* lynxes */
+ !BSTRCMPI(bp, p-4, "ches") ||
+ !BSTRCMPI(bp, p-4, "uses") || /* lotuses */
+ !BSTRCMPI(bp, p-4, "sses") || /* priestesses */
+ !BSTRCMPI(bp, p-5, "atoes") || /* tomatoes */
+ !BSTRCMPI(bp, p-7, "dingoes") ||
+ !BSTRCMPI(bp, p-7, "Aleaxes")) {
+ *(p-2) = '\0'; /* drop es */
+ goto bottom;
+ } /* else fall through to mins */
+
+ /* ends in 's' but not 'es' */
+ } else if (!BSTRCMPI(bp, p-2, "us")) { /* lotus, fungus... */
+ if (BSTRCMPI(bp, p-6, "tengus") && /* but not these... */
+ BSTRCMPI(bp, p-7, "hezrous"))
+ goto bottom;
+ } else if (!BSTRCMPI(bp, p-2, "ss") ||
+ !BSTRCMPI(bp, p-5, " lens") ||
+ (p-4 == bp && !strcmpi(p-4, "lens"))) {
+ goto bottom;
+ }
+ mins:
+ *(p-1) = '\0'; /* drop s */
+
+ } else { /* input doesn't end in 's' */
+
+ if (!BSTRCMPI(bp, p-3, "men")) {
+ Strcasecpy(p-2, "an");
+ goto bottom;
+ }
+ /* matzot -> matzo, algae -> alga */
+ if (!BSTRCMPI(bp, p-6, "matzot") ||
+ !BSTRCMPI(bp, p-2, "ae")) {
+ *(p-1) = '\0'; /* drop t/e */
+ goto bottom;
+ }
+ /* balactheria -> balactherium */
+ if (p-4 >= bp && !strcmpi(p-2, "ia") &&
+ index("lr", lowc(*(p-3))) && lowc(*(p-4)) == 'e') {
+ Strcasecpy(p-1, "um"); /* a -> um */
+ }
+
+ /* here we cannot find the plural suffix */
+ }
bottom:
- /* if we stripped off a suffix (" of bar" from "foo of bar"),
- put it back now [strcat() isn't actually 100% safe here...] */
- if (excess) Strcat(bp, excess);
+ /* if we stripped off a suffix (" of bar" from "foo of bar"),
+ put it back now [strcat() isn't actually 100% safe here...] */
+ if (excess) Strcat(bp, excess);
- return bp;
+ return bp;
}
/* compare user string against object name string using fuzzy matching */
const char *o_str; /* from objects[], so is in canonical form */
boolean retry_inverted; /* optional extra "of" handling */
{
- static NEARDATA const char
- detect_SP[] = "detect ", SP_detection[] = " detection";
- char *p, buf[BUFSZ];
-
- /* ignore spaces & hyphens and upper/lower case when comparing */
- if (fuzzymatch(u_str, o_str, " -", TRUE)) return TRUE;
-
- if (retry_inverted) {
- const char *u_of, *o_of;
-
- /* when just one of the strings is in the form "foo of bar",
- convert it into "bar foo" and perform another comparison */
- u_of = strstri(u_str, " of ");
- o_of = strstri(o_str, " of ");
- if (u_of && !o_of) {
- Strcpy(buf, u_of + 4);
- p = eos(strcat(buf, " "));
- while (u_str < u_of) *p++ = *u_str++;
- *p = '\0';
- return fuzzymatch(buf, o_str, " -", TRUE);
- } else if (o_of && !u_of) {
- Strcpy(buf, o_of + 4);
- p = eos(strcat(buf, " "));
- while (o_str < o_of) *p++ = *o_str++;
- *p = '\0';
- return fuzzymatch(u_str, buf, " -", TRUE);
- }
- }
-
- /* [note: if something like "elven speed boots" ever gets added, these
- special cases should be changed to call wishymatch() recursively in
- order to get the "of" inversion handling] */
- if (!strncmp(o_str, "dwarvish ", 9)) {
- if (!strncmpi(u_str, "dwarven ", 8))
- return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
- } else if (!strncmp(o_str, "elven ", 6)) {
- if (!strncmpi(u_str, "elvish ", 7))
- return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
- else if (!strncmpi(u_str, "elfin ", 6))
- return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
- } else if (!strncmp(o_str, detect_SP, sizeof detect_SP - 1)) {
- /* check for "detect <foo>" vs "<foo> detection" */
- if ((p = strstri(u_str, SP_detection)) != 0 &&
- !*(p + sizeof SP_detection - 1)) {
- /* convert "<foo> detection" into "detect <foo>" */
- *p = '\0';
- Strcat(strcpy(buf, detect_SP), u_str);
- /* "detect monster" -> "detect monsters" */
- if (!strcmpi(u_str, "monster")) Strcat(buf, "s");
- *p = ' ';
- return fuzzymatch(buf, o_str, " -", TRUE);
- }
- } else if (strstri(o_str, SP_detection)) {
- /* and the inverse, "<foo> detection" vs "detect <foo>" */
- if (!strncmpi(u_str, detect_SP, sizeof detect_SP - 1)) {
- /* convert "detect <foo>s" into "<foo> detection" */
- p = makesingular(u_str + sizeof detect_SP - 1);
- Strcat(strcpy(buf, p), SP_detection);
- /* caller may be looping through objects[], so avoid
- churning through all the obufs */
- releaseobuf(p);
- return fuzzymatch(buf, o_str, " -", TRUE);
- }
- } else if (strstri(o_str, "ability")) {
- /* when presented with "foo of bar", make singular() used to
- singularize both foo & bar, but now only does so for foo */
- /* catch "{potion(s),ring} of {gain,restore,sustain} abilities" */
- if ((p = strstri(u_str, "abilities")) != 0 &&
- !*(p + sizeof "abilities" - 1)) {
- (void)strncpy(buf, u_str, (unsigned)(p - u_str));
- Strcpy(buf + (p - u_str), "ability");
- return fuzzymatch(buf, o_str, " -", TRUE);
- }
- } else if (!strcmp(o_str, "aluminum")) {
- /* this special case doesn't really fit anywhere else... */
- /* (note that " wand" will have been stripped off by now) */
- if (!strcmpi(u_str, "aluminium"))
- return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
- }
-
- return FALSE;
+ static NEARDATA const char
+ detect_SP[] = "detect ", SP_detection[] = " detection";
+ char *p, buf[BUFSZ];
+
+ /* ignore spaces & hyphens and upper/lower case when comparing */
+ if (fuzzymatch(u_str, o_str, " -", TRUE)) return TRUE;
+
+ if (retry_inverted) {
+ const char *u_of, *o_of;
+
+ /* when just one of the strings is in the form "foo of bar",
+ convert it into "bar foo" and perform another comparison */
+ u_of = strstri(u_str, " of ");
+ o_of = strstri(o_str, " of ");
+ if (u_of && !o_of) {
+ Strcpy(buf, u_of + 4);
+ p = eos(strcat(buf, " "));
+ while (u_str < u_of) *p++ = *u_str++;
+ *p = '\0';
+ return fuzzymatch(buf, o_str, " -", TRUE);
+ } else if (o_of && !u_of) {
+ Strcpy(buf, o_of + 4);
+ p = eos(strcat(buf, " "));
+ while (o_str < o_of) *p++ = *o_str++;
+ *p = '\0';
+ return fuzzymatch(u_str, buf, " -", TRUE);
+ }
+ }
+
+ /* [note: if something like "elven speed boots" ever gets added, these
+ special cases should be changed to call wishymatch() recursively in
+ order to get the "of" inversion handling] */
+ if (!strncmp(o_str, "dwarvish ", 9)) {
+ if (!strncmpi(u_str, "dwarven ", 8))
+ return fuzzymatch(u_str + 8, o_str + 9, " -", TRUE);
+ } else if (!strncmp(o_str, "elven ", 6)) {
+ if (!strncmpi(u_str, "elvish ", 7))
+ return fuzzymatch(u_str + 7, o_str + 6, " -", TRUE);
+ else if (!strncmpi(u_str, "elfin ", 6))
+ return fuzzymatch(u_str + 6, o_str + 6, " -", TRUE);
+ } else if (!strncmp(o_str, detect_SP, sizeof detect_SP - 1)) {
+ /* check for "detect <foo>" vs "<foo> detection" */
+ if ((p = strstri(u_str, SP_detection)) != 0 &&
+ !*(p + sizeof SP_detection - 1)) {
+ /* convert "<foo> detection" into "detect <foo>" */
+ *p = '\0';
+ Strcat(strcpy(buf, detect_SP), u_str);
+ /* "detect monster" -> "detect monsters" */
+ if (!strcmpi(u_str, "monster")) Strcat(buf, "s");
+ *p = ' ';
+ return fuzzymatch(buf, o_str, " -", TRUE);
+ }
+ } else if (strstri(o_str, SP_detection)) {
+ /* and the inverse, "<foo> detection" vs "detect <foo>" */
+ if (!strncmpi(u_str, detect_SP, sizeof detect_SP - 1)) {
+ /* convert "detect <foo>s" into "<foo> detection" */
+ p = makesingular(u_str + sizeof detect_SP - 1);
+ Strcat(strcpy(buf, p), SP_detection);
+ /* caller may be looping through objects[], so avoid
+ churning through all the obufs */
+ releaseobuf(p);
+ return fuzzymatch(buf, o_str, " -", TRUE);
+ }
+ } else if (strstri(o_str, "ability")) {
+ /* when presented with "foo of bar", make singular() used to
+ singularize both foo & bar, but now only does so for foo */
+ /* catch "{potion(s),ring} of {gain,restore,sustain} abilities" */
+ if ((p = strstri(u_str, "abilities")) != 0 &&
+ !*(p + sizeof "abilities" - 1)) {
+ (void)strncpy(buf, u_str, (unsigned)(p - u_str));
+ Strcpy(buf + (p - u_str), "ability");
+ return fuzzymatch(buf, o_str, " -", TRUE);
+ }
+ } else if (!strcmp(o_str, "aluminum")) {
+ /* this special case doesn't really fit anywhere else... */
+ /* (note that " wand" will have been stripped off by now) */
+ if (!strcmpi(u_str, "aluminium"))
+ return fuzzymatch(u_str + 9, o_str + 8, " -", TRUE);
+ }
+
+ return FALSE;
}
struct o_range {
- const char *name, oclass;
- int f_o_range, l_o_range;
+ const char *name, oclass;
+ int f_o_range, l_o_range;
};
/* wishable subranges of objects */
STATIC_OVL NEARDATA const struct o_range o_ranges[] = {
- { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
- { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
- { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
- { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
- { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
- { "hat", ARMOR_CLASS, FEDORA, DUNCE_CAP },
- { "helm", ARMOR_CLASS, ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
- { "gloves", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
- { "gauntlets", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
- { "boots", ARMOR_CLASS, LOW_BOOTS, LEVITATION_BOOTS },
- { "shoes", ARMOR_CLASS, LOW_BOOTS, IRON_SHOES },
- { "cloak", ARMOR_CLASS, MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
- { "shirt", ARMOR_CLASS, HAWAIIAN_SHIRT, T_SHIRT },
- { "dragon scales",
- ARMOR_CLASS, GRAY_DRAGON_SCALES, YELLOW_DRAGON_SCALES },
- { "dragon scale mail",
- ARMOR_CLASS, GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL },
- { "sword", WEAPON_CLASS, SHORT_SWORD, KATANA },
- { "venom", VENOM_CLASS, BLINDING_VENOM, ACID_VENOM },
- { "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
- { "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
+ { "bag", TOOL_CLASS, SACK, BAG_OF_TRICKS },
+ { "lamp", TOOL_CLASS, OIL_LAMP, MAGIC_LAMP },
+ { "candle", TOOL_CLASS, TALLOW_CANDLE, WAX_CANDLE },
+ { "horn", TOOL_CLASS, TOOLED_HORN, HORN_OF_PLENTY },
+ { "shield", ARMOR_CLASS, SMALL_SHIELD, SHIELD_OF_REFLECTION },
+ { "hat", ARMOR_CLASS, FEDORA, DUNCE_CAP },
+ { "helm", ARMOR_CLASS, ELVEN_LEATHER_HELM, HELM_OF_TELEPATHY },
+ { "gloves", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
+ { "gauntlets", ARMOR_CLASS, LEATHER_GLOVES, GAUNTLETS_OF_DEXTERITY },
+ { "boots", ARMOR_CLASS, LOW_BOOTS, LEVITATION_BOOTS },
+ { "shoes", ARMOR_CLASS, LOW_BOOTS, IRON_SHOES },
+ { "cloak", ARMOR_CLASS, MUMMY_WRAPPING, CLOAK_OF_DISPLACEMENT },
+ { "shirt", ARMOR_CLASS, HAWAIIAN_SHIRT, T_SHIRT },
+ { "dragon scales",
+ ARMOR_CLASS, GRAY_DRAGON_SCALES, YELLOW_DRAGON_SCALES },
+ { "dragon scale mail",
+ ARMOR_CLASS, GRAY_DRAGON_SCALE_MAIL, YELLOW_DRAGON_SCALE_MAIL },
+ { "sword", WEAPON_CLASS, SHORT_SWORD, KATANA },
+ { "venom", VENOM_CLASS, BLINDING_VENOM, ACID_VENOM },
+ { "gray stone", GEM_CLASS, LUCKSTONE, FLINT },
+ { "grey stone", GEM_CLASS, LUCKSTONE, FLINT },
};
/* alternate spellings; if the difference is only the presence or
vs "pick-axe") then there is no need for inclusion in this list;
likewise for ``"of" inversions'' ("boots of speed" vs "speed boots") */
struct alt_spellings {
- const char *sp;
- int ob;
+ const char *sp;
+ int ob;
} spellings[] = {
- { "pickax", PICK_AXE },
- { "whip", BULLWHIP },
- { "saber", SILVER_SABER },
- { "silver sabre", SILVER_SABER },
- { "smooth shield", SHIELD_OF_REFLECTION },
- { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
- { "grey dragon scales", GRAY_DRAGON_SCALES },
- { "iron ball", HEAVY_IRON_BALL },
- { "lantern", BRASS_LANTERN },
- { "mattock", DWARVISH_MATTOCK },
- { "amulet of poison resistance", AMULET_VERSUS_POISON },
- { "potion of sleep", POT_SLEEPING },
- { "stone", ROCK },
- { "camera", EXPENSIVE_CAMERA },
- { "tee shirt", T_SHIRT },
- { "can", TIN },
- { "can opener", TIN_OPENER },
- { "kelp", KELP_FROND },
- { "eucalyptus", EUCALYPTUS_LEAF },
- { "hook", GRAPPLING_HOOK },
- { "grappling iron", GRAPPLING_HOOK },
- { "grapnel", GRAPPLING_HOOK },
- { "grapple", GRAPPLING_HOOK },
- { (const char *)0, 0 },
+ { "pickax", PICK_AXE },
+ { "whip", BULLWHIP },
+ { "saber", SILVER_SABER },
+ { "silver sabre", SILVER_SABER },
+ { "smooth shield", SHIELD_OF_REFLECTION },
+ { "grey dragon scale mail", GRAY_DRAGON_SCALE_MAIL },
+ { "grey dragon scales", GRAY_DRAGON_SCALES },
+ { "iron ball", HEAVY_IRON_BALL },
+ { "lantern", BRASS_LANTERN },
+ { "mattock", DWARVISH_MATTOCK },
+ { "amulet of poison resistance", AMULET_VERSUS_POISON },
+ { "potion of sleep", POT_SLEEPING },
+ { "stone", ROCK },
+ { "camera", EXPENSIVE_CAMERA },
+ { "tee shirt", T_SHIRT },
+ { "can", TIN },
+ { "can opener", TIN_OPENER },
+ { "kelp", KELP_FROND },
+ { "eucalyptus", EUCALYPTUS_LEAF },
+ { "hook", GRAPPLING_HOOK },
+ { "grappling iron", GRAPPLING_HOOK },
+ { "grapnel", GRAPPLING_HOOK },
+ { "grapple", GRAPPLING_HOOK },
+ { (const char *)0, 0 },
};
/*
register char *bp;
struct obj *no_wish;
{
- register char *p;
- register int i;
- register struct obj *otmp;
- int cnt, spe, spesgn, typ, very, rechrg;
- int blessed, uncursed, iscursed, ispoisoned, isgreased;
- int eroded, eroded2, erodeproof;
- int halfeaten, mntmp, contents;
- int islit, unlabeled, ishistoric, isdiluted, trapped;
- int tmp, tinv, tvariety;
- struct fruit *f;
- int ftype = context.current_fruit;
- char fruitbuf[BUFSZ];
- /* Fruits may not mess up the ability to wish for real objects (since
- * you can leave a fruit in a bones file and it will be added to
- * another person's game), so they must be checked for last, after
- * stripping all the possible prefixes and seeing if there's a real
- * name in there. So we have to save the full original name. However,
- * it's still possible to do things like "uncursed burnt Alaska",
- * or worse yet, "2 burned 5 course meals", so we need to loop to
- * strip off the prefixes again, this time stripping only the ones
- * possible on food.
- * We could get even more detailed so as to allow food names with
- * prefixes that _are_ possible on food, so you could wish for
- * "2 3 alarm chilis". Currently this isn't allowed; options.c
- * automatically sticks 'candied' in front of such names.
- */
-
- char oclass;
- char *un, *dn, *actualn;
- const char *name=0;
-
- cnt = spe = spesgn = typ = very = rechrg =
- blessed = uncursed = iscursed =
- ispoisoned = isgreased = eroded = eroded2 = erodeproof =
- halfeaten = islit = unlabeled = ishistoric = isdiluted =
- trapped = 0;
- tvariety = RANDOM_TIN;
- mntmp = NON_PM;
+ register char *p;
+ register int i;
+ register struct obj *otmp;
+ int cnt, spe, spesgn, typ, very, rechrg;
+ int blessed, uncursed, iscursed, ispoisoned, isgreased;
+ int eroded, eroded2, erodeproof;
+ int halfeaten, mntmp, contents;
+ int islit, unlabeled, ishistoric, isdiluted, trapped;
+ int tmp, tinv, tvariety;
+ struct fruit *f;
+ int ftype = context.current_fruit;
+ char fruitbuf[BUFSZ];
+ /* Fruits may not mess up the ability to wish for real objects (since
+ * you can leave a fruit in a bones file and it will be added to
+ * another person's game), so they must be checked for last, after
+ * stripping all the possible prefixes and seeing if there's a real
+ * name in there. So we have to save the full original name. However,
+ * it's still possible to do things like "uncursed burnt Alaska",
+ * or worse yet, "2 burned 5 course meals", so we need to loop to
+ * strip off the prefixes again, this time stripping only the ones
+ * possible on food.
+ * We could get even more detailed so as to allow food names with
+ * prefixes that _are_ possible on food, so you could wish for
+ * "2 3 alarm chilis". Currently this isn't allowed; options.c
+ * automatically sticks 'candied' in front of such names.
+ */
+
+ char oclass;
+ char *un, *dn, *actualn;
+ const char *name=0;
+
+ cnt = spe = spesgn = typ = very = rechrg =
+ blessed = uncursed = iscursed =
+ ispoisoned = isgreased = eroded = eroded2 = erodeproof =
+ halfeaten = islit = unlabeled = ishistoric = isdiluted =
+ trapped = 0;
+ tvariety = RANDOM_TIN;
+ mntmp = NON_PM;
#define UNDEFINED 0
#define EMPTY 1
#define SPINACH 2
- contents = UNDEFINED;
- oclass = 0;
- actualn = dn = un = 0;
-
- if (!bp) goto any;
- /* first, remove extra whitespace they may have typed */
- (void)mungspaces(bp);
- /* allow wishing for "nothing" to preserve wishless conduct...
- [now requires "wand of nothing" if that's what was really wanted] */
- if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil") ||
- !strcmpi(bp, "none")) return no_wish;
- /* save the [nearly] unmodified choice string */
- Strcpy(fruitbuf, bp);
-
- for(;;) {
- register int l;
-
- if (!bp || !*bp) goto any;
- if (!strncmpi(bp, "an ", l=3) ||
- !strncmpi(bp, "a ", l=2)) {
- cnt = 1;
- } else if (!strncmpi(bp, "the ", l=4)) {
- ; /* just increment `bp' by `l' below */
- } else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
- cnt = atoi(bp);
- while(digit(*bp)) bp++;
- while(*bp == ' ') bp++;
- l = 0;
- } else if (*bp == '+' || *bp == '-') {
- spesgn = (*bp++ == '+') ? 1 : -1;
- spe = atoi(bp);
- while(digit(*bp)) bp++;
- while(*bp == ' ') bp++;
- l = 0;
- } else if (!strncmpi(bp, "blessed ", l=8) ||
- !strncmpi(bp, "holy ", l=5)) {
- blessed = 1;
- } else if (!strncmpi(bp, "cursed ", l=7) ||
- !strncmpi(bp, "unholy ", l=7)) {
- iscursed = 1;
- } else if (!strncmpi(bp, "uncursed ", l=9)) {
- uncursed = 1;
- } else if (!strncmpi(bp, "rustproof ", l=10) ||
- !strncmpi(bp, "erodeproof ", l=11) ||
- !strncmpi(bp, "corrodeproof ", l=13) ||
- !strncmpi(bp, "fixed ", l=6) ||
- !strncmpi(bp, "fireproof ", l=10) ||
- !strncmpi(bp, "rotproof ", l=9)) {
- erodeproof = 1;
- } else if (!strncmpi(bp,"lit ", l=4) ||
- !strncmpi(bp,"burning ", l=8)) {
- islit = 1;
- } else if (!strncmpi(bp,"unlit ", l=6) ||
- !strncmpi(bp,"extinguished ", l=13)) {
- islit = 0;
- /* "unlabeled" and "blank" are synonymous */
- } else if (!strncmpi(bp,"unlabeled ", l=10) ||
- !strncmpi(bp,"unlabelled ", l=11) ||
- !strncmpi(bp,"blank ", l=6)) {
- unlabeled = 1;
- } else if(!strncmpi(bp, "poisoned ",l=9)) {
- ispoisoned=1;
- /* "trapped" recognized but not honored outside wizard mode */
- } else if(!strncmpi(bp, "trapped ",l=8)) {
- trapped = 0; /* undo any previous "untrapped" */
- if (wizard) trapped = 1;
- } else if(!strncmpi(bp, "untrapped ",l=10)) {
- trapped = 2; /* not trapped */
- } else if(!strncmpi(bp, "greased ",l=8)) {
- isgreased=1;
- } else if (!strncmpi(bp, "very ", l=5)) {
- /* very rusted very heavy iron ball */
- very = 1;
- } else if (!strncmpi(bp, "thoroughly ", l=11)) {
- very = 2;
- } else if (!strncmpi(bp, "rusty ", l=6) ||
- !strncmpi(bp, "rusted ", l=7) ||
- !strncmpi(bp, "burnt ", l=6) ||
- !strncmpi(bp, "burned ", l=7)) {
- eroded = 1 + very;
- very = 0;
- } else if (!strncmpi(bp, "corroded ", l=9) ||
- !strncmpi(bp, "rotted ", l=7)) {
- eroded2 = 1 + very;
- very = 0;
- } else if (!strncmpi(bp, "partly eaten ", l=13) ||
- !strncmpi(bp, "partially eaten ", l=16)) {
- halfeaten = 1;
- } else if (!strncmpi(bp, "historic ", l=9)) {
- ishistoric = 1;
- } else if (!strncmpi(bp, "diluted ", l=8)) {
- isdiluted = 1;
- } else if(!strncmpi(bp, "empty ", l=6)) {
- contents = EMPTY;
- } else break;
- bp += l;
- }
- if(!cnt) cnt = 1; /* %% what with "gems" etc. ? */
- if (strlen(bp) > 1) {
- if ((p = rindex(bp, '(')) != 0) {
- if (p > bp && p[-1] == ' ') p[-1] = 0;
- else *p = 0;
- p++;
- if (!strcmpi(p, "lit)")) {
- islit = 1;
- } else {
- spe = atoi(p);
- while (digit(*p)) p++;
- if (*p == ':') {
- p++;
- rechrg = spe;
- spe = atoi(p);
- while (digit(*p)) p++;
- }
- if (*p != ')') {
- spe = rechrg = 0;
- } else {
- spesgn = 1;
- p++;
- if (*p) Strcat(bp, p);
- }
- }
- }
- }
+ contents = UNDEFINED;
+ oclass = 0;
+ actualn = dn = un = 0;
+
+ if (!bp) goto any;
+ /* first, remove extra whitespace they may have typed */
+ (void)mungspaces(bp);
+ /* allow wishing for "nothing" to preserve wishless conduct...
+ [now requires "wand of nothing" if that's what was really wanted] */
+ if (!strcmpi(bp, "nothing") || !strcmpi(bp, "nil") ||
+ !strcmpi(bp, "none")) return no_wish;
+ /* save the [nearly] unmodified choice string */
+ Strcpy(fruitbuf, bp);
+
+ for(;;) {
+ register int l;
+
+ if (!bp || !*bp) goto any;
+ if (!strncmpi(bp, "an ", l=3) ||
+ !strncmpi(bp, "a ", l=2)) {
+ cnt = 1;
+ } else if (!strncmpi(bp, "the ", l=4)) {
+ ; /* just increment `bp' by `l' below */
+ } else if (!cnt && digit(*bp) && strcmp(bp, "0")) {
+ cnt = atoi(bp);
+ while(digit(*bp)) bp++;
+ while(*bp == ' ') bp++;
+ l = 0;
+ } else if (*bp == '+' || *bp == '-') {
+ spesgn = (*bp++ == '+') ? 1 : -1;
+ spe = atoi(bp);
+ while(digit(*bp)) bp++;
+ while(*bp == ' ') bp++;
+ l = 0;
+ } else if (!strncmpi(bp, "blessed ", l=8) ||
+ !strncmpi(bp, "holy ", l=5)) {
+ blessed = 1;
+ } else if (!strncmpi(bp, "cursed ", l=7) ||
+ !strncmpi(bp, "unholy ", l=7)) {
+ iscursed = 1;
+ } else if (!strncmpi(bp, "uncursed ", l=9)) {
+ uncursed = 1;
+ } else if (!strncmpi(bp, "rustproof ", l=10) ||
+ !strncmpi(bp, "erodeproof ", l=11) ||
+ !strncmpi(bp, "corrodeproof ", l=13) ||
+ !strncmpi(bp, "fixed ", l=6) ||
+ !strncmpi(bp, "fireproof ", l=10) ||
+ !strncmpi(bp, "rotproof ", l=9)) {
+ erodeproof = 1;
+ } else if (!strncmpi(bp,"lit ", l=4) ||
+ !strncmpi(bp,"burning ", l=8)) {
+ islit = 1;
+ } else if (!strncmpi(bp,"unlit ", l=6) ||
+ !strncmpi(bp,"extinguished ", l=13)) {
+ islit = 0;
+ /* "unlabeled" and "blank" are synonymous */
+ } else if (!strncmpi(bp,"unlabeled ", l=10) ||
+ !strncmpi(bp,"unlabelled ", l=11) ||
+ !strncmpi(bp,"blank ", l=6)) {
+ unlabeled = 1;
+ } else if(!strncmpi(bp, "poisoned ",l=9)) {
+ ispoisoned=1;
+ /* "trapped" recognized but not honored outside wizard mode */
+ } else if(!strncmpi(bp, "trapped ",l=8)) {
+ trapped = 0; /* undo any previous "untrapped" */
+ if (wizard) trapped = 1;
+ } else if(!strncmpi(bp, "untrapped ",l=10)) {
+ trapped = 2; /* not trapped */
+ } else if(!strncmpi(bp, "greased ",l=8)) {
+ isgreased=1;
+ } else if (!strncmpi(bp, "very ", l=5)) {
+ /* very rusted very heavy iron ball */
+ very = 1;
+ } else if (!strncmpi(bp, "thoroughly ", l=11)) {
+ very = 2;
+ } else if (!strncmpi(bp, "rusty ", l=6) ||
+ !strncmpi(bp, "rusted ", l=7) ||
+ !strncmpi(bp, "burnt ", l=6) ||
+ !strncmpi(bp, "burned ", l=7)) {
+ eroded = 1 + very;
+ very = 0;
+ } else if (!strncmpi(bp, "corroded ", l=9) ||
+ !strncmpi(bp, "rotted ", l=7)) {
+ eroded2 = 1 + very;
+ very = 0;
+ } else if (!strncmpi(bp, "partly eaten ", l=13) ||
+ !strncmpi(bp, "partially eaten ", l=16)) {
+ halfeaten = 1;
+ } else if (!strncmpi(bp, "historic ", l=9)) {
+ ishistoric = 1;
+ } else if (!strncmpi(bp, "diluted ", l=8)) {
+ isdiluted = 1;
+ } else if(!strncmpi(bp, "empty ", l=6)) {
+ contents = EMPTY;
+ } else break;
+ bp += l;
+ }
+ if(!cnt) cnt = 1; /* %% what with "gems" etc. ? */
+ if (strlen(bp) > 1) {
+ if ((p = rindex(bp, '(')) != 0) {
+ if (p > bp && p[-1] == ' ') p[-1] = 0;
+ else *p = 0;
+ p++;
+ if (!strcmpi(p, "lit)")) {
+ islit = 1;
+ } else {
+ spe = atoi(p);
+ while (digit(*p)) p++;
+ if (*p == ':') {
+ p++;
+ rechrg = spe;
+ spe = atoi(p);
+ while (digit(*p)) p++;
+ }
+ if (*p != ')') {
+ spe = rechrg = 0;
+ } else {
+ spesgn = 1;
+ p++;
+ if (*p) Strcat(bp, p);
+ }
+ }
+ }
+ }
/*
otmp->spe is type schar; so we don't want spe to be any bigger or smaller.
also, spe should always be positive -- some cheaters may try to confuse
atoi()
*/
- if (spe < 0) {
- spesgn = -1; /* cheaters get what they deserve */
- spe = abs(spe);
- }
- if (spe > SCHAR_LIM)
- spe = SCHAR_LIM;
- if (rechrg < 0 || rechrg > 7) rechrg = 7; /* recharge_limit */
-
- /* now we have the actual name, as delivered by xname, say
- green potions called whisky
- scrolls labeled "QWERTY"
- egg
- fortune cookies
- very heavy iron ball named hoei
- wand of wishing
- elven cloak
- */
- if ((p = strstri(bp, " named ")) != 0) {
- *p = 0;
- name = p+7;
- }
- if ((p = strstri(bp, " called ")) != 0) {
- *p = 0;
- un = p+8;
- /* "helmet called telepathy" is not "helmet" (a specific type)
- * "shield called reflection" is not "shield" (a general type)
- */
- for(i = 0; i < SIZE(o_ranges); i++)
- if(!strcmpi(bp, o_ranges[i].name)) {
- oclass = o_ranges[i].oclass;
- goto srch;
- }
- }
- if ((p = strstri(bp, " labeled ")) != 0) {
- *p = 0;
- dn = p+9;
- } else if ((p = strstri(bp, " labelled ")) != 0) {
- *p = 0;
- dn = p+10;
- }
- if ((p = strstri(bp, " of spinach")) != 0) {
- *p = 0;
- contents = SPINACH;
- }
-
- /*
- Skip over "pair of ", "pairs of", "set of" and "sets of".
-
- Accept "3 pair of boots" as well as "3 pairs of boots". It is valid
- English either way. See makeplural() for more on pair/pairs.
-
- We should only double count if the object in question is not
- refered to as a "pair of". E.g. We should double if the player
- types "pair of spears", but not if the player types "pair of
- lenses". Luckily (?) all objects that are refered to as pairs
- -- boots, gloves, and lenses -- are also not mergable, so cnt is
- ignored anyway.
- */
- if(!strncmpi(bp, "pair of ",8)) {
- bp += 8;
- cnt *= 2;
- } else if(cnt > 1 && !strncmpi(bp, "pairs of ",9)) {
- bp += 9;
- cnt *= 2;
- } else if (!strncmpi(bp, "set of ",7)) {
- bp += 7;
- } else if (!strncmpi(bp, "sets of ",8)) {
- bp += 8;
- }
-
- /*
- * Find corpse type using "of" (figurine of an orc, tin of orc meat)
- * Don't check if it's a wand or spellbook.
- * (avoid "wand/finger of death" confusion).
- */
- if (!strstri(bp, "wand ")
- && !strstri(bp, "spellbook ")
- && !strstri(bp, "finger ")) {
- if (((p = strstri(bp, "tin of ")) != 0) &&
- (tmp = tin_variety_txt(p+7, &tinv)) &&
- (mntmp = name_to_mon(p+7+tmp)) >= LOW_PM) {
- *(p+3) = 0;
- tvariety = tinv;
- } else if ((p = strstri(bp, " of ")) != 0
- && (mntmp = name_to_mon(p+4)) >= LOW_PM)
- *p = 0;
- }
- /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
- if (strncmpi(bp, "samurai sword", 13)) /* not the "samurai" monster! */
- if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */
- if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */
- if (strncmpi(bp, "master key", 10)) /* not the "master" rank */
- if (strncmpi(bp, "magenta", 7)) /* not the "mage" rank */
- if (mntmp < LOW_PM && strlen(bp) > 2 &&
- (mntmp = name_to_mon(bp)) >= LOW_PM) {
- int mntmptoo, mntmplen; /* double check for rank title */
- char *obp = bp;
- mntmptoo = title_to_mon(bp, (int *)0, &mntmplen);
- bp += mntmp != mntmptoo ? (int)strlen(mons[mntmp].mname) : mntmplen;
- if (*bp == ' ') bp++;
- else if (!strncmpi(bp, "s ", 2)) bp += 2;
- else if (!strncmpi(bp, "es ", 3)) bp += 3;
- else if (!*bp && !actualn && !dn && !un && !oclass) {
- /* no referent; they don't really mean a monster type */
- bp = obp;
- mntmp = NON_PM;
- }
- }
-
- /* first change to singular if necessary */
- if (*bp) {
- char *sng = makesingular(bp);
- if (strcmp(bp, sng)) {
- if (cnt == 1) cnt = 2;
- Strcpy(bp, sng);
- }
- }
-
- /* Alternate spellings (pick-ax, silver sabre, &c) */
+ if (spe < 0) {
+ spesgn = -1; /* cheaters get what they deserve */
+ spe = abs(spe);
+ }
+ if (spe > SCHAR_LIM)
+ spe = SCHAR_LIM;
+ if (rechrg < 0 || rechrg > 7) rechrg = 7; /* recharge_limit */
+
+ /* now we have the actual name, as delivered by xname, say
+ green potions called whisky
+ scrolls labeled "QWERTY"
+ egg
+ fortune cookies
+ very heavy iron ball named hoei
+ wand of wishing
+ elven cloak
+ */
+ if ((p = strstri(bp, " named ")) != 0) {
+ *p = 0;
+ name = p+7;
+ }
+ if ((p = strstri(bp, " called ")) != 0) {
+ *p = 0;
+ un = p+8;
+ /* "helmet called telepathy" is not "helmet" (a specific type)
+ * "shield called reflection" is not "shield" (a general type)
+ */
+ for(i = 0; i < SIZE(o_ranges); i++)
+ if(!strcmpi(bp, o_ranges[i].name)) {
+ oclass = o_ranges[i].oclass;
+ goto srch;
+ }
+ }
+ if ((p = strstri(bp, " labeled ")) != 0) {
+ *p = 0;
+ dn = p+9;
+ } else if ((p = strstri(bp, " labelled ")) != 0) {
+ *p = 0;
+ dn = p+10;
+ }
+ if ((p = strstri(bp, " of spinach")) != 0) {
+ *p = 0;
+ contents = SPINACH;
+ }
+
+ /*
+ Skip over "pair of ", "pairs of", "set of" and "sets of".
+
+ Accept "3 pair of boots" as well as "3 pairs of boots". It is valid
+ English either way. See makeplural() for more on pair/pairs.
+
+ We should only double count if the object in question is not
+ refered to as a "pair of". E.g. We should double if the player
+ types "pair of spears", but not if the player types "pair of
+ lenses". Luckily (?) all objects that are refered to as pairs
+ -- boots, gloves, and lenses -- are also not mergable, so cnt is
+ ignored anyway.
+ */
+ if(!strncmpi(bp, "pair of ",8)) {
+ bp += 8;
+ cnt *= 2;
+ } else if(cnt > 1 && !strncmpi(bp, "pairs of ",9)) {
+ bp += 9;
+ cnt *= 2;
+ } else if (!strncmpi(bp, "set of ",7)) {
+ bp += 7;
+ } else if (!strncmpi(bp, "sets of ",8)) {
+ bp += 8;
+ }
+
+ /*
+ * Find corpse type using "of" (figurine of an orc, tin of orc meat)
+ * Don't check if it's a wand or spellbook.
+ * (avoid "wand/finger of death" confusion).
+ */
+ if (!strstri(bp, "wand ")
+ && !strstri(bp, "spellbook ")
+ && !strstri(bp, "finger ")) {
+ if (((p = strstri(bp, "tin of ")) != 0) &&
+ (tmp = tin_variety_txt(p+7, &tinv)) &&
+ (mntmp = name_to_mon(p+7+tmp)) >= LOW_PM) {
+ *(p+3) = 0;
+ tvariety = tinv;
+ } else if ((p = strstri(bp, " of ")) != 0
+ && (mntmp = name_to_mon(p+4)) >= LOW_PM)
+ *p = 0;
+ }
+ /* Find corpse type w/o "of" (red dragon scale mail, yeti corpse) */
+ if (strncmpi(bp, "samurai sword", 13)) /* not the "samurai" monster! */
+ if (strncmpi(bp, "wizard lock", 11)) /* not the "wizard" monster! */
+ if (strncmpi(bp, "ninja-to", 8)) /* not the "ninja" rank */
+ if (strncmpi(bp, "master key", 10)) /* not the "master" rank */
+ if (strncmpi(bp, "magenta", 7)) /* not the "mage" rank */
+ if (mntmp < LOW_PM && strlen(bp) > 2 &&
+ (mntmp = name_to_mon(bp)) >= LOW_PM) {
+ int mntmptoo, mntmplen; /* double check for rank title */
+ char *obp = bp;
+ mntmptoo = title_to_mon(bp, (int *)0, &mntmplen);
+ bp += mntmp != mntmptoo ? (int)strlen(mons[mntmp].mname) : mntmplen;
+ if (*bp == ' ') bp++;
+ else if (!strncmpi(bp, "s ", 2)) bp += 2;
+ else if (!strncmpi(bp, "es ", 3)) bp += 3;
+ else if (!*bp && !actualn && !dn && !un && !oclass) {
+ /* no referent; they don't really mean a monster type */
+ bp = obp;
+ mntmp = NON_PM;
+ }
+ }
+
+ /* first change to singular if necessary */
+ if (*bp) {
+ char *sng = makesingular(bp);
+ if (strcmp(bp, sng)) {
+ if (cnt == 1) cnt = 2;
+ Strcpy(bp, sng);
+ }
+ }
+
+ /* Alternate spellings (pick-ax, silver sabre, &c) */
{
- struct alt_spellings *as = spellings;
-
- while (as->sp) {
- if (fuzzymatch(bp, as->sp, " -", TRUE)) {
- typ = as->ob;
- goto typfnd;
- }
- as++;
- }
- /* can't use spellings list for this one due to shuffling */
- if (!strncmpi(bp, "grey spell", 10))
- *(bp + 2) = 'a';
-
- if ((p = strstri(bp, "armour")) != 0) {
- /* skip past "armo", then copy remainer beyond "u" */
- p += 4;
- while ((*p = *(p + 1)) != '\0') ++p; /* self terminating */
- }
- }
-
- /* dragon scales - assumes order of dragons */
- if(!strcmpi(bp, "scales") &&
- mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON) {
- typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
- mntmp = NON_PM; /* no monster */
- goto typfnd;
- }
-
- p = eos(bp);
- if(!BSTRCMPI(bp, p-10, "holy water")) {
- typ = POT_WATER;
- if ((p-bp) >= 12 && *(p-12) == 'u')
- iscursed = 1; /* unholy water */
- else blessed = 1;
- goto typfnd;
- }
- if(unlabeled && !BSTRCMPI(bp, p-6, "scroll")) {
- typ = SCR_BLANK_PAPER;
- goto typfnd;
- }
- if(unlabeled && !BSTRCMPI(bp, p-9, "spellbook")) {
- typ = SPE_BLANK_PAPER;
- goto typfnd;
- }
- /*
- * NOTE: Gold pieces are handled as objects nowadays, and therefore
- * this section should probably be reconsidered as well as the entire
- * gold/money concept. Maybe we want to add other monetary units as
- * well in the future. (TH)
- */
- if(!BSTRCMPI(bp, p-10, "gold piece") || !BSTRCMPI(bp, p-7, "zorkmid") ||
- !strcmpi(bp, "gold") || !strcmpi(bp, "money") ||
- !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
- if (cnt > 5000 && !wizard) cnt = 5000;
- else if (cnt < 1) cnt = 1;
- otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
- otmp->quan = (long) cnt;
- otmp->owt = weight(otmp);
- context.botl = 1;
- return otmp;
- }
-
- /* check for single character object class code ("/" for wand, &c) */
- if (strlen(bp) == 1 &&
- (i = def_char_to_objclass(*bp)) < MAXOCLASSES &&
- i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) {
- oclass = i;
- goto any;
- }
-
- /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */
- /* false hits on, e.g., rings for "ring mail". */
- if(strncmpi(bp, "enchant ", 8) &&
- strncmpi(bp, "destroy ", 8) &&
- strncmpi(bp, "detect food", 11) &&
- strncmpi(bp, "food detection", 14) &&
- strncmpi(bp, "ring mail", 9) &&
- strncmpi(bp, "studded leather armor", 21) &&
- strncmpi(bp, "leather armor", 13) &&
- strncmpi(bp, "tooled horn", 11) &&
- strncmpi(bp, "food ration", 11) &&
- strncmpi(bp, "meat ring", 9)
- )
- for (i = 0; i < (int)(sizeof wrpsym); i++) {
- register int j = strlen(wrp[i]);
- if(!strncmpi(bp, wrp[i], j)){
- oclass = wrpsym[i];
- if(oclass != AMULET_CLASS) {
- bp += j;
- if(!strncmpi(bp, " of ", 4)) actualn = bp+4;
- /* else if(*bp) ?? */
- } else
- actualn = bp;
- goto srch;
- }
- if(!BSTRCMPI(bp, p-j, wrp[i])){
- oclass = wrpsym[i];
- p -= j;
- *p = 0;
- if(p > bp && p[-1] == ' ') p[-1] = 0;
- actualn = dn = bp;
- goto srch;
- }
- }
-
- /* Wishing in wizard mode can create traps and furniture.
- * Part I: distinguish between trap and object for the two
- * types of traps which have corresponding objects: bear trap
- * and land mine. "beartrap" (object) and "bear trap" (trap)
- * have a difference in spelling which we used to exploit by
- * adding a special case in wishymatch(), but "land mine" is
- * spelled the same either way so needs different handing.
- * Since we need something else for land mine, we've dropped
- * the bear trap hack so that both are handled exactly the
- * same. To get an armed trap instead of a disarmed object,
- * the player can prefix either the object name or the trap
- * name with "trapped " (which ordinarily applies to chests
- * and tins), or append something--anything at all except for
- * " object", but " trap" is suggested--to either the trap
- * name or the object name.
- */
- if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) {
- boolean beartrap = (lowc(*bp) == 'b');
- char *zp = bp + 4; /* skip "bear"/"land" */
-
- if (*zp == ' ') ++zp; /* embedded space is optional */
- if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) {
- zp += 4;
- if (trapped == 2 || !strcmpi(zp, " object")) {
- /* "untrapped <foo>" or "<foo> object" */
- typ = beartrap ? BEARTRAP : LAND_MINE;
- goto typfnd;
- } else if (trapped == 1 || *zp != '\0') {
- /* "trapped <foo>" or "<foo> trap" (actually "<foo>*") */
- int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE);
-
- /* use canonical trap spelling, skip object matching */
- Strcpy(bp, defsyms[idx].explanation);
- goto wiztrap;
- }
- /* [no prefix or suffix; we're going to end up matching
- the object name and getting a disarmed trap object] */
- }
- }
+ struct alt_spellings *as = spellings;
+
+ while (as->sp) {
+ if (fuzzymatch(bp, as->sp, " -", TRUE)) {
+ typ = as->ob;
+ goto typfnd;
+ }
+ as++;
+ }
+ /* can't use spellings list for this one due to shuffling */
+ if (!strncmpi(bp, "grey spell", 10))
+ *(bp + 2) = 'a';
+
+ if ((p = strstri(bp, "armour")) != 0) {
+ /* skip past "armo", then copy remainer beyond "u" */
+ p += 4;
+ while ((*p = *(p + 1)) != '\0') ++p; /* self terminating */
+ }
+ }
+
+ /* dragon scales - assumes order of dragons */
+ if(!strcmpi(bp, "scales") &&
+ mntmp >= PM_GRAY_DRAGON && mntmp <= PM_YELLOW_DRAGON) {
+ typ = GRAY_DRAGON_SCALES + mntmp - PM_GRAY_DRAGON;
+ mntmp = NON_PM; /* no monster */
+ goto typfnd;
+ }
+
+ p = eos(bp);
+ if(!BSTRCMPI(bp, p-10, "holy water")) {
+ typ = POT_WATER;
+ if ((p-bp) >= 12 && *(p-12) == 'u')
+ iscursed = 1; /* unholy water */
+ else blessed = 1;
+ goto typfnd;
+ }
+ if(unlabeled && !BSTRCMPI(bp, p-6, "scroll")) {
+ typ = SCR_BLANK_PAPER;
+ goto typfnd;
+ }
+ if(unlabeled && !BSTRCMPI(bp, p-9, "spellbook")) {
+ typ = SPE_BLANK_PAPER;
+ goto typfnd;
+ }
+ /*
+ * NOTE: Gold pieces are handled as objects nowadays, and therefore
+ * this section should probably be reconsidered as well as the entire
+ * gold/money concept. Maybe we want to add other monetary units as
+ * well in the future. (TH)
+ */
+ if(!BSTRCMPI(bp, p-10, "gold piece") || !BSTRCMPI(bp, p-7, "zorkmid") ||
+ !strcmpi(bp, "gold") || !strcmpi(bp, "money") ||
+ !strcmpi(bp, "coin") || *bp == GOLD_SYM) {
+ if (cnt > 5000 && !wizard) cnt = 5000;
+ else if (cnt < 1) cnt = 1;
+ otmp = mksobj(GOLD_PIECE, FALSE, FALSE);
+ otmp->quan = (long) cnt;
+ otmp->owt = weight(otmp);
+ context.botl = 1;
+ return otmp;
+ }
+
+ /* check for single character object class code ("/" for wand, &c) */
+ if (strlen(bp) == 1 &&
+ (i = def_char_to_objclass(*bp)) < MAXOCLASSES &&
+ i > ILLOBJ_CLASS && (i != VENOM_CLASS || wizard)) {
+ oclass = i;
+ goto any;
+ }
+
+ /* Search for class names: XXXXX potion, scroll of XXXXX. Avoid */
+ /* false hits on, e.g., rings for "ring mail". */
+ if(strncmpi(bp, "enchant ", 8) &&
+ strncmpi(bp, "destroy ", 8) &&
+ strncmpi(bp, "detect food", 11) &&
+ strncmpi(bp, "food detection", 14) &&
+ strncmpi(bp, "ring mail", 9) &&
+ strncmpi(bp, "studded leather armor", 21) &&
+ strncmpi(bp, "leather armor", 13) &&
+ strncmpi(bp, "tooled horn", 11) &&
+ strncmpi(bp, "food ration", 11) &&
+ strncmpi(bp, "meat ring", 9)
+ )
+ for (i = 0; i < (int)(sizeof wrpsym); i++) {
+ register int j = strlen(wrp[i]);
+ if(!strncmpi(bp, wrp[i], j)){
+ oclass = wrpsym[i];
+ if(oclass != AMULET_CLASS) {
+ bp += j;
+ if(!strncmpi(bp, " of ", 4)) actualn = bp+4;
+ /* else if(*bp) ?? */
+ } else
+ actualn = bp;
+ goto srch;
+ }
+ if(!BSTRCMPI(bp, p-j, wrp[i])){
+ oclass = wrpsym[i];
+ p -= j;
+ *p = 0;
+ if(p > bp && p[-1] == ' ') p[-1] = 0;
+ actualn = dn = bp;
+ goto srch;
+ }
+ }
+
+ /* Wishing in wizard mode can create traps and furniture.
+ * Part I: distinguish between trap and object for the two
+ * types of traps which have corresponding objects: bear trap
+ * and land mine. "beartrap" (object) and "bear trap" (trap)
+ * have a difference in spelling which we used to exploit by
+ * adding a special case in wishymatch(), but "land mine" is
+ * spelled the same either way so needs different handing.
+ * Since we need something else for land mine, we've dropped
+ * the bear trap hack so that both are handled exactly the
+ * same. To get an armed trap instead of a disarmed object,
+ * the player can prefix either the object name or the trap
+ * name with "trapped " (which ordinarily applies to chests
+ * and tins), or append something--anything at all except for
+ * " object", but " trap" is suggested--to either the trap
+ * name or the object name.
+ */
+ if (wizard && (!strncmpi(bp, "bear", 4) || !strncmpi(bp, "land", 4))) {
+ boolean beartrap = (lowc(*bp) == 'b');
+ char *zp = bp + 4; /* skip "bear"/"land" */
+
+ if (*zp == ' ') ++zp; /* embedded space is optional */
+ if (!strncmpi(zp, beartrap ? "trap" : "mine", 4)) {
+ zp += 4;
+ if (trapped == 2 || !strcmpi(zp, " object")) {
+ /* "untrapped <foo>" or "<foo> object" */
+ typ = beartrap ? BEARTRAP : LAND_MINE;
+ goto typfnd;
+ } else if (trapped == 1 || *zp != '\0') {
+ /* "trapped <foo>" or "<foo> trap" (actually "<foo>*") */
+ int idx = trap_to_defsym(beartrap ? BEAR_TRAP : LANDMINE);
+
+ /* use canonical trap spelling, skip object matching */
+ Strcpy(bp, defsyms[idx].explanation);
+ goto wiztrap;
+ }
+ /* [no prefix or suffix; we're going to end up matching
+ the object name and getting a disarmed trap object] */
+ }
+ }
retry:
- /* "grey stone" check must be before general "stone" */
- for (i = 0; i < SIZE(o_ranges); i++)
- if(!strcmpi(bp, o_ranges[i].name)) {
- typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
- goto typfnd;
- }
-
- if (!BSTRCMPI(bp, p-6, " stone")) {
- p[-6] = 0;
- oclass = GEM_CLASS;
- dn = actualn = bp;
- goto srch;
- } else if (!strcmpi(bp, "looking glass")) {
- ; /* avoid false hit on "* glass" */
- } else if (!BSTRCMPI(bp, p-6, " glass") || !strcmpi(bp, "glass")) {
- register char *g = bp;
- if (strstri(g, "broken")) return (struct obj *)0;
- if (!strncmpi(g, "worthless ", 10)) g += 10;
- if (!strncmpi(g, "piece of ", 9)) g += 9;
- if (!strncmpi(g, "colored ", 8)) g += 8;
- else if (!strncmpi(g, "coloured ", 9)) g += 9;
- if (!strcmpi(g, "glass")) { /* choose random color */
- /* 9 different kinds */
- typ = LAST_GEM + rnd(9);
- if (objects[typ].oc_class == GEM_CLASS) goto typfnd;
- else typ = 0; /* somebody changed objects[]? punt */
- } else { /* try to construct canonical form */
- char tbuf[BUFSZ];
- Strcpy(tbuf, "worthless piece of ");
- Strcat(tbuf, g); /* assume it starts with the color */
- Strcpy(bp, tbuf);
- }
- }
-
- actualn = bp;
- if (!dn) dn = actualn; /* ex. "skull cap" */
+ /* "grey stone" check must be before general "stone" */
+ for (i = 0; i < SIZE(o_ranges); i++)
+ if(!strcmpi(bp, o_ranges[i].name)) {
+ typ = rnd_class(o_ranges[i].f_o_range, o_ranges[i].l_o_range);
+ goto typfnd;
+ }
+
+ if (!BSTRCMPI(bp, p-6, " stone")) {
+ p[-6] = 0;
+ oclass = GEM_CLASS;
+ dn = actualn = bp;
+ goto srch;
+ } else if (!strcmpi(bp, "looking glass")) {
+ ; /* avoid false hit on "* glass" */
+ } else if (!BSTRCMPI(bp, p-6, " glass") || !strcmpi(bp, "glass")) {
+ register char *g = bp;
+ if (strstri(g, "broken")) return (struct obj *)0;
+ if (!strncmpi(g, "worthless ", 10)) g += 10;
+ if (!strncmpi(g, "piece of ", 9)) g += 9;
+ if (!strncmpi(g, "colored ", 8)) g += 8;
+ else if (!strncmpi(g, "coloured ", 9)) g += 9;
+ if (!strcmpi(g, "glass")) { /* choose random color */
+ /* 9 different kinds */
+ typ = LAST_GEM + rnd(9);
+ if (objects[typ].oc_class == GEM_CLASS) goto typfnd;
+ else typ = 0; /* somebody changed objects[]? punt */
+ } else { /* try to construct canonical form */
+ char tbuf[BUFSZ];
+ Strcpy(tbuf, "worthless piece of ");
+ Strcat(tbuf, g); /* assume it starts with the color */
+ Strcpy(bp, tbuf);
+ }
+ }
+
+ actualn = bp;
+ if (!dn) dn = actualn; /* ex. "skull cap" */
srch:
- /* check real names of gems first */
- if(!oclass && actualn) {
- for(i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
- register const char *zn;
-
- if((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) {
- typ = i;
- goto typfnd;
- }
- }
- }
- i = oclass ? bases[(int)oclass] : 1;
- while(i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass)){
- register const char *zn;
-
- if (actualn && (zn = OBJ_NAME(objects[i])) != 0 &&
- wishymatch(actualn, zn, TRUE)) {
- typ = i;
- goto typfnd;
- }
- if (dn && (zn = OBJ_DESCR(objects[i])) != 0 &&
- wishymatch(dn, zn, FALSE)) {
- /* don't match extra descriptions (w/o real name) */
- if (!OBJ_NAME(objects[i])) return (struct obj *)0;
- typ = i;
- goto typfnd;
- }
- if (un && (zn = objects[i].oc_uname) != 0 &&
- wishymatch(un, zn, FALSE)) {
- typ = i;
- goto typfnd;
- }
- i++;
- }
- if (actualn) {
- struct Jitem *j = Japanese_items;
- while(j->item) {
- if (actualn && !strcmpi(actualn, j->name)) {
- typ = j->item;
- goto typfnd;
- }
- j++;
- }
- }
- /* if we've stripped off "armor" and failed to match anything
- in objects[], append "mail" and try again to catch misnamed
- requests like "plate armor" and "yellow dragon scale armor" */
- if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) {
- /* modifying bp's string is ok; we're about to resort
- to random armor if this also fails to match anything */
- Strcat(bp, " mail");
- goto retry;
- }
- if (!strcmpi(bp, "spinach")) {
- contents = SPINACH;
- typ = TIN;
- goto typfnd;
- }
- /* Note: not strcmpi. 2 fruits, one capital, one not, are possible.
- Also not strncmp. We used to ignore trailing text with it, but
- that resulted in "grapefruit" matching "grape" if the latter came
- earlier than the former in the fruit list. */
- {
- char *fp;
- int l, cntf;
- int blessedf, iscursedf, uncursedf, halfeatenf;
-
- blessedf = iscursedf = uncursedf = halfeatenf = 0;
- cntf = 0;
-
- fp = fruitbuf;
- for(;;) {
- if (!fp || !*fp) break;
- if (!strncmpi(fp, "an ", l=3) ||
- !strncmpi(fp, "a ", l=2)) {
- cntf = 1;
- } else if (!cntf && digit(*fp)) {
- cntf = atoi(fp);
- while(digit(*fp)) fp++;
- while(*fp == ' ') fp++;
- l = 0;
- } else if (!strncmpi(fp, "blessed ", l=8)) {
- blessedf = 1;
- } else if (!strncmpi(fp, "cursed ", l=7)) {
- iscursedf = 1;
- } else if (!strncmpi(fp, "uncursed ", l=9)) {
- uncursedf = 1;
- } else if (!strncmpi(fp, "partly eaten ", l=13) ||
- !strncmpi(fp, "partially eaten ", l=16)) {
- halfeatenf = 1;
- } else break;
- fp += l;
- }
-
- for(f=ffruit; f; f = f->nextf) {
- /* match type: 0=none, 1=exact, 2=singular, 3=plural */
- int ftyp = 0;
-
- if (!strcmp(fp, f->fname)) ftyp = 1;
- else if (!strcmp(fp, makesingular(f->fname))) ftyp = 2;
- else if (!strcmp(fp, makeplural(f->fname))) ftyp = 3;
- if (ftyp) {
- typ = SLIME_MOLD;
- blessed = blessedf;
- iscursed = iscursedf;
- uncursed = uncursedf;
- halfeaten = halfeatenf;
- /* adjust count if user explicitly asked for
- singular amount (can't happen unless fruit
- has been given an already pluralized name)
- or for plural amount */
- if (ftyp == 2 && !cntf) cntf = 1;
- else if (ftyp == 3 && !cntf) cntf = 2;
- cnt = cntf;
- ftype = f->fid;
- goto typfnd;
- }
- }
- }
-
- if(!oclass && actualn) {
- short objtyp;
-
- /* Perhaps it's an artifact specified by name, not type */
- name = artifact_name(actualn, &objtyp);
- if(name) {
- typ = objtyp;
- goto typfnd;
- }
- }
- /* Let wizards wish for traps and furniture.
- * Must come after objects check so wizards can still wish for
- * trap objects like beartraps.
- * Disallow such topology tweaks for WIZKIT startup wishes.
- */
+ /* check real names of gems first */
+ if(!oclass && actualn) {
+ for(i = bases[GEM_CLASS]; i <= LAST_GEM; i++) {
+ register const char *zn;
+
+ if((zn = OBJ_NAME(objects[i])) && !strcmpi(actualn, zn)) {
+ typ = i;
+ goto typfnd;
+ }
+ }
+ }
+ i = oclass ? bases[(int)oclass] : 1;
+ while(i < NUM_OBJECTS && (!oclass || objects[i].oc_class == oclass)){
+ register const char *zn;
+
+ if (actualn && (zn = OBJ_NAME(objects[i])) != 0 &&
+ wishymatch(actualn, zn, TRUE)) {
+ typ = i;
+ goto typfnd;
+ }
+ if (dn && (zn = OBJ_DESCR(objects[i])) != 0 &&
+ wishymatch(dn, zn, FALSE)) {
+ /* don't match extra descriptions (w/o real name) */
+ if (!OBJ_NAME(objects[i])) return (struct obj *)0;
+ typ = i;
+ goto typfnd;
+ }
+ if (un && (zn = objects[i].oc_uname) != 0 &&
+ wishymatch(un, zn, FALSE)) {
+ typ = i;
+ goto typfnd;
+ }
+ i++;
+ }
+ if (actualn) {
+ struct Jitem *j = Japanese_items;
+ while(j->item) {
+ if (actualn && !strcmpi(actualn, j->name)) {
+ typ = j->item;
+ goto typfnd;
+ }
+ j++;
+ }
+ }
+ /* if we've stripped off "armor" and failed to match anything
+ in objects[], append "mail" and try again to catch misnamed
+ requests like "plate armor" and "yellow dragon scale armor" */
+ if (oclass == ARMOR_CLASS && !strstri(bp, "mail")) {
+ /* modifying bp's string is ok; we're about to resort
+ to random armor if this also fails to match anything */
+ Strcat(bp, " mail");
+ goto retry;
+ }
+ if (!strcmpi(bp, "spinach")) {
+ contents = SPINACH;
+ typ = TIN;
+ goto typfnd;
+ }
+ /* Note: not strcmpi. 2 fruits, one capital, one not, are possible.
+ Also not strncmp. We used to ignore trailing text with it, but
+ that resulted in "grapefruit" matching "grape" if the latter came
+ earlier than the former in the fruit list. */
+ {
+ char *fp;
+ int l, cntf;
+ int blessedf, iscursedf, uncursedf, halfeatenf;
+
+ blessedf = iscursedf = uncursedf = halfeatenf = 0;
+ cntf = 0;
+
+ fp = fruitbuf;
+ for(;;) {
+ if (!fp || !*fp) break;
+ if (!strncmpi(fp, "an ", l=3) ||
+ !strncmpi(fp, "a ", l=2)) {
+ cntf = 1;
+ } else if (!cntf && digit(*fp)) {
+ cntf = atoi(fp);
+ while(digit(*fp)) fp++;
+ while(*fp == ' ') fp++;
+ l = 0;
+ } else if (!strncmpi(fp, "blessed ", l=8)) {
+ blessedf = 1;
+ } else if (!strncmpi(fp, "cursed ", l=7)) {
+ iscursedf = 1;
+ } else if (!strncmpi(fp, "uncursed ", l=9)) {
+ uncursedf = 1;
+ } else if (!strncmpi(fp, "partly eaten ", l=13) ||
+ !strncmpi(fp, "partially eaten ", l=16)) {
+ halfeatenf = 1;
+ } else break;
+ fp += l;
+ }
+
+ for(f=ffruit; f; f = f->nextf) {
+ /* match type: 0=none, 1=exact, 2=singular, 3=plural */
+ int ftyp = 0;
+
+ if (!strcmp(fp, f->fname)) ftyp = 1;
+ else if (!strcmp(fp, makesingular(f->fname))) ftyp = 2;
+ else if (!strcmp(fp, makeplural(f->fname))) ftyp = 3;
+ if (ftyp) {
+ typ = SLIME_MOLD;
+ blessed = blessedf;
+ iscursed = iscursedf;
+ uncursed = uncursedf;
+ halfeaten = halfeatenf;
+ /* adjust count if user explicitly asked for
+ singular amount (can't happen unless fruit
+ has been given an already pluralized name)
+ or for plural amount */
+ if (ftyp == 2 && !cntf) cntf = 1;
+ else if (ftyp == 3 && !cntf) cntf = 2;
+ cnt = cntf;
+ ftype = f->fid;
+ goto typfnd;
+ }
+ }
+ }
+
+ if(!oclass && actualn) {
+ short objtyp;
+
+ /* Perhaps it's an artifact specified by name, not type */
+ name = artifact_name(actualn, &objtyp);
+ if(name) {
+ typ = objtyp;
+ goto typfnd;
+ }
+ }
+ /* Let wizards wish for traps and furniture.
+ * Must come after objects check so wizards can still wish for
+ * trap objects like beartraps.
+ * Disallow such topology tweaks for WIZKIT startup wishes.
+ */
wiztrap:
- if (wizard && !program_state.wizkit_wishing) {
- struct rm *lev;
- int trap, x = u.ux, y = u.uy;
-
- for (trap = NO_TRAP+1; trap < TRAPNUM; trap++) {
- struct trap *t;
- const char *tname;
-
- tname = defsyms[trap_to_defsym(trap)].explanation;
- if (strncmpi(tname, bp, strlen(tname))) continue;
- /* found it; avoid stupid mistakes */
- if ((trap == TRAPDOOR || trap == HOLE) &&
- !Can_fall_thru(&u.uz)) trap = ROCKTRAP;
- if ((t = maketrap(x, y, trap)) != 0) {
- trap = t->ttyp;
- tname = defsyms[trap_to_defsym(trap)].explanation;
- pline("%s%s.", An(tname),
- (trap != MAGIC_PORTAL) ? "" : " to nowhere");
- } else
- pline("Creation of %s failed.", an(tname));
- return(&zeroobj);
- }
-
- /* furniture and terrain */
- lev = &levl[x][y];
- p = eos(bp);
- if (!BSTRCMPI(bp, p-8, "fountain")) {
- lev->typ = FOUNTAIN;
- level.flags.nfountains++;
- if(!strncmpi(bp, "magic ", 6)) lev->blessedftn = 1;
- pline("A %sfountain.", lev->blessedftn ? "magic " : "");
- newsym(x, y);
- return(&zeroobj);
- }
- if (!BSTRCMPI(bp, p-6, "throne")) {
- lev->typ = THRONE;
- pline("A throne.");
- newsym(x, y);
- return(&zeroobj);
- }
- if (!BSTRCMPI(bp, p-4, "sink")) {
- lev->typ = SINK;
- level.flags.nsinks++;
- pline("A sink.");
- newsym(x, y);
- return &zeroobj;
- }
- /* ("water" matches "potion of water" rather than terrain) */
- if (!BSTRCMPI(bp, p-4, "pool") || !BSTRCMPI(bp, p-4, "moat")) {
- lev->typ = !BSTRCMPI(bp, p-4, "pool") ? POOL : MOAT;
- del_engr_at(x, y);
- pline("A %s.", (lev->typ == POOL) ? "pool" : "moat");
- /* Must manually make kelp! */
- water_damage_chain(level.objects[x][y], TRUE);
- newsym(x, y);
- return &zeroobj;
- }
- if (!BSTRCMPI(bp, p-4, "lava")) { /* also matches "molten lava" */
- lev->typ = LAVAPOOL;
- del_engr_at(x, y);
- pline("A pool of molten lava.");
- if (!(Levitation || Flying)) (void) lava_effects();
- newsym(x, y);
- return &zeroobj;
- }
-
- if (!BSTRCMPI(bp, p-5, "altar")) {
- aligntyp al;
-
- lev->typ = ALTAR;
- if(!strncmpi(bp, "chaotic ", 8))
- al = A_CHAOTIC;
- else if(!strncmpi(bp, "neutral ", 8))
- al = A_NEUTRAL;
- else if(!strncmpi(bp, "lawful ", 7))
- al = A_LAWFUL;
- else if(!strncmpi(bp, "unaligned ", 10))
- al = A_NONE;
- else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
- al = (!rn2(6)) ? A_NONE : rn2((int)A_LAWFUL+2) - 1;
- lev->altarmask = Align2amask(al);
- pline("%s altar.", An(align_str(al)));
- newsym(x, y);
- return(&zeroobj);
- }
-
- if (!BSTRCMPI(bp, p-5, "grave") ||
- !BSTRCMPI(bp, p-9, "headstone")) {
- make_grave(x, y, (char *)0);
- pline("%s.", IS_GRAVE(lev->typ) ? "A grave" :
- "Can't place a grave here");
- newsym(x, y);
- return(&zeroobj);
- }
-
- if (!BSTRCMPI(bp, p-4, "tree")) {
- lev->typ = TREE;
- pline("A tree.");
- newsym(x, y);
- block_point(x, y);
- return &zeroobj;
- }
-
- if (!BSTRCMPI(bp, p-4, "bars")) {
- lev->typ = IRONBARS;
- pline("Iron bars.");
- newsym(x, y);
- return &zeroobj;
- }
- }
-
- if(!oclass) return((struct obj *)0);
+ if (wizard && !program_state.wizkit_wishing) {
+ struct rm *lev;
+ int trap, x = u.ux, y = u.uy;
+
+ for (trap = NO_TRAP+1; trap < TRAPNUM; trap++) {
+ struct trap *t;
+ const char *tname;
+
+ tname = defsyms[trap_to_defsym(trap)].explanation;
+ if (strncmpi(tname, bp, strlen(tname))) continue;
+ /* found it; avoid stupid mistakes */
+ if ((trap == TRAPDOOR || trap == HOLE) &&
+ !Can_fall_thru(&u.uz)) trap = ROCKTRAP;
+ if ((t = maketrap(x, y, trap)) != 0) {
+ trap = t->ttyp;
+ tname = defsyms[trap_to_defsym(trap)].explanation;
+ pline("%s%s.", An(tname),
+ (trap != MAGIC_PORTAL) ? "" : " to nowhere");
+ } else
+ pline("Creation of %s failed.", an(tname));
+ return(&zeroobj);
+ }
+
+ /* furniture and terrain */
+ lev = &levl[x][y];
+ p = eos(bp);
+ if (!BSTRCMPI(bp, p-8, "fountain")) {
+ lev->typ = FOUNTAIN;
+ level.flags.nfountains++;
+ if(!strncmpi(bp, "magic ", 6)) lev->blessedftn = 1;
+ pline("A %sfountain.", lev->blessedftn ? "magic " : "");
+ newsym(x, y);
+ return(&zeroobj);
+ }
+ if (!BSTRCMPI(bp, p-6, "throne")) {
+ lev->typ = THRONE;
+ pline("A throne.");
+ newsym(x, y);
+ return(&zeroobj);
+ }
+ if (!BSTRCMPI(bp, p-4, "sink")) {
+ lev->typ = SINK;
+ level.flags.nsinks++;
+ pline("A sink.");
+ newsym(x, y);
+ return &zeroobj;
+ }
+ /* ("water" matches "potion of water" rather than terrain) */
+ if (!BSTRCMPI(bp, p-4, "pool") || !BSTRCMPI(bp, p-4, "moat")) {
+ lev->typ = !BSTRCMPI(bp, p-4, "pool") ? POOL : MOAT;
+ del_engr_at(x, y);
+ pline("A %s.", (lev->typ == POOL) ? "pool" : "moat");
+ /* Must manually make kelp! */
+ water_damage_chain(level.objects[x][y], TRUE);
+ newsym(x, y);
+ return &zeroobj;
+ }
+ if (!BSTRCMPI(bp, p-4, "lava")) { /* also matches "molten lava" */
+ lev->typ = LAVAPOOL;
+ del_engr_at(x, y);
+ pline("A pool of molten lava.");
+ if (!(Levitation || Flying)) (void) lava_effects();
+ newsym(x, y);
+ return &zeroobj;
+ }
+
+ if (!BSTRCMPI(bp, p-5, "altar")) {
+ aligntyp al;
+
+ lev->typ = ALTAR;
+ if(!strncmpi(bp, "chaotic ", 8))
+ al = A_CHAOTIC;
+ else if(!strncmpi(bp, "neutral ", 8))
+ al = A_NEUTRAL;
+ else if(!strncmpi(bp, "lawful ", 7))
+ al = A_LAWFUL;
+ else if(!strncmpi(bp, "unaligned ", 10))
+ al = A_NONE;
+ else /* -1 - A_CHAOTIC, 0 - A_NEUTRAL, 1 - A_LAWFUL */
+ al = (!rn2(6)) ? A_NONE : rn2((int)A_LAWFUL+2) - 1;
+ lev->altarmask = Align2amask(al);
+ pline("%s altar.", An(align_str(al)));
+ newsym(x, y);
+ return(&zeroobj);
+ }
+
+ if (!BSTRCMPI(bp, p-5, "grave") ||
+ !BSTRCMPI(bp, p-9, "headstone")) {
+ make_grave(x, y, (char *)0);
+ pline("%s.", IS_GRAVE(lev->typ) ? "A grave" :
+ "Can't place a grave here");
+ newsym(x, y);
+ return(&zeroobj);
+ }
+
+ if (!BSTRCMPI(bp, p-4, "tree")) {
+ lev->typ = TREE;
+ pline("A tree.");
+ newsym(x, y);
+ block_point(x, y);
+ return &zeroobj;
+ }
+
+ if (!BSTRCMPI(bp, p-4, "bars")) {
+ lev->typ = IRONBARS;
+ pline("Iron bars.");
+ newsym(x, y);
+ return &zeroobj;
+ }
+ }
+
+ if(!oclass) return((struct obj *)0);
any:
- if(!oclass) oclass = wrpsym[rn2((int)sizeof(wrpsym))];
+ if(!oclass) oclass = wrpsym[rn2((int)sizeof(wrpsym))];
typfnd:
- if (typ) oclass = objects[typ].oc_class;
-
- /* handle some objects that are only allowed in wizard mode */
- if (typ && !wizard) {
- switch (typ) {
- case AMULET_OF_YENDOR:
- typ = FAKE_AMULET_OF_YENDOR;
- break;
- case CANDELABRUM_OF_INVOCATION:
- typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
- break;
- case BELL_OF_OPENING:
- typ = BELL;
- break;
- case SPE_BOOK_OF_THE_DEAD:
- typ = SPE_BLANK_PAPER;
- break;
- case MAGIC_LAMP:
- typ = OIL_LAMP;
- break;
- default:
- /* catch any other non-wishable objects (venom) */
- if (objects[typ].oc_nowish) return ((struct obj *)0);
- break;
- }
- }
-
- /*
- * Create the object, then fine-tune it.
- */
- otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE);
- typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */
-
- if (islit &&
- (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN ||
- Is_candle(otmp) || typ == POT_OIL)) {
- place_object(otmp, u.ux, u.uy); /* make it viable light source */
- begin_burn(otmp, FALSE);
- obj_extract_self(otmp); /* now release it for caller's use */
- }
-
- /* if player specified a reasonable count, maybe honor it */
- if (cnt > 0 && objects[typ].oc_merge &&
- (wizard || cnt < rnd(6) ||
- (cnt <= 7 && Is_candle(otmp)) ||
- (cnt <= 20 &&
- ((oclass == WEAPON_CLASS && is_ammo(otmp))
- || typ == ROCK || is_missile(otmp)))))
- otmp->quan = (long) cnt;
-
- if (oclass == VENOM_CLASS) otmp->spe = 1;
-
- if (spesgn == 0) {
- spe = otmp->spe;
- } else if (wizard) {
- ; /* no alteration to spe */
- } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS ||
- is_weptool(otmp) ||
- (oclass==RING_CLASS && objects[typ].oc_charged)) {
- if(spe > rnd(5) && spe > otmp->spe) spe = 0;
- if(spe > 2 && Luck < 0) spesgn = -1;
- } else {
- if (oclass == WAND_CLASS) {
- if (spe > 1 && spesgn == -1) spe = 1;
- } else {
- if (spe > 0 && spesgn == -1) spe = 0;
- }
- if (spe > otmp->spe) spe = otmp->spe;
- }
-
- if (spesgn == -1) spe = -spe;
-
- /* set otmp->spe. This may, or may not, use spe... */
- switch (typ) {
- case TIN: if (contents==EMPTY) {
- otmp->corpsenm = NON_PM;
- otmp->spe = 0;
- } else if (contents==SPINACH) {
- otmp->corpsenm = NON_PM;
- otmp->spe = 1;
- }
- break;
- case SLIME_MOLD: otmp->spe = ftype;
- /* Fall through */
- case SKELETON_KEY: case CHEST: case LARGE_BOX:
- case HEAVY_IRON_BALL: case IRON_CHAIN: case STATUE:
- /* otmp->cobj already done in mksobj() */
- break;
+ if (typ) oclass = objects[typ].oc_class;
+
+ /* handle some objects that are only allowed in wizard mode */
+ if (typ && !wizard) {
+ switch (typ) {
+ case AMULET_OF_YENDOR:
+ typ = FAKE_AMULET_OF_YENDOR;
+ break;
+ case CANDELABRUM_OF_INVOCATION:
+ typ = rnd_class(TALLOW_CANDLE, WAX_CANDLE);
+ break;
+ case BELL_OF_OPENING:
+ typ = BELL;
+ break;
+ case SPE_BOOK_OF_THE_DEAD:
+ typ = SPE_BLANK_PAPER;
+ break;
+ case MAGIC_LAMP:
+ typ = OIL_LAMP;
+ break;
+ default:
+ /* catch any other non-wishable objects (venom) */
+ if (objects[typ].oc_nowish) return ((struct obj *)0);
+ break;
+ }
+ }
+
+ /*
+ * Create the object, then fine-tune it.
+ */
+ otmp = typ ? mksobj(typ, TRUE, FALSE) : mkobj(oclass, FALSE);
+ typ = otmp->otyp, oclass = otmp->oclass; /* what we actually got */
+
+ if (islit &&
+ (typ == OIL_LAMP || typ == MAGIC_LAMP || typ == BRASS_LANTERN ||
+ Is_candle(otmp) || typ == POT_OIL)) {
+ place_object(otmp, u.ux, u.uy); /* make it viable light source */
+ begin_burn(otmp, FALSE);
+ obj_extract_self(otmp); /* now release it for caller's use */
+ }
+
+ /* if player specified a reasonable count, maybe honor it */
+ if (cnt > 0 && objects[typ].oc_merge &&
+ (wizard || cnt < rnd(6) ||
+ (cnt <= 7 && Is_candle(otmp)) ||
+ (cnt <= 20 &&
+ ((oclass == WEAPON_CLASS && is_ammo(otmp))
+ || typ == ROCK || is_missile(otmp)))))
+ otmp->quan = (long) cnt;
+
+ if (oclass == VENOM_CLASS) otmp->spe = 1;
+
+ if (spesgn == 0) {
+ spe = otmp->spe;
+ } else if (wizard) {
+ ; /* no alteration to spe */
+ } else if (oclass == ARMOR_CLASS || oclass == WEAPON_CLASS ||
+ is_weptool(otmp) ||
+ (oclass==RING_CLASS && objects[typ].oc_charged)) {
+ if(spe > rnd(5) && spe > otmp->spe) spe = 0;
+ if(spe > 2 && Luck < 0) spesgn = -1;
+ } else {
+ if (oclass == WAND_CLASS) {
+ if (spe > 1 && spesgn == -1) spe = 1;
+ } else {
+ if (spe > 0 && spesgn == -1) spe = 0;
+ }
+ if (spe > otmp->spe) spe = otmp->spe;
+ }
+
+ if (spesgn == -1) spe = -spe;
+
+ /* set otmp->spe. This may, or may not, use spe... */
+ switch (typ) {
+ case TIN: if (contents==EMPTY) {
+ otmp->corpsenm = NON_PM;
+ otmp->spe = 0;
+ } else if (contents==SPINACH) {
+ otmp->corpsenm = NON_PM;
+ otmp->spe = 1;
+ }
+ break;
+ case SLIME_MOLD: otmp->spe = ftype;
+ /* Fall through */
+ case SKELETON_KEY: case CHEST: case LARGE_BOX:
+ case HEAVY_IRON_BALL: case IRON_CHAIN: case STATUE:
+ /* otmp->cobj already done in mksobj() */
+ break;
#ifdef MAIL
- case SCR_MAIL: otmp->spe = 1; break;
+ case SCR_MAIL: otmp->spe = 1; break;
#endif
- case WAN_WISHING:
- if (!wizard) {
- otmp->spe = (rn2(10) ? -1 : 0);
- break;
- }
- /* fall through, if wizard */
- default: otmp->spe = spe;
- }
-
- /* set otmp->corpsenm or dragon scale [mail] */
- if (mntmp >= LOW_PM) {
- if (mntmp == PM_LONG_WORM_TAIL) mntmp = PM_LONG_WORM;
-
- switch (typ) {
- case TIN:
- otmp->spe = 0; /* No spinach */
- if (dead_species(mntmp, FALSE)) {
- otmp->corpsenm = NON_PM; /* it's empty */
- } else if (!(mons[mntmp].geno & G_UNIQ) &&
- !(mvitals[mntmp].mvflags & G_NOCORPSE) &&
- mons[mntmp].cnutrit != 0) {
- otmp->corpsenm = mntmp;
- }
- break;
- case CORPSE:
- if (!(mons[mntmp].geno & G_UNIQ) &&
- !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
- if (mons[mntmp].msound == MS_GUARDIAN)
- mntmp = genus(mntmp,1);
- set_corpsenm(otmp, mntmp);
- }
- break;
- case FIGURINE:
- if (!(mons[mntmp].geno & G_UNIQ)
- && !is_human(&mons[mntmp])
+ case WAN_WISHING:
+ if (!wizard) {
+ otmp->spe = (rn2(10) ? -1 : 0);
+ break;
+ }
+ /* fall through, if wizard */
+ default: otmp->spe = spe;
+ }
+
+ /* set otmp->corpsenm or dragon scale [mail] */
+ if (mntmp >= LOW_PM) {
+ if (mntmp == PM_LONG_WORM_TAIL) mntmp = PM_LONG_WORM;
+
+ switch (typ) {
+ case TIN:
+ otmp->spe = 0; /* No spinach */
+ if (dead_species(mntmp, FALSE)) {
+ otmp->corpsenm = NON_PM; /* it's empty */
+ } else if (!(mons[mntmp].geno & G_UNIQ) &&
+ !(mvitals[mntmp].mvflags & G_NOCORPSE) &&
+ mons[mntmp].cnutrit != 0) {
+ otmp->corpsenm = mntmp;
+ }
+ break;
+ case CORPSE:
+ if (!(mons[mntmp].geno & G_UNIQ) &&
+ !(mvitals[mntmp].mvflags & G_NOCORPSE)) {
+ if (mons[mntmp].msound == MS_GUARDIAN)
+ mntmp = genus(mntmp,1);
+ set_corpsenm(otmp, mntmp);
+ }
+ break;
+ case FIGURINE:
+ if (!(mons[mntmp].geno & G_UNIQ)
+ && !is_human(&mons[mntmp])
#ifdef MAIL
- && mntmp != PM_MAIL_DAEMON
+ && mntmp != PM_MAIL_DAEMON
#endif
- )
- otmp->corpsenm = mntmp;
- break;
- case EGG:
- mntmp = can_be_hatched(mntmp);
- /* this also sets hatch timer if appropriate */
- set_corpsenm(otmp, mntmp);
- break;
- case STATUE: otmp->corpsenm = mntmp;
- if (Has_contents(otmp) && verysmall(&mons[mntmp]))
- delete_contents(otmp); /* no spellbook */
- otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
- break;
- case SCALE_MAIL:
- /* Dragon mail - depends on the order of objects */
- /* & dragons. */
- if (mntmp >= PM_GRAY_DRAGON &&
- mntmp <= PM_YELLOW_DRAGON)
- otmp->otyp = GRAY_DRAGON_SCALE_MAIL +
- mntmp - PM_GRAY_DRAGON;
- break;
- }
- }
-
- /* set blessed/cursed -- setting the fields directly is safe
- * since weight() is called below and addinv() will take care
- * of luck */
- if (iscursed) {
- curse(otmp);
- } else if (uncursed) {
- otmp->blessed = 0;
- otmp->cursed = (Luck < 0 && !wizard);
- } else if (blessed) {
- otmp->blessed = (Luck >= 0 || wizard);
- otmp->cursed = (Luck < 0 && !wizard);
- } else if (spesgn < 0) {
- curse(otmp);
- }
-
- /* set eroded */
- if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) {
- if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
- otmp->oeroded = eroded;
- if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
- otmp->oeroded2 = eroded2;
-
- /* set erodeproof */
- if (erodeproof && !eroded && !eroded2)
- otmp->oerodeproof = (Luck >= 0 || wizard);
- }
-
- /* set otmp->recharged */
- if (oclass == WAND_CLASS) {
- /* prevent wishing abuse */
- if (otmp->otyp == WAN_WISHING && !wizard) rechrg = 1;
- otmp->recharged = (unsigned)rechrg;
- }
-
- /* set poisoned */
- if (ispoisoned) {
- if (is_poisonable(otmp))
- otmp->opoisoned = (Luck >= 0);
- else if (oclass == FOOD_CLASS)
- /* try to taint by making it as old as possible */
- otmp->age = 1L;
- }
- /* and [un]trapped */
- if (trapped) {
- if (Is_box(otmp) || typ == TIN)
- otmp->otrapped = (trapped == 1);
- }
-
- if (isgreased) otmp->greased = 1;
-
- if (isdiluted && otmp->oclass == POTION_CLASS &&
- otmp->otyp != POT_WATER)
- otmp->odiluted = 1;
-
- /* set tin variety */
- if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard))
- set_tin_variety(otmp, tvariety);
-
- if (name) {
- const char *aname;
- short objtyp;
-
- /* an artifact name might need capitalization fixing */
- aname = artifact_name(name, &objtyp);
- if (aname && objtyp == otmp->otyp) name = aname;
-
- otmp = oname(otmp, name);
- if (otmp->oartifact) {
- otmp->quan = 1L;
- u.uconduct.wisharti++; /* KMH, conduct */
- }
- }
-
- /* more wishing abuse: don't allow wishing for certain artifacts */
- /* and make them pay; charge them for the wish anyway! */
- if ((is_quest_artifact(otmp) ||
- (otmp->oartifact && rn2(nartifact_exist()) > 1)) &&
- !wizard) {
- artifact_exists(otmp, safe_oname(otmp), FALSE);
- obfree(otmp, (struct obj *) 0);
- otmp = &zeroobj;
- pline("For a moment, you feel %s in your %s, but it disappears!",
- something,
- makeplural(body_part(HAND)));
- }
-
- if (halfeaten && otmp->oclass == FOOD_CLASS) {
- if (otmp->otyp == CORPSE)
- otmp->oeaten = mons[otmp->corpsenm].cnutrit;
- else otmp->oeaten = objects[otmp->otyp].oc_nutrition;
- /* (do this adjustment before setting up object's weight) */
- consume_oeaten(otmp, 1);
- }
- otmp->owt = weight(otmp);
- if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160;
-
- return(otmp);
+ )
+ otmp->corpsenm = mntmp;
+ break;
+ case EGG:
+ mntmp = can_be_hatched(mntmp);
+ /* this also sets hatch timer if appropriate */
+ set_corpsenm(otmp, mntmp);
+ break;
+ case STATUE: otmp->corpsenm = mntmp;
+ if (Has_contents(otmp) && verysmall(&mons[mntmp]))
+ delete_contents(otmp); /* no spellbook */
+ otmp->spe = ishistoric ? STATUE_HISTORIC : 0;
+ break;
+ case SCALE_MAIL:
+ /* Dragon mail - depends on the order of objects */
+ /* & dragons. */
+ if (mntmp >= PM_GRAY_DRAGON &&
+ mntmp <= PM_YELLOW_DRAGON)
+ otmp->otyp = GRAY_DRAGON_SCALE_MAIL +
+ mntmp - PM_GRAY_DRAGON;
+ break;
+ }
+ }
+
+ /* set blessed/cursed -- setting the fields directly is safe
+ * since weight() is called below and addinv() will take care
+ * of luck */
+ if (iscursed) {
+ curse(otmp);
+ } else if (uncursed) {
+ otmp->blessed = 0;
+ otmp->cursed = (Luck < 0 && !wizard);
+ } else if (blessed) {
+ otmp->blessed = (Luck >= 0 || wizard);
+ otmp->cursed = (Luck < 0 && !wizard);
+ } else if (spesgn < 0) {
+ curse(otmp);
+ }
+
+ /* set eroded */
+ if (is_damageable(otmp) || otmp->otyp == CRYSKNIFE) {
+ if (eroded && (is_flammable(otmp) || is_rustprone(otmp)))
+ otmp->oeroded = eroded;
+ if (eroded2 && (is_corrodeable(otmp) || is_rottable(otmp)))
+ otmp->oeroded2 = eroded2;
+
+ /* set erodeproof */
+ if (erodeproof && !eroded && !eroded2)
+ otmp->oerodeproof = (Luck >= 0 || wizard);
+ }
+
+ /* set otmp->recharged */
+ if (oclass == WAND_CLASS) {
+ /* prevent wishing abuse */
+ if (otmp->otyp == WAN_WISHING && !wizard) rechrg = 1;
+ otmp->recharged = (unsigned)rechrg;
+ }
+
+ /* set poisoned */
+ if (ispoisoned) {
+ if (is_poisonable(otmp))
+ otmp->opoisoned = (Luck >= 0);
+ else if (oclass == FOOD_CLASS)
+ /* try to taint by making it as old as possible */
+ otmp->age = 1L;
+ }
+ /* and [un]trapped */
+ if (trapped) {
+ if (Is_box(otmp) || typ == TIN)
+ otmp->otrapped = (trapped == 1);
+ }
+
+ if (isgreased) otmp->greased = 1;
+
+ if (isdiluted && otmp->oclass == POTION_CLASS &&
+ otmp->otyp != POT_WATER)
+ otmp->odiluted = 1;
+
+ /* set tin variety */
+ if (otmp->otyp == TIN && tvariety >= 0 && (rn2(4) || wizard))
+ set_tin_variety(otmp, tvariety);
+
+ if (name) {
+ const char *aname;
+ short objtyp;
+
+ /* an artifact name might need capitalization fixing */
+ aname = artifact_name(name, &objtyp);
+ if (aname && objtyp == otmp->otyp) name = aname;
+
+ otmp = oname(otmp, name);
+ if (otmp->oartifact) {
+ otmp->quan = 1L;
+ u.uconduct.wisharti++; /* KMH, conduct */
+ }
+ }
+
+ /* more wishing abuse: don't allow wishing for certain artifacts */
+ /* and make them pay; charge them for the wish anyway! */
+ if ((is_quest_artifact(otmp) ||
+ (otmp->oartifact && rn2(nartifact_exist()) > 1)) &&
+ !wizard) {
+ artifact_exists(otmp, safe_oname(otmp), FALSE);
+ obfree(otmp, (struct obj *) 0);
+ otmp = &zeroobj;
+ pline("For a moment, you feel %s in your %s, but it disappears!",
+ something,
+ makeplural(body_part(HAND)));
+ }
+
+ if (halfeaten && otmp->oclass == FOOD_CLASS) {
+ if (otmp->otyp == CORPSE)
+ otmp->oeaten = mons[otmp->corpsenm].cnutrit;
+ else otmp->oeaten = objects[otmp->otyp].oc_nutrition;
+ /* (do this adjustment before setting up object's weight) */
+ consume_oeaten(otmp, 1);
+ }
+ otmp->owt = weight(otmp);
+ if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160;
+
+ return(otmp);
}
int
rnd_class(first,last)
int first,last;
{
- int i, x, sum=0;
-
- if (first == last)
- return (first);
- for(i=first; i<=last; i++)
- sum += objects[i].oc_prob;
- if (!sum) /* all zero */
- return first + rn2(last-first+1);
- x = rnd(sum);
- for(i=first; i<=last; i++)
- if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
- return i;
- return 0;
+ int i, x, sum=0;
+
+ if (first == last)
+ return (first);
+ for(i=first; i<=last; i++)
+ sum += objects[i].oc_prob;
+ if (!sum) /* all zero */
+ return first + rn2(last-first+1);
+ x = rnd(sum);
+ for(i=first; i<=last; i++)
+ if (objects[i].oc_prob && (x -= objects[i].oc_prob) <= 0)
+ return i;
+ return 0;
}
STATIC_OVL const char *
Japanese_item_name(i)
int i;
{
- struct Jitem *j = Japanese_items;
-
- while(j->item) {
- if (i == j->item)
- return j->name;
- j++;
- }
- return (const char *)0;
+ struct Jitem *j = Japanese_items;
+
+ while(j->item) {
+ if (i == j->item)
+ return j->name;
+ j++;
+ }
+ return (const char *)0;
}
const char *
suit_simple_name(suit)
struct obj *suit;
{
- const char *suitnm, *esuitp;
-
- if (Is_dragon_mail(suit))
- return "dragon mail"; /* <color> dragon scale mail */
- else if (Is_dragon_scales(suit))
- return "dragon scales";
- suitnm = OBJ_NAME(objects[suit->otyp]);
- esuitp = eos((char *)suitnm);
- if (strlen(suitnm) > 5 && !strcmp(esuitp - 5, " mail"))
- return "mail"; /* most suits fall into this category */
- else if (strlen(suitnm) > 7 && !strcmp(esuitp - 7, " jacket"))
- return "jacket"; /* leather jacket */
- /* suit is lame but armor is ambiguous and body armor is absurd */
- return "suit";
+ const char *suitnm, *esuitp;
+
+ if (Is_dragon_mail(suit))
+ return "dragon mail"; /* <color> dragon scale mail */
+ else if (Is_dragon_scales(suit))
+ return "dragon scales";
+ suitnm = OBJ_NAME(objects[suit->otyp]);
+ esuitp = eos((char *)suitnm);
+ if (strlen(suitnm) > 5 && !strcmp(esuitp - 5, " mail"))
+ return "mail"; /* most suits fall into this category */
+ else if (strlen(suitnm) > 7 && !strcmp(esuitp - 7, " jacket"))
+ return "jacket"; /* leather jacket */
+ /* suit is lame but armor is ambiguous and body armor is absurd */
+ return "suit";
}
const char *
struct obj *cloak;
{
if (cloak) {
- switch (cloak->otyp) {
- case ROBE:
- return "robe";
- case MUMMY_WRAPPING:
- return "wrapping";
- case ALCHEMY_SMOCK:
- return (objects[cloak->otyp].oc_name_known &&
- cloak->dknown) ? "smock" : "apron";
- default:
- break;
- }
+ switch (cloak->otyp) {
+ case ROBE:
+ return "robe";
+ case MUMMY_WRAPPING:
+ return "wrapping";
+ case ALCHEMY_SMOCK:
+ return (objects[cloak->otyp].oc_name_known &&
+ cloak->dknown) ? "smock" : "apron";
+ default:
+ break;
+ }
}
return "cloak";
}
mimic_obj_name(mtmp)
struct monst *mtmp;
{
- if (mtmp->m_ap_type == M_AP_OBJECT && mtmp->mappearance != STRANGE_OBJECT) {
- int idx = objects[mtmp->mappearance].oc_descr_idx;
- if (mtmp->mappearance == GOLD_PIECE) return "gold";
- return obj_descr[idx].oc_name;
- }
- return "whatcha-may-callit";
+ if (mtmp->m_ap_type == M_AP_OBJECT && mtmp->mappearance != STRANGE_OBJECT) {
+ int idx = objects[mtmp->mappearance].oc_descr_idx;
+ if (mtmp->mappearance == GOLD_PIECE) return "gold";
+ return obj_descr[idx].oc_name;
+ }
+ return "whatcha-may-callit";
}
/*
char *bufp, *endp;
/* convert size_t (or int for ancient systems) to ordinary unsigned */
unsigned len, lenlimit,
- len_qpfx = (unsigned)(qprefix ? strlen(qprefix) : 0),
- len_qsfx = (unsigned)(qsuffix ? strlen(qsuffix) : 0),
- len_lastR = (unsigned)strlen(lastR);
+ len_qpfx = (unsigned)(qprefix ? strlen(qprefix) : 0),
+ len_qsfx = (unsigned)(qsuffix ? strlen(qsuffix) : 0),
+ len_lastR = (unsigned)strlen(lastR);
lenlimit = QBUFSZ - 1;
endp = qbuf + lenlimit;
the result of short_oname() to be shorter than the length of
the last resort string, but we ignore that possibility here) */
if (len_qpfx > lenlimit)
- impossible("safe_qbuf: prefix too long (%u characters).",
- len_qpfx);
+ impossible("safe_qbuf: prefix too long (%u characters).",
+ len_qpfx);
else if (len_qpfx + len_qsfx > lenlimit)
- impossible("safe_qbuf: suffix too long (%u + %u characters).",
- len_qpfx, len_qsfx);
+ impossible("safe_qbuf: suffix too long (%u + %u characters).",
+ len_qpfx, len_qsfx);
else if (len_qpfx + len_lastR + len_qsfx > lenlimit)
- impossible("safe_qbuf: filler too long (%u + %u + %u characters).",
- len_qpfx, len_lastR, len_qsfx);
+ impossible("safe_qbuf: filler too long (%u + %u + %u characters).",
+ len_qpfx, len_lastR, len_qsfx);
/* the output buffer might be the same as the prefix if caller
has already partially filled it */
if (qbuf == qprefix) {
- /* prefix is already in the buffer */
- *endp = '\0';
+ /* prefix is already in the buffer */
+ *endp = '\0';
} else if (qprefix) {
- /* put prefix into the buffer */
- (void)strncpy(qbuf, qprefix, lenlimit);
- *endp = '\0';
+ /* put prefix into the buffer */
+ (void)strncpy(qbuf, qprefix, lenlimit);
+ *endp = '\0';
} else {
- /* no prefix; output buffer starts out empty */
- qbuf[0] = '\0';
+ /* no prefix; output buffer starts out empty */
+ qbuf[0] = '\0';
}
len = (unsigned)strlen(qbuf);
if (len + len_lastR + len_qsfx > lenlimit) {
- /* too long; skip formatting, last resort output is truncated */
- if (len < lenlimit) {
- (void)strncpy(&qbuf[len], lastR, lenlimit - len);
- *endp = '\0';
- len = (unsigned)strlen(qbuf);
- if (qsuffix && len < lenlimit) {
- (void)strncpy(&qbuf[len], qsuffix, lenlimit - len);
- *endp = '\0';
- /* len = (unsigned)strlen(qbuf); */
- }
- }
+ /* too long; skip formatting, last resort output is truncated */
+ if (len < lenlimit) {
+ (void)strncpy(&qbuf[len], lastR, lenlimit - len);
+ *endp = '\0';
+ len = (unsigned)strlen(qbuf);
+ if (qsuffix && len < lenlimit) {
+ (void)strncpy(&qbuf[len], qsuffix, lenlimit - len);
+ *endp = '\0';
+ /* len = (unsigned)strlen(qbuf); */
+ }
+ }
} else {
- /* suffix and last resort are guaranteed to fit */
- len += len_qsfx; /* include the pending suffix */
- /* format the object */
- bufp = short_oname(obj, func, altfunc, lenlimit - len);
- if (len + strlen(bufp) <= lenlimit)
- Strcat(qbuf, bufp); /* formatted name fits */
- else
- Strcat(qbuf, lastR); /* use last resort */
- releaseobuf(bufp);
-
- if (qsuffix) Strcat(qbuf, qsuffix);
+ /* suffix and last resort are guaranteed to fit */
+ len += len_qsfx; /* include the pending suffix */
+ /* format the object */
+ bufp = short_oname(obj, func, altfunc, lenlimit - len);
+ if (len + strlen(bufp) <= lenlimit)
+ Strcat(qbuf, bufp); /* formatted name fits */
+ else
+ Strcat(qbuf, lastR); /* use last resort */
+ releaseobuf(bufp);
+
+ if (qsuffix) Strcat(qbuf, qsuffix);
}
/* assert( strlen(qbuf) < QBUFSZ ); */
return qbuf;
{
char buf[BUFSZ], *bufp, monclass;
int which, tryct, i, firstchoice = NON_PM;
- struct permonst *whichpm;
+ struct permonst *whichpm = NULL;
struct monst *mtmp;
boolean madeany = FALSE;
boolean maketame, makepeaceful, makehostile;