sync changes since last snapshot

This commit is contained in:
cohrs
2002-01-07 02:12:04 +00:00
parent 7218689e70
commit c77073be31
51 changed files with 581 additions and 286 deletions
+3 -2
View File
@@ -1,4 +1,4 @@
/* SCCS Id: @(#)allmain.c 3.3 2000/05/05 */
/* SCCS Id: @(#)allmain.c 3.3 2002/01/04 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -415,7 +415,8 @@ void
stop_occupation()
{
if(occupation) {
You("stop %s.", occtxt);
if (!maybe_finished_meal(TRUE))
You("stop %s.", occtxt);
occupation = 0;
flags.botl = 1; /* in case u.uhs changed */
/* fainting stops your occupation, there's no reason to sync.
+2 -2
View File
@@ -936,7 +936,7 @@ register struct obj *obj;
return;
} else {
if ((long)otmp->spe + obj->quan > 7L)
(void)splitobj(obj, 7L - (long)otmp->spe);
obj = splitobj(obj, 7L - (long)otmp->spe);
You("attach %ld%s candle%s to %s.",
obj->quan, !otmp->spe ? "" : " more",
plur(obj->quan), the(xname(otmp)));
@@ -1107,7 +1107,7 @@ light_cocktail(obj)
makeknown(obj->otyp);
if (obj->quan > 1L) {
(void) splitobj(obj, 1L);
obj = splitobj(obj, 1L);
begin_burn(obj, FALSE); /* burn before free to get position */
obj_extract_self(obj); /* free from inv */
+101 -19
View File
@@ -345,7 +345,8 @@ xchar ballx, bally, chainx, chainy; /* only matter !before */
/* return TRUE if ball could be dragged
*
* Should not be called while swallowed.
* Should not be called while swallowed. Should be called before movement,
* because we might want to move the ball or chain to the hero's old position.
*/
boolean
drag_ball(x, y, bc_control, ballx, bally, chainx, chainy, cause_delay)
@@ -368,27 +369,108 @@ boolean *cause_delay;
return TRUE;
}
if (carried(uball) || dist2(x, y, uball->ox, uball->oy) < 3 ||
(uball->ox == uchain->ox && uball->oy == uchain->oy)) {
/*
* Case where the ball doesn't move but the chain can't just move
* to the player's position:
* @ _
* _ moving southwest becomes @_ and not @
* 0 0 0
*/
/* only need to move the chain? */
if (carried(uball) || distmin(x, y, uball->ox, uball->oy) <= 2) {
*bc_control = BC_CHAIN;
move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
if (dist2(x, y, uball->ox, uball->oy) == 2 &&
dist2(x, y, uchain->ox, uchain->oy) == 4) {
if (uchain->oy == y)
*chainx = uball->ox;
else
*chainy = uball->oy;
} else {
*chainx = u.ux;
*chainy = u.uy;
if (carried(uball)) {
/* move chain only if necessary; assume they didn't teleport */
if (distmin(x, y, uchain->ox, uchain->oy) > 1) {
*chainx = u.ux;
*chainy = u.uy;
}
return TRUE;
}
#define CHAIN_IN_MIDDLE(chx, chy) \
(distmin(x, y, chx, chy) <= 1 && distmin(chx, chy, uball->ox, uball->oy) <= 1)
switch(dist2(x, y, uball->ox, uball->oy)) {
/* two spaces diagonal from ball, move chain inbetween */
case 8:
*chainx = (uball->ox + x)/2;
*chainy = (uball->oy + y)/2;
break;
/* player is distance 2/1 from ball; move chain to one of the
* two spaces between
* @
* __
* 0
*/
case 5: {
xchar tempx, tempy, tempx2, tempy2;
/* find position closest to current position of chain */
/* no effect if current position is already OK */
if (abs(x - uball->ox) == 1) {
tempx = x;
tempx2 = uball->ox;
tempy = tempy2 = (uball->oy + y)/2;
} else {
tempx = tempx2 = (uball->ox + x)/2;
tempy = y;
tempy2 = uball->oy;
}
if (dist2(tempx, tempy, uchain->ox, uchain->oy) <
dist2(tempx2, tempy2, uchain->ox, uchain->oy) ||
((dist2(tempx, tempy, uchain->ox, uchain->oy) ==
dist2(tempx2, tempy2, uchain->ox, uchain->oy)) && rn2(2))) {
*chainx = tempx;
*chainy = tempy;
} else {
*chainx = tempx2;
*chainy = tempy2;
}
break;
}
/* ball is two spaces horizontal or vertical from player; move*/
/* chain inbetween *unless* current chain position is OK */
case 4:
if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy))
break;
*chainx = (x + uchain->ox)/2;
*chainy = (y + uchain->oy)/2;
break;
/* ball is one space diagonal from player. Check for the
* following special case:
* @
* _ moving southwest becomes @_
* 0 0
* (This will also catch teleporting that happens to resemble
* this case, but oh well.) Otherwise fall through.
*/
case 2:
if (dist2(x, y, uball->ox, uball->oy) == 2 &&
dist2(x, y, uchain->ox, uchain->oy) == 4) {
if (uchain->oy == y)
*chainx = uball->ox;
else
*chainy = uball->oy;
break;
}
/* fall through */
case 1:
case 0:
/* do nothing if possible */
if (CHAIN_IN_MIDDLE(uchain->ox, uchain->oy))
break;
/* otherwise try to drag chain to player's old position */
if (CHAIN_IN_MIDDLE(u.ux, u.uy)) {
*chainx = u.ux;
*chainy = u.uy;
break;
}
/* otherwise use player's new position (they must have
teleported, for this to happen) */
*chainx = x;
*chainy = y;
break;
default: impossible("bad chain movement");
break;
}
#undef CHAIN_IN_MIDDLE
return TRUE;
}
+3
View File
@@ -48,6 +48,9 @@ NEARDATA char *save_cm = 0;
NEARDATA int killer_format = 0;
const char *killer = 0;
const char *delayed_killer = 0;
#ifdef GOLDOBJ
NEARDATA long done_money = 0;
#endif
char killer_buf[BUFSZ] = DUMMY;
const char *nomovemsg = 0;
const char nul[40] = DUMMY; /* contains zeros */
+31 -27
View File
@@ -171,9 +171,10 @@ const char *verb;
if (mtmp) {
if (!passes_walls(mtmp->data) &&
!throws_rocks(mtmp->data)) {
if (hmon(mtmp, obj, TRUE))
if (hmon(mtmp, obj, TRUE) && !is_whirly(mtmp->data))
return FALSE; /* still alive */
} else mtmp->mtrapped = 0;
}
mtmp->mtrapped = 0;
} else {
if (!Passes_walls && !throws_rocks(youmonst.data)) {
losehp(rnd(15), "squished under a boulder",
@@ -523,31 +524,35 @@ void
dropy(obj)
register struct obj *obj;
{
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 */
obj_no_longer_held(obj);
if(u.uswallow) {
boolean could_petrify;
if (obj != uball) { /* mon doesn't pick up ball */
could_petrify = obj->otyp == CORPSE &&
touch_petrifies(&mons[obj->corpsenm]);
(void) mpickobj(u.ustuck,obj);
if (could_petrify && is_animal(u.ustuck->data)) {
minstapetrify(u.ustuck, TRUE);
/* Don't leave a cockatrice corpse available in a statue */
if (!u.uswallow) delobj(obj);
}
boolean could_petrify;
if (obj != uball) { /* mon doesn't pick up ball */
could_petrify = obj->otyp == CORPSE &&
touch_petrifies(&mons[obj->corpsenm]);
(void) mpickobj(u.ustuck,obj);
if (could_petrify && is_animal(u.ustuck->data)) {
minstapetrify(u.ustuck, TRUE);
/* Don't leave a cockatrice corpse available in a statue */
if (!u.uswallow) delobj(obj);
}
}
} else {
place_object(obj, u.ux, u.uy);
if (obj == uball)
drop_ball(u.ux,u.uy);
else
sellobj(obj, u.ux, u.uy);
stackobj(obj);
if(Blind && Levitation)
map_object(obj, 0);
newsym(u.ux,u.uy); /* remap location under self */
place_object(obj, u.ux, u.uy);
if (obj == uball)
drop_ball(u.ux,u.uy);
else
sellobj(obj, u.ux, u.uy);
stackobj(obj);
if(Blind && Levitation)
map_object(obj, 0);
newsym(u.ux,u.uy); /* remap location under self */
}
}
@@ -597,7 +602,10 @@ int retry;
{
int n, i, n_dropped = 0;
long cnt;
struct obj *otmp, *otmp2, *u_gold = 0;
struct obj *otmp, *otmp2;
#ifndef GOLDOBJ
struct obj *u_gold = 0;
#endif
menu_item *pick_list;
boolean all_categories = TRUE;
boolean drop_everything = FALSE;
@@ -657,11 +665,7 @@ int retry;
cnt = pick_list[i].count;
if (cnt < otmp->quan && !welded(otmp) &&
(!otmp->cursed || otmp->otyp != LOADSTONE)) {
otmp2 = splitobj(otmp, cnt);
/* assume other worn items aren't mergable */
if (otmp == uwep) setuwep(otmp2);
if (otmp == uquiver) setuqwep(otmp2);
if (otmp == uswapwep) setuswapwep(otmp2);
otmp = splitobj(otmp, cnt);
}
n_dropped += drop(otmp);
}
+10 -1
View File
@@ -431,6 +431,11 @@ xchar x, y;
result = "cracking";
}
if (result) {
if (otmp->otyp == MIRROR)
change_luck(-2);
/* eggs laid by you */
if (otmp->otyp == EGG && otmp->spe && otmp->corpsenm >= LOW_PM)
change_luck(-5);
You_hear("a muffled %s.",result);
if(costly) loss += stolen_value(otmp, x, y,
(boolean)shkp->mpeaceful, TRUE);
@@ -512,7 +517,7 @@ xchar x, y;
return(!rn2(3) || martial());
}
if (kickobj->quan > 1L && !isgold) (void) splitobj(kickobj, 1L);
if (kickobj->quan > 1L && !isgold) kickobj = splitobj(kickobj, 1L);
if (slide && !Blind)
pline("Whee! %s slide%s across the %s.", Doname2(kickobj),
@@ -1267,6 +1272,10 @@ boolean shop_floor_obj;
otmp->no_charge = 0;
}
if (otmp == uwep) setuwep((struct obj *)0);
if (otmp == uquiver) setuqwep((struct obj *)0);
if (otmp == uswapwep) setuswapwep((struct obj *)0);
add_to_migration(otmp);
otmp->ox = cc.x;
otmp->oy = cc.y;
+16 -6
View File
@@ -52,7 +52,12 @@ int shotlimit;
if(obj->oclass == GOLD_CLASS) return(throw_gold(obj));
#else
if (!getdir((char *)0)) return(0);
if (!getdir((char *)0)) {
/* obj might need to be merged back into the singular gold object */
freeinv(obj);
addinv(obj);
return(0);
}
/*
Throwing money is usually for getting rid of it when
@@ -157,8 +162,7 @@ int shotlimit;
twoweap = u.twoweap;
/* split this object off from its slot if necessary */
if (obj->quan > 1L) {
otmp = splitobj(obj, obj->quan - 1L);
otmp->owornmask = 0L;
otmp = splitobj(obj, 1L);
} else {
otmp = obj;
if (otmp->owornmask && otmp != uball)
@@ -846,7 +850,7 @@ boolean twoweap; /* used to restore twoweapon mode if wielded weapon returns */
if (is_ammo(obj)) {
if (ammo_and_launcher(obj, uwep))
range++;
else
else if (obj->oclass != GEM_CLASS)
range /= 2;
}
@@ -1482,9 +1486,10 @@ breaktest(obj)
struct obj *obj;
{
if (obj_resists(obj, 1, 99)) return 0;
if (objects[obj->otyp].oc_material == GLASS && !obj->oartifact &&
obj->oclass != GEM_CLASS)
return 1;
switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
case MIRROR:
case CRYSTAL_BALL:
#ifdef TOURIST
case EXPENSIVE_CAMERA:
#endif
@@ -1508,6 +1513,11 @@ boolean in_view;
to_pieces = "";
switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
default: /* glass or crystal wand */
if (obj->oclass != WAND_CLASS)
impossible("breaking odd object?");
case CRYSTAL_PLATE_MAIL:
case LENSES:
case MIRROR:
case CRYSTAL_BALL:
#ifdef TOURIST
+82 -18
View File
@@ -1,4 +1,4 @@
/* SCCS Id: @(#)eat.c 3.3 2001/11/28 */
/* SCCS Id: @(#)eat.c 3.3 2002/01/02 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -40,7 +40,7 @@ STATIC_DCL int FDECL(edibility_prompts, (struct obj *));
STATIC_DCL int FDECL(rottenfood, (struct obj *));
STATIC_DCL void NDECL(eatspecial);
STATIC_DCL void FDECL(eataccessory, (struct obj *));
STATIC_DCL const char * FDECL(foodword, (struct obj *));
STATIC_DCL const char *FDECL(foodword, (struct obj *));
char msgbuf[BUFSZ];
@@ -303,9 +303,9 @@ register struct obj *otmp;
{
if (otmp->quan > 1L) {
if(!carried(otmp))
(void) splitobj(otmp, 1L);
(void) splitobj(otmp, otmp->quan - 1L);
else
otmp = splitobj(otmp, otmp->quan - 1L);
otmp = splitobj(otmp, 1L);
#ifdef DEBUG
debugpline("split object,");
#endif
@@ -1097,11 +1097,7 @@ no_opener:
pline_The("tin slips from your %s.",
makeplural(body_part(FINGER)));
if(otmp->quan > 1L) {
register struct obj *obj;
obj = splitobj(otmp, 1L);
if (otmp == uwep) setuwep(obj);
if (otmp == uswapwep) setuswapwep(obj);
if (otmp == uquiver) setuqwep(obj);
otmp = splitobj(otmp, 1L);
}
if (carried(otmp)) dropx(otmp);
else stackobj(otmp);
@@ -1233,7 +1229,7 @@ eatcorpse(otmp) /* called when a corpse is selected as food */
(void)touchfood(otmp);
retcode = 1;
} else
otmp->oeaten >>= 2;
consume_oeaten(otmp, 2); /* oeaten >>= 2 */
} else {
pline("%s%s %s!",
!uniq ? "This " : !type_is_pname(&mons[mnum]) ? "The " : "",
@@ -1800,10 +1796,10 @@ doeat() /* generic "eat" command funtion (see cmd.c) */
u.umonnum == PM_RUST_MONSTER && otmp->oerodeproof) {
otmp->rknown = TRUE;
if (otmp->quan > 1L) {
if(!carried(otmp))
(void) splitobj(otmp, 1L);
else
otmp = splitobj(otmp, otmp->quan - 1L);
if(!carried(otmp))
(void) splitobj(otmp, otmp->quan - 1L);
else
otmp = splitobj(otmp, 1L);
}
pline("Ulch - That %s was rustproofed!", xname(otmp));
/* The regurgitated object's rustproofing is gone now */
@@ -1926,7 +1922,7 @@ doeat() /* generic "eat" command funtion (see cmd.c) */
otmp->orotten = TRUE;
dont_start = TRUE;
}
otmp->oeaten >>= 1;
consume_oeaten(otmp, 1); /* oeaten >>= 1 */
} else fprefx(otmp);
}
@@ -1979,10 +1975,10 @@ bite()
force_save_hs = TRUE;
if(victual.nmod < 0) {
lesshungry(-victual.nmod);
victual.piece->oeaten -= -victual.nmod;
consume_oeaten(victual.piece, victual.nmod); /* -= -nmod */
} else if(victual.nmod > 0 && (victual.usedtime % victual.nmod)) {
lesshungry(1);
victual.piece->oeaten--;
consume_oeaten(victual.piece, -1); /* -= 1 */
}
force_save_hs = FALSE;
recalc_wt();
@@ -2279,7 +2275,7 @@ floorfood(verb,corpsecheck) /* get food from floor or pack */
/* if we can't touch floor objects then use invent food only */
if (!can_reach_floor() ||
#ifdef STEED
u.usteed || /* can't eat off floor while riding */
(feeding && u.usteed) || /* can't eat off floor while riding */
#endif
((is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) &&
(Wwalking || is_clinger(youmonst.data) ||
@@ -2382,6 +2378,74 @@ register struct obj *obj;
return (base < 1) ? 1 : base;
}
/* reduce obj's oeaten field, making sure it never hits or passes 0 */
void
consume_oeaten(obj, amt)
struct obj *obj;
int amt;
{
/*
* This is a hack to try to squelch several long standing mystery
* food bugs. A better solution would be to rewrite the entire
* victual handling mechanism from scratch using a less complex
* model. Alternatively, this routine could call done_eating()
* or food_disappears() but its callers would need revisions to
* cope with victual.piece unexpectedly going away.
*
* Multi-turn eating operates by setting the food's oeaten field
* to its full nutritional value and then running a counter which
* independently keeps track of whether there is any food left.
* The oeaten field can reach exactly zero on the last turn, and
* the object isn't removed from inventory until the next turn
* when the "you finish eating" message gets delivered, so the
* food would be restored to the status of untouched during that
* interval. This resulted in unexpected encumbrance messages
* at the end of a meal (if near enough to a threshold) and would
* yield full food if there was an interruption on the critical
* turn. Also, there have been reports over the years of food
* becoming massively heavy or producing unlimited satiation;
* this would occur if reducing oeaten via subtraction attempted
* to drop it below 0 since its unsigned type would produce a
* huge positive value instead. So far, no one has figured out
* _why_ that inappropriate subtraction might sometimes happen.
*/
if (amt > 0) {
/* bit shift to divide the remaining amount of food */
obj->oeaten >>= amt;
} else {
/* simple decrement; value is negative so we actually add it */
if ((int) obj->oeaten > -amt)
obj->oeaten += amt;
else
obj->oeaten = 0;
}
if (obj->oeaten == 0) {
if (obj == victual.piece) /* always true unless wishing... */
victual.reqtime = victual.usedtime; /* no bites left */
obj->oeaten = 1; /* smallest possible positive value */
}
}
#endif /* OVLB */
#ifdef OVL1
/* called when eatfood occupation has been interrupted,
or in the case of theft, is about to be interrupted */
boolean
maybe_finished_meal(stopping)
boolean stopping;
{
/* in case consume_oeaten() has decided that the food is all gone */
if (occupation == eatfood && victual.usedtime >= victual.reqtime) {
if (stopping) occupation = 0; /* for do_reset_eat */
(void) eatfood(); /* calls done_eating() to use up victual.piece */
return TRUE;
}
return FALSE;
}
#endif /* OVL1 */
/*eat.c*/
+1 -1
View File
@@ -662,7 +662,7 @@ die:
#ifndef GOLDOBJ
u.ugold = umoney;
#else
/* FIXME */
done_money = umoney;
#endif
/* clean up unneeded windows */
+9 -11
View File
@@ -416,20 +416,18 @@ struct obj *obj; /* only scatter this obj */
qtmp = otmp->quan - 1;
if (qtmp > LARGEST_INT) qtmp = LARGEST_INT;
qtmp = (long)rnd((int)qtmp);
(void) splitobj(otmp, qtmp);
if (qtmp < otmp->quan)
split_up = TRUE;
otmp = splitobj(otmp, qtmp);
if (rn2(qtmp))
split_up = TRUE;
else
split_up = FALSE;
}
split_up = FALSE;
} else
split_up = FALSE;
if (individual_object) {
if (split_up) {
if (otmp->where == OBJ_FLOOR)
obj = otmp->nexthere;
else
obj = otmp->nobj;
if (split_up) {
obj = otmp;
} else
obj = (struct obj *)0;
obj = (struct obj *)0;
}
obj_extract_self(otmp);
used_up = FALSE;
+2 -2
View File
@@ -730,7 +730,7 @@ boolean uncomp;
* end up being displayed after the error message.
*/
if (istty)
fflush(stdout);
wait_synch();
# endif
if (f == 0) { /* child */
# ifdef TTY_GRAPHICS
@@ -740,7 +740,7 @@ boolean uncomp;
* invisible if there are no error messages.
*/
if (istty)
raw_printf("");
raw_print("");
# endif
/* run compressor without privileges, in case other programs
* have surprises along the line of gzip once taking filenames
+5 -1
View File
@@ -160,7 +160,11 @@ moverock()
continue;
case HOLE:
case TRAPDOOR:
pline("%s %s and plugs a %s in the %s!",
if (Blind)
pline("Kerplunk! You no longer feel %s.",
the(xname(otmp)));
else
pline("%s %s and plugs a %s in the %s!",
The(xname(otmp)),
(ttmp->ttyp == TRAPDOOR) ? "triggers" : "falls into",
(ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",
+44 -48
View File
@@ -51,8 +51,10 @@ register struct obj *otmp;
#ifdef GOLDOBJ
/* There is only one of these in inventory... */
if (otmp->oclass == GOLD_CLASS) otmp->invlet = GOLD_SYM;
return;
if (otmp->oclass == GOLD_CLASS) {
otmp->invlet = GOLD_SYM;
return;
}
#endif
for(i = 0; i < 52; i++) inuse[i] = FALSE;
@@ -395,10 +397,7 @@ const char *drop_fmt, *drop_arg, *hold_msg;
if (drop_fmt) pline(drop_fmt, drop_arg);
/* undo any merge which took place */
if (obj->quan > oquan) {
struct obj *otmp = splitobj(obj, oquan);
/* might have merged with weapon */
if (obj->owornmask)
setworn(otmp, obj->owornmask);
obj = splitobj(obj, oquan);
}
dropx(obj);
} else {
@@ -914,23 +913,26 @@ register const char *let,*word;
pline_The("LRS would be very interested to know you have that much.");
return(struct obj *)0;
}
#ifndef GOLDOBJ
#ifndef GOLDOBJ
if(!(allowcnt == 2 && cnt < u.ugold))
cnt = u.ugold;
return(mkgoldobj(cnt));
#endif
}
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 */
/* permit counts for throwing gold, but don't accept
* counts for other things since the throw code will
* split off a single item anyway */
#ifdef GOLDOBJ
if (ilet != def_oc_syms[GOLD_CLASS])
#endif
allowcnt = 1;
if(cnt == 0 && prezero) return((struct obj *)0);
if(cnt > 1) {
You("can only throw one item at a time.");
continue;
}
if(cnt == 0 && prezero) return((struct obj *)0);
if(cnt > 1) {
You("can only throw one item at a time.");
continue;
}
}
#ifdef GOLDOBJ
flags.botl = 1; /* May have changed the amount of money */
@@ -975,20 +977,17 @@ register const char *let,*word;
return((struct obj *)0);
}
if(allowcnt == 2) { /* cnt given */
if(cnt == 0) return (struct obj *)0;
if(cnt != otmp->quan) {
register struct obj *obj = splitobj(otmp, cnt);
if(cnt == 0) return (struct obj *)0;
if(cnt != otmp->quan) {
otmp = splitobj(otmp, cnt);
/* Very ugly kludge necessary to prevent someone from trying
* to drop one of several loadstones and having the loadstone
* now be separate.
*/
if (!strcmp(word, "drop") &&
obj->otyp == LOADSTONE && obj->cursed)
otmp->corpsenm = obj->invlet;
if(otmp == uwep) setuwep(obj);
else if (otmp == uquiver) setuqwep(obj);
if (otmp == uswapwep) setuswapwep(obj);
}
if (!strcmp(word, "drop") &&
otmp->otyp == LOADSTONE && otmp->cursed)
otmp->corpsenm = otmp->invlet;
}
}
return(otmp);
}
@@ -1230,7 +1229,7 @@ nextclass:
if (ckfn && !(*ckfn)(otmp)) continue;
if (!allflag) {
Strcpy(qbuf, !ininv ? doname(otmp) :
xprname(otmp, (char *)0, ilet, !nodot, 0L));
xprname(otmp, (char *)0, ilet, !nodot, 0L, 0L));
Strcat(qbuf, "?");
sym = (takeoff || ident || otmp->quan < 2L) ?
nyaq(qbuf) : nyNaq(qbuf);
@@ -1250,13 +1249,7 @@ nextclass:
sym = 'y';
if (yn_number < otmp->quan && !welded(otmp) &&
(!otmp->cursed || otmp->otyp != LOADSTONE)) {
struct obj *otmpx = splitobj(otmp, yn_number);
if (!otmpx || otmpx->nobj != otmp2)
impossible("bad object split in askchain");
/* assume other worn items aren't mergable */
if (otmp == uwep) setuwep(otmpx);
if (otmp == uquiver) setuqwep(otmpx);
if (otmp == uswapwep) setuswapwep(otmpx);
otmp = splitobj(otmp, yn_number);
}
}
}
@@ -1411,32 +1404,33 @@ const char *prefix;
register struct obj *obj;
long quan;
{
long savequan = obj->quan;
if (quan) obj->quan = quan;
if (!prefix) prefix = "";
pline("%s%s%s",
prefix, *prefix ? " " : "",
xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L));
if (quan) obj->quan = savequan;
xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L, quan));
}
#endif /* OVL2 */
#ifdef OVL1
char *
xprname(obj, txt, let, dot, cost)
xprname(obj, txt, let, dot, cost, quan)
struct obj *obj;
const char *txt; /* text to print instead of obj */
char let; /* inventory letter */
boolean dot; /* append period; (dot && cost => Iu) */
long cost; /* cost (for inventory of unpaid or expended items) */
long quan; /* if non-0, print this quantity, not obj->quan */
{
#ifdef LINT /* handle static char li[BUFSZ]; */
char li[BUFSZ];
char li[BUFSZ];
#else
static char li[BUFSZ];
static char li[BUFSZ];
#endif
boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM;
boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM;
long savequan = obj->quan;
if (quan) obj->quan = quan;
/*
* If let is:
* * Then obj == null and we are printing a total amount.
@@ -1458,6 +1452,8 @@ long cost; /* cost (for inventory of unpaid or expended items) */
(use_invlet ? obj->invlet : let),
(txt ? txt : doname(obj)), (dot ? "." : ""));
}
if (quan) obj->quan = savequan;
return li;
}
@@ -1566,8 +1562,8 @@ boolean want_reply;
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));
want_reply ? PICK_ONE : PICK_NONE,
xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L));
break;
}
}
@@ -1658,7 +1654,7 @@ dounpaid()
pline("%s", xprname(otmp, distant_name(otmp, doname),
marker ? otmp->invlet : CONTAINED_SYM,
TRUE, unpaid_cost(otmp)));
TRUE, unpaid_cost(otmp), 0L));
return;
}
@@ -1683,7 +1679,7 @@ dounpaid()
save_unpaid = otmp->unpaid;
otmp->unpaid = 0;
putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
ilet, TRUE, cost));
ilet, TRUE, cost, 0L));
otmp->unpaid = save_unpaid;
num_so_far++;
}
@@ -1709,7 +1705,7 @@ dounpaid()
marker->unpaid = 0; /* suppress "(unpaid)" suffix */
putstr(win, 0,
xprname(marker, distant_name(marker, doname),
CONTAINED_SYM, TRUE, cost));
CONTAINED_SYM, TRUE, cost, 0L));
marker->unpaid = save_unpaid;
}
}
@@ -1717,7 +1713,7 @@ dounpaid()
}
putstr(win, 0, "");
putstr(win, 0, xprname((struct obj *)0, "Total:", '*', FALSE, totcost));
putstr(win, 0, xprname((struct obj *)0, "Total:", '*', FALSE, totcost, 0L));
display_nhwindow(win, FALSE);
destroy_nhwindow(win);
}
@@ -2291,7 +2287,7 @@ long numused;
/* 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, obj->quan - numused);
otmp = splitobj(obj, numused);
else
otmp = obj;
if(costly_spot(otmp->ox, otmp->oy)) {
+3 -2
View File
@@ -751,6 +751,7 @@ register int mmflags;
boolean anymon = (!ptr);
boolean byyou = (x == u.ux && y == u.uy);
boolean allow_minvent = ((mmflags & NO_MINVENT) == 0);
boolean countbirth = ((mmflags & MM_NOCOUNTBIRTH) == 0);
uchar lim;
/* if caller wants random location, do it here */
@@ -818,10 +819,10 @@ register int mmflags;
* the caller manually decrement mvitals if the monster is created
* under circumstances where one would not logically expect the
* creation to reduce the supply of wild monsters. Monster cloning
* might be one such case, but we go against logic there in order to
* might be one such case, but we go against logic there in order to
* reduce the possibility of abuse.
*/
if (mvitals[mndx].born < 255) mvitals[mndx].born++;
if (mvitals[mndx].born < 255 && countbirth) mvitals[mndx].born++;
lim = mbirth_limit(mndx);
if ((int) mvitals[mndx].born >= lim && !(mons[mndx].geno & G_NOGEN) &&
!(mvitals[mndx].mvflags & G_EXTINCT)) {
+8 -7
View File
@@ -217,10 +217,10 @@ rndmonnum() /* select a random, common monster type */
}
/*
* Split obj so that it gets size num. The remainder is put in the object
* structure delivered by this call. The object is positioned just
* following the original in the nobj chain (and nexthere chain when on
* the floor).
* Split obj so that it gets size gets reduced by num. The quantity num is
* put in the object structure delivered by this call. The returned object
* has its wornmask cleared and is positioned just following the original
* in the nobj chain (and nexthere chain when on the floor).
*/
struct obj *
splitobj(obj, num)
@@ -229,7 +229,7 @@ long num;
{
struct obj *otmp;
if (obj->cobj || num <= 0L || obj->quan < num)
if (obj->cobj || num <= 0L || obj->quan <= num)
panic("splitobj"); /* can't split containers */
otmp = newobj(obj->oxlth + obj->onamelth);
*otmp = *obj; /* copies whole structure */
@@ -237,9 +237,10 @@ long num;
if (!otmp->o_id) otmp->o_id = flags.ident++; /* ident overflowed */
otmp->timed = 0; /* not timed, yet */
otmp->lamplit = 0; /* ditto */
obj->quan = num;
otmp->owornmask = 0L; /* new object isn't worn */
obj->quan -= num;
obj->owt = weight(obj);
otmp->quan -= num;
otmp->quan = num;
otmp->owt = weight(otmp); /* -= obj->owt ? */
obj->nobj = otmp;
/* Only set nexthere when on the floor, nexthere is also used */
+3 -3
View File
@@ -297,7 +297,7 @@ register struct monst *mtmp;
register int tmp=0;
int inrange, nearby, scared;
#ifdef GOLDOBJ
struct obj *ygold, *lepgold;
struct obj *ygold = 0, *lepgold = 0;
#endif
/* Pre-movement adjustments */
@@ -474,8 +474,8 @@ toofar:
(mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||
#else
if (mdat->mlet == S_LEPRECHAUN) {
ygold = findgold(invent);
lepgold = findgold(mtmp->minvent);
ygold = findgold(invent);
lepgold = findgold(mtmp->minvent);
}
if(!nearby || mtmp->mflee || scared ||
+3 -3
View File
@@ -1987,7 +1987,7 @@ struct permonst _mons2[] = {
* Vampires
*/
MON("vampire", S_VAMPIRE,
LVL(10, 12, 1, 25, -8), (G_GENO|1),
LVL(10, 12, 1, 25, -8), (G_GENO|G_NOCORPSE|1),
A(ATTK(AT_CLAW, AD_PHYS, 1, 6), ATTK(AT_BITE, AD_DRLI, 1, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
@@ -1995,7 +1995,7 @@ struct permonst _mons2[] = {
M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY, M3_INFRAVISIBLE,
CLR_RED),
MON("vampire lord", S_VAMPIRE,
LVL(12, 14, 0, 50, -9), (G_GENO|1),
LVL(12, 14, 0, 50, -9), (G_GENO|G_NOCORPSE|1),
A(ATTK(AT_CLAW, AD_PHYS, 1, 8), ATTK(AT_BITE, AD_DRLI, 1, 8),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
@@ -2004,7 +2004,7 @@ struct permonst _mons2[] = {
M3_INFRAVISIBLE, CLR_BLUE),
#if 0 /* DEFERRED */
MON("vampire mage", S_VAMPIRE,
LVL(20, 14, -4, 50, -9), (G_GENO|1),
LVL(20, 14, -4, 50, -9), (G_GENO|G_NOCORPSE|1),
A(ATTK(AT_CLAW, AD_DRLI, 2, 8), ATTK(AT_BITE, AD_DRLI, 1, 8),
ATTK(AT_MAGC, AD_SPEL, 2, 6), NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0,
+2 -1
View File
@@ -282,7 +282,7 @@ m_throw(mon, x, y, dx, dy, range, obj)
singleobj = obj;
obj = (struct obj *) 0;
} else {
singleobj = splitobj(obj, obj->quan - 1L);
singleobj = splitobj(obj, 1L);
obj_extract_self(singleobj);
}
@@ -557,6 +557,7 @@ struct monst *mtmp;
case PM_ROGUE:
if (skill == P_DAGGER) multishot++;
break;
case PM_NINJA:
case PM_SAMURAI:
if (otmp->otyp == YA && mwep &&
mwep->otyp == YUMI) multishot++;
+3 -3
View File
@@ -875,10 +875,10 @@ WAND((char *)0, "jeweled", 0, 150, 1, 0, IRON, HI_MINERAL),
#undef WAND
/* coins ... - so far, gold is all there is */
#define COIN(name,prob,metal) OBJECT( \
#define COIN(name,prob,metal,worth) OBJECT( \
OBJ(name,(char *)0), BITS(0,1,0,0,0,0,0,0,0,0,0,P_NONE,metal), 0, \
GOLD_CLASS, prob, 0, 1, 0, 0, 0, 0, 0, 0, HI_GOLD )
COIN("gold piece", 1000, GOLD),
GOLD_CLASS, prob, 0, 1, worth, 0, 0, 0, 0, 0, HI_GOLD )
COIN("gold piece", 1000, GOLD,1),
#undef COIN
/* gems ... - includes stones and rocks but not boulders */
+6 -7
View File
@@ -1,4 +1,4 @@
/* SCCS Id: @(#)objnam.c 3.3 2001/10/29 */
/* SCCS Id: @(#)objnam.c 3.3 2002/01/04 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2430,17 +2430,16 @@ typfnd:
makeplural(body_part(HAND)));
}
otmp->owt = weight(otmp);
if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160;
if (halfeaten && otmp->oclass == FOOD_CLASS) {
if (otmp->otyp == CORPSE)
otmp->oeaten = mons[otmp->corpsenm].cnutrit;
else otmp->oeaten = objects[otmp->otyp].oc_nutrition;
otmp->owt /= 2;
otmp->oeaten /= 2;
if (!otmp->owt) otmp->owt = 1;
if (!otmp->oeaten) otmp->oeaten = 1;
/* (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);
}
+5
View File
@@ -115,6 +115,11 @@ static struct Bool_Opt
#else
{"mail", (boolean *)0, TRUE},
#endif
#ifdef TTY_GRAPHICS
{"msg_window", &iflags.prevmsg_window, FALSE},
#else
{"msg_window", (boolean *)0, FALSE},
#endif
#ifdef NEWS
{"news", &iflags.news, TRUE},
#else
+19 -16
View File
@@ -1081,11 +1081,10 @@ long count;
boolean telekinesis; /* not picking it up directly by hand */
{
int res, nearload;
#ifdef GOLDOBJ
long umoney = money_cnt(invent);
#endif
#ifndef GOLDOBJ
const char *where = (obj->ox == u.ux && obj->oy == u.uy) ?
"here" : "there";
#endif
if (obj->quan < count) {
impossible("pickup_object: count %ld > quan %ld?",
@@ -1191,13 +1190,14 @@ boolean telekinesis; /* not picking it up directly by hand */
if (obj->oclass == GOLD_CLASS) flags.botl = 1;
#endif
if (obj->quan != count && obj->otyp != LOADSTONE)
(void) splitobj(obj, count);
obj = splitobj(obj, count);
obj = pick_obj(obj);
if (uwep && uwep == obj) mrg_to_wielded = TRUE;
nearload = near_capacity();
prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0, obj, count);
prinv(nearload == SLT_ENCUMBER ? moderateloadmsg : (char *) 0,
obj, count);
mrg_to_wielded = FALSE;
return 1;
}
@@ -1406,12 +1406,15 @@ lootcont:
struct obj *goldob = mkgoldobj(contribution);
#else
struct obj *goldob;
/* Find a money object to mess with */
for (goldob = invent; goldob; goldob = goldob->nobj) ;
/* Find a money object to mess with */
for (goldob = invent; goldob; goldob = goldob->nobj) {
if (goldob->oclass == GOLD_CLASS) break;
}
if (goldob){
long contribution = rnd((int)min(LARGEST_INT, goldob->quan));
if (contribution < goldob->quan) (void)splitobj(goldob, contribution);
freeinv(goldob);
if (contribution < goldob->quan)
goldob = splitobj(goldob, contribution);
freeinv(goldob);
#endif
if (IS_THRONE(levl[u.ux][u.uy].typ)){
struct obj *coffers;
@@ -1515,11 +1518,12 @@ struct monst *mtmp;
int *passed_info;
boolean *prev_loot;
{
struct obj *otmp;
int c = -1;
int timepassed = 0;
char qbuf[QBUFSZ];
#ifdef STEED
struct obj *otmp;
char qbuf[QBUFSZ];
/* 3.3.1 introduced the ability to remove saddle from a steed */
/* *passed_info is set to TRUE if a loot query was given. */
/* *prev_loot is set to TRUE if something was actually acquired in here. */
@@ -1789,7 +1793,7 @@ register struct obj *obj;
return res;
if (obj->quan != count && obj->otyp != LOADSTONE)
(void) splitobj(obj, count);
obj = splitobj(obj, count);
/* Remove the object from the list. */
obj_extract_self(obj);
@@ -1822,7 +1826,9 @@ register struct obj *obj;
otmp, count);
if (is_gold) {
#ifndef GOLDOBJ
dealloc_obj(obj);
#endif
bot(); /* update character's gold piece count immediately */
}
return 1;
@@ -2109,11 +2115,8 @@ boolean put_in;
otmp = pick_list[i].item.a_obj;
count = pick_list[i].count;
if (count > 0 && count < otmp->quan) {
otmp2 = splitobj(otmp, count);
otmp = splitobj(otmp, count);
/* special split case also handled by askchain() */
if (otmp == uwep) setuwep(otmp2);
if (otmp == uquiver) setuqwep(otmp2);
if (otmp == uswapwep) setuswapwep(otmp2);
}
res = put_in ? in_container(otmp) : out_container(otmp);
if (res < 0)
+1 -1
View File
@@ -1817,7 +1817,7 @@ dodip()
/* with multiple merged potions, split off one and
just clear it */
if (potion->quan > 1L) {
singlepotion = splitobj(potion, potion->quan - 1L);
singlepotion = splitobj(potion, 1L);
} else singlepotion = potion;
if(singlepotion->unpaid && costly_spot(u.ux, u.uy)) {
+1 -4
View File
@@ -111,10 +111,7 @@ int how;
#ifndef GOLDOBJ
Sprintf(buf, "%ld Au", u.ugold);
#else
/* FIXME: this neglects gold in containers (which will be gone by
now if bones have been saved). For the !GOLDOBJ configuration,
any such gold gets added into u.ugold by done(). */
Sprintf(buf, "%ld Au", money_cnt(invent));
Sprintf(buf, "%ld Au", done_money);
#endif
buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */
center(GOLD_LINE, buf);
+7 -2
View File
@@ -146,11 +146,16 @@ int mechanism;
boolean reading = (mechanism == BY_COOKIE ||
mechanism == BY_PAPER);
if (reading && Blind) {
if (reading) {
/* deal with various things that prevent reading */
if (is_fainted() && mechanism == BY_COOKIE)
return;
else if (Blind) {
if (mechanism == BY_COOKIE)
pline(fortune_msg);
pline("What a pity that you cannot read it!");
return;
return;
}
}
line = getrumor(truth, buf, reading ? FALSE : TRUE);
if (!*line)
+5 -7
View File
@@ -103,7 +103,7 @@ long amount;
return 0;
}
if (ygold->quan > amount) splitobj(ygold, amount);
if (ygold->quan > amount) ygold = splitobj(ygold, amount);
freeinv(ygold);
add_to_minv(mon, ygold);
flags.botl = 1;
@@ -131,7 +131,7 @@ long amount;
return;
}
if (mongold->quan > amount) splitobj(mongold, amount);
if (mongold->quan > amount) mongold = splitobj(mongold, amount);
obj_extract_self(mongold);
if (!merge_choice(invent, mongold) && inv_cnt() >= 52) {
@@ -2748,11 +2748,9 @@ int mode; /* 0: deliver count 1: paged */
uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
thisused = bp->price * uquan;
totused += thisused;
obj->quan = uquan; /* cheat doname */
obj->unpaid = 0; /* ditto */
/* Why 'x'? To match `I x', more or less. */
buf_p = xprname(obj, (char *)0, 'x', FALSE, thisused);
obj->quan = oquan; /* restore value */
buf_p = xprname(obj, (char *)0, 'x', FALSE, thisused, uquan);
#ifdef __SASC
/* SAS/C 6.2 can't cope for some reason */
sasc_bug(obj,save_unpaid);
@@ -2768,10 +2766,10 @@ int mode; /* 0: deliver count 1: paged */
totused += eshkp->debit;
buf_p = xprname((struct obj *)0,
"usage charges and/or other fees",
GOLD_SYM, FALSE, eshkp->debit);
GOLD_SYM, FALSE, eshkp->debit, 0L);
putstr(datawin, 0, buf_p);
}
buf_p = xprname((struct obj *)0, "Total:", '*', FALSE, totused);
buf_p = xprname((struct obj *)0, "Total:", '*', FALSE, totused, 0L);
putstr(datawin, 0, "");
putstr(datawin, 0, buf_p);
display_nhwindow(datawin, FALSE);
+2 -2
View File
@@ -850,8 +850,8 @@ struct mkroom *croom;
case M_AP_OBJECT:
for (i = 0; i < NUM_OBJECTS; i++)
if (!strcmp(OBJ_NAME(objects[i]),
m->appear_as.str))
if (OBJ_NAME(objects[i]) &&
!strcmp(OBJ_NAME(objects[i]),m->appear_as.str))
break;
if (i == NUM_OBJECTS) {
impossible(
+7 -2
View File
@@ -1,4 +1,4 @@
/* SCCS Id: @(#)steal.c 3.3 2001/10/15 */
/* SCCS Id: @(#)steal.c 3.3 2002/01/04 */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -123,7 +123,7 @@ register struct monst *mtmp;
const int gold_price = objects[GOLD_PIECE].oc_cost;
tmp = (somegold(money_cnt(invent)) + gold_price - 1) / gold_price;
tmp = min(tmp, ygold->quan);
if (tmp < ygold->quan) splitobj(ygold, tmp);
if (tmp < ygold->quan) ygold = splitobj(ygold, tmp);
freeinv(ygold);
add_to_minv(mtmp, ygold);
Your("purse feels lighter.");
@@ -229,6 +229,11 @@ char *objnambuf;
/* the following is true if successful on first of two attacks. */
if(!monnear(mtmp, u.ux, u.uy)) return(0);
/* food being eaten might already be used up but will not have
been removed from inventory yet; we don't want to steal that,
so this will cause it to be removed now */
if (occupation) (void) maybe_finished_meal(FALSE);
if (!invent || (inv_cnt() == 1 && uskin)) {
nothing_to_steal:
/* Not even a thousand men in armor can strip a naked man. */
+26 -2
View File
@@ -204,7 +204,19 @@ void
teleds(nux, nuy)
register int nux,nuy;
{
if (Punished) unplacebc();
boolean dont_teleport_ball = FALSE;
if (Punished) {
/* If they're teleporting to a position where the ball doesn't need
* to be moved, don't place the ball. Especially useful when this
* function is being called for crawling out of water instead of
* real teleportation.
*/
if (!carried(uball) && distmin(nux, nuy, uball->ox, uball->oy) <= 2)
dont_teleport_ball = TRUE;
else
unplacebc();
}
u.utrap = 0;
u.ustuck = 0;
u.ux0 = u.ux;
@@ -228,7 +240,19 @@ register int nux,nuy;
u.uswldtim = u.uswallow = 0;
docrt();
}
if (Punished) placebc();
if (Punished) {
if (dont_teleport_ball) {
int bc_control;
xchar ballx, bally, chainx, chainy;
boolean cause_delay;
/* this should only drag the chain (and never give a near-
capacity message) since we already checked ball distance */
drag_ball(u.ux, u.uy, &bc_control, &ballx, &bally, &chainx, &chainy, &cause_delay);
move_bc(0, bc_control, ballx, bally, chainx, chainy);
} else
placebc();
}
initrack(); /* teleports mess up tracking monsters without this */
update_player_regions();
#ifdef STEED
+1 -1
View File
@@ -1160,7 +1160,7 @@ int style;
singleobj = otmp;
otmp = (struct obj *) 0;
} else {
singleobj = splitobj(otmp, otmp->quan - 1L);
singleobj = splitobj(otmp, 1L);
obj_extract_self(singleobj);
}
newsym(x1,y1);
+1 -1
View File
@@ -634,7 +634,7 @@ int thrown;
}
} else if(obj->oclass == POTION_CLASS) {
if (obj->quan > 1L)
setworn(splitobj(obj, 1L), W_WEP);
obj = splitobj(obj, 1L);
else
setuwep((struct obj *)0);
freeinv(obj);
+25 -11
View File
@@ -6,6 +6,7 @@
STATIC_DCL void FDECL(m_lose_armor, (struct monst *,struct obj *));
STATIC_DCL void FDECL(m_dowear_type, (struct monst *,long,BOOLEAN_P));
STATIC_DCL int FDECL(extra_pref, (struct monst *, struct obj *));
const struct worn {
long w_mask;
@@ -114,16 +115,16 @@ register struct obj *obj;
if (!obj) return;
if (obj == uwep || obj == uswapwep) u.twoweap = 0;
for(wp = worn; wp->w_mask; wp++)
if(obj == *(wp->w_obj)) {
*(wp->w_obj) = 0;
p = objects[obj->otyp].oc_oprop;
u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask;
obj->owornmask &= ~wp->w_mask;
if (obj->oartifact)
set_artifact_intrinsic(obj, 0, wp->w_mask);
if ((p = w_blocks(obj,wp->w_mask)) != 0)
u.uprops[p].blocked &= ~wp->w_mask;
}
if(obj == *(wp->w_obj)) {
*(wp->w_obj) = 0;
p = objects[obj->otyp].oc_oprop;
u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask;
obj->owornmask &= ~wp->w_mask;
if (obj->oartifact)
set_artifact_intrinsic(obj, 0, wp->w_mask);
if ((p = w_blocks(obj,wp->w_mask)) != 0)
u.uprops[p].blocked &= ~wp->w_mask;
}
update_inventory();
}
@@ -404,7 +405,8 @@ boolean creation;
* it would forget spe and once again think the object is better
* than what it already has.
*/
if (best && (ARM_BONUS(best) >= ARM_BONUS(obj))) continue;
if (best && (ARM_BONUS(best) + extra_pref(mon,best) >= ARM_BONUS(obj) + extra_pref(mon,obj)))
continue;
best = obj;
}
outer_break:
@@ -667,4 +669,16 @@ boolean polyspot;
return;
}
/* bias a monster's preferences towards armor that has special benefits. */
/* currently only does speed boots, but might be expanded if monsters get to
use more armor abilities */
static int
extra_pref(struct monst *mon, struct obj *obj)
{
if (obj) {
if (obj->otyp == SPEED_BOOTS && mon->permspeed != MFAST)
return 20;
}
return 0;
}
/*worn.c*/
+17 -9
View File
@@ -140,6 +140,7 @@ struct obj *otmp;
case SPE_SLOW_MONSTER:
if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
mon_adjust_speed(mtmp, -1);
m_dowear(mtmp, FALSE); /* might want speed boots */
if (u.uswallow && (mtmp == u.ustuck) &&
is_whirly(mtmp->data)) {
You("disrupt %s!", mon_nam(mtmp));
@@ -149,8 +150,10 @@ struct obj *otmp;
}
break;
case WAN_SPEED_MONSTER:
if (!resist(mtmp, otmp->oclass, 0, NOTELL))
if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
mon_adjust_speed(mtmp, 1);
m_dowear(mtmp, FALSE); /* might want speed boots */
}
break;
case WAN_UNDEAD_TURNING:
case SPE_TURN_UNDEAD:
@@ -450,7 +453,7 @@ coord *cc;
if (mtmp2->mhpmax <= 0 && !is_rider(mtmp2->data))
return (struct monst *)0;
mtmp = makemon(mtmp2->data,
cc->x, cc->y, NO_MINVENT|MM_NOWAIT);
cc->x, cc->y, NO_MINVENT|MM_NOWAIT|MM_NOCOUNTBIRTH);
if (!mtmp) return mtmp;
/* heal the monster */
@@ -610,7 +613,7 @@ register struct obj *obj;
wary_dog(mtmp, TRUE);
} else
mtmp = makemon(&mons[montype], x, y,
NO_MINVENT|MM_NOWAIT);
NO_MINVENT|MM_NOWAIT|MM_NOCOUNTBIRTH);
if (mtmp) {
if (obj->oxlth && (obj->oattached == OATTACHED_M_ID)) {
unsigned m_id;
@@ -666,7 +669,7 @@ register struct obj *obj;
x = obj->ox, y = obj->oy;
/* not useupf(), which charges */
if (obj->quan > 1L)
(void) splitobj(obj, 1L);
obj = splitobj(obj, 1L);
delobj(obj);
newsym(x, y);
break;
@@ -1134,9 +1137,9 @@ struct obj *obj;
/* if quan > 1 then some will survive intact */
if (obj->quan > 1L) {
if (obj->quan > LARGEST_INT)
(void) splitobj(obj, (long)rnd(30000));
obj = splitobj(obj, (long)rnd(30000));
else
(void) splitobj(obj, (long)rnd((int)obj->quan - 1));
obj = splitobj(obj, (long)rnd((int)obj->quan - 1));
}
/* appropriately add damage to bill */
@@ -2504,10 +2507,13 @@ register const char *str;
register struct monst *mtmp;
register const char *force; /* usually either "." or "!" */
{
int pl = strcmp(str, makesingular(str));
if((!cansee(bhitpos.x,bhitpos.y) && !canspotmon(mtmp))
|| !flags.verbose)
pline("%s hits it.", The(str));
else pline("%s hits %s%s", The(str), mon_nam(mtmp), force);
pline("%s %s it.", The(str), pl ? "hit" : "hits");
else pline("%s %s %s%s", The(str), pl ? "hit" : "hits",
mon_nam(mtmp), force);
}
void
@@ -2515,7 +2521,9 @@ miss(str,mtmp)
register const char *str;
register struct monst *mtmp;
{
pline("%s misses %s.", The(str),
int pl = strcmp(str, makesingular(str));
pline("%s %s %s.", The(str), pl ? "miss" : "misses",
((cansee(bhitpos.x,bhitpos.y) || canspotmon(mtmp))
&& flags.verbose) ?
mon_nam(mtmp) : "it");