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
View File
@@ -71,6 +71,9 @@ timed_delay on unix and VMS, use a timer instead of sending
display effect. on MSDOS without the termcap display effect. on MSDOS without the termcap
lib, whether or not to pause for visual effect. [TRUE] lib, whether or not to pause for visual effect. [TRUE]
Boolean option if TTY_GRAPHICS was set at compile time:
msg_window show previous messages in a screen-size window [FALSE]
Boolean option if USE_TILES was set at compile time (MSDOS protected mode only): Boolean option if USE_TILES was set at compile time (MSDOS protected mode only):
preload_tiles control whether tiles get pre-loaded into RAM at the preload_tiles control whether tiles get pre-loaded into RAM at the
start of the game. Doing so enhances performance start of the game. Doing so enhances performance
+3
View File
@@ -1863,6 +1863,9 @@ Cannot be set with the `O' command.
.lp msghistory .lp msghistory
The number of top line messages to save (and recall with ^P) (default 20). The number of top line messages to save (and recall with ^P) (default 20).
Cannot be set with the `O' command. Cannot be set with the `O' command.
.lp msg_window
Use a screen-size window to show the previous messages with ^P instead of
showing them one at a time. (Currently implemented for tty only.)
.lp "name " .lp "name "
Set your character's name (defaults to your user name). You can also Set your character's name (defaults to your user name). You can also
set your character's role by appending a dash and one or more letters of set your character's role by appending a dash and one or more letters of
+4
View File
@@ -2299,6 +2299,10 @@ Cannot be set with the `{\tt O}' command.
The number of top line messages to save (and recall with `{\tt \^{}P}') The number of top line messages to save (and recall with `{\tt \^{}P}')
(default 20). Cannot be set with the `{\tt O}' command. (default 20). Cannot be set with the `{\tt O}' command.
%.lp %.lp
\item[\ib{msg\_window}]
Use a screen-size window to show the previous messages with `{\tt \^{}P}'
instead of showing them one at a time. (Currently implemented for tty only.)
%.lp
\item[\ib{name}] \item[\ib{name}]
Set your character's name (defaults to your user name). You can also Set your character's name (defaults to your user name). You can also
set your character's role by appending a dash and one or more letters of set your character's role by appending a dash and one or more letters of
+1 -27
View File
@@ -51,9 +51,6 @@ Drain life requires you to reach floor to wipe an engraving.
Orc monsters should be given poison res? [psmith@spod-central.org] Orc monsters should be given poison res? [psmith@spod-central.org]
Ninja monsters should get multishot bonuses with yumi-ya?
[psmith@spod-central.org]
Chromatic Dragon should have reflection? [psmith@spod-central.org] Chromatic Dragon should have reflection? [psmith@spod-central.org]
stone-to-flesh monsters' inventory? [psmith@spod-central.org] stone-to-flesh monsters' inventory? [psmith@spod-central.org]
@@ -61,15 +58,6 @@ stone-to-flesh monsters' inventory? [psmith@spod-central.org]
Releasing your pet from a bear trap by displacing is silly. Releasing your pet from a bear trap by displacing is silly.
[eino.keskitalo@purkki.mbnet.fi] [eino.keskitalo@purkki.mbnet.fi]
When punished, being teleported always places the iron ball underneath you
even when you land at a spot that's within range of the current ball&chain
position. Since the teleport mechanism is used for crawling out of water,
this can produce an even stranger effect: if you're carrying the attached
ball when you step into water and it happens to be chosen as an item to
drop in order to lighten your load, it will end up crawling out of the
water with you. (Ie, it will end up underneath you on land rather than in
the adjacent water where it was actually dropped.)
Monster spellcasting is in serious need of overhaul. Monster spellcasting is in serious need of overhaul.
Clerical spell `case 1' has ``if (...) {} /* else fall into default */'' Clerical spell `case 1' has ``if (...) {} /* else fall into default */''
but the default case has been moved away so the comment is a lie. but the default case has been moved away so the comment is a lie.
@@ -96,18 +84,6 @@ inefficient when multiple objects are migrating. It might be better to place
all of the migrating objects that are being scattered onto a special obj all of the migrating objects that are being scattered onto a special obj
chain which scatter() could easily be changed to accomodate. chain which scatter() could easily be changed to accomodate.
Occasionally an eating attempt which gets interrupted will produce a
food object that is not flagged as partially eaten, even though it did
get split out of a merged group. (Observed in both 3.1.3 and 3.2.2),
for ordinary food rations carried in the player's inventory.)
Occasionally player will get messages about become encumbered while eating,
when they didn't begin eating encumbered, but they return to proper encum-
berance when finished eating. There is also a problem with partly eaten
food rations carrying the wrong nutritional value (player can start out weak,
get interrupted, finish the partly eaten ration, and end up satiated) which is
likely the same bug.
For "traditional" menu style, pickup and #loot/apply can't accept an 'm' For "traditional" menu style, pickup and #loot/apply can't accept an 'm'
response to bring up a menu upon request when all items involved are of response to bring up a menu upon request when all items involved are of
the same class, because the prompt where that response is allowed only the same class, because the prompt where that response is allowed only
@@ -128,9 +104,7 @@ The resistance delays are very slow on some machines and fine on others, with
no apparent pattern. There is a proposal to do timing in a different manner. no apparent pattern. There is a proposal to do timing in a different manner.
Monsters do not get affected by special properties of many types of armor, Monsters do not get affected by special properties of many types of armor,
like levitation boots. They do get affected by speed boots, but do not like levitation boots.
consider such items to be any better than other shoes which grant 1 point
of AC when deciding whether to wear them.
Corpses buried under ice ought to be handled as if they were inside an Corpses buried under ice ought to be handled as if they were inside an
ice box. ice box.
+22
View File
@@ -349,6 +349,25 @@ make blindness with just 1 turn remaining be a candicate for repair by
healing potions/spells shouldn't fix being creamed healing potions/spells shouldn't fix being creamed
make pie throwing and venom spitting by the player be consistent with the make pie throwing and venom spitting by the player be consistent with the
effects of those attacks by monsters effects of those attacks by monsters
offering & tinning corpses on altars should work even while riding
It was possible to faint after eating a fortune cookie and still read
the fortune's text despite being unconscious
when filling a pit containing a vortex, a surviving vortex gets untrapped
teleporting no longer moves the iron ball to under you if that's not necessary;
prevents odd ball movement when crawling out of water
monsters now prefer to wear speed boots over other boots
prevent crash when loading a special level specifying a mimic using m_object
prevent crashes caused by dropping or shipping quivered or secondary weapons
don't trigger spurious encumbrance messages on last turn of a multi-turn meal
prevent food being restored to untouched status if interrupted while eating
troll revival shouldn't increment the troll creation counter
breaking mirrors and your eggs should be bad luck when kicking chests as well
as throwing
vampires should be G_NOCORPSE so you can't wish for them
glass objects should break when thrown, just like when kicked in chests
rocks/gems shouldn't be hard to throw by hand because they are ammo
avoid all cases where splitting an object would result in two objects being
quivered, wielded or otherwise having its owornflag set
Platform- and/or Interface-Specific Fixes Platform- and/or Interface-Specific Fixes
@@ -378,6 +397,7 @@ X11: allow extra space added to map widget to be removed if widget shrinks
Gnome: workaround for GTK+ attempts to disallow setgid executables Gnome: workaround for GTK+ attempts to disallow setgid executables
X11: general solution to the problem that the meaning of font height varies X11: general solution to the problem that the meaning of font height varies
among different implementations of X11 among different implementations of X11
X11: make "slow" mode the default since it seems to be very prevalent
General New Features General New Features
@@ -433,6 +453,8 @@ blessed gold detection now detects anything made of gold, not just
new T-shirt messages from Scott Bigham new T-shirt messages from Scott Bigham
option to get rid of resistance 'sparkle' (shieldeffect) (Scott Bigham) option to get rid of resistance 'sparkle' (shieldeffect) (Scott Bigham)
glowing Sunsword (inspired by Slashem) glowing Sunsword (inspired by Slashem)
msg_window option for ^P in TTY mode (Jay Tilton)
ninjas should get multishot bonus with yumi and ya (Dylan O'Donnell)
Platform- and/or Interface-Specific New Features Platform- and/or Interface-Specific New Features
+3
View File
@@ -171,6 +171,9 @@ E NEARDATA char *save_cm;
E NEARDATA int killer_format; E NEARDATA int killer_format;
E const char *killer; E const char *killer;
E const char *delayed_killer; E const char *delayed_killer;
#ifdef GOLDOBJ
E long done_money;
#endif
E char killer_buf[BUFSZ]; E char killer_buf[BUFSZ];
E const char *configfile; E const char *configfile;
E NEARDATA char plname[PL_NSIZ]; E NEARDATA char plname[PL_NSIZ];
+4 -2
View File
@@ -1,4 +1,4 @@
/* SCCS Id: @(#)extern.h 3.3 2001/09/06 */ /* SCCS Id: @(#)extern.h 3.3 2002/01/04 */
/* Copyright (c) Steve Creps, 1988. */ /* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -521,6 +521,8 @@ E int FDECL(eaten_stat, (int,struct obj *));
E void FDECL(food_disappears, (struct obj *)); E void FDECL(food_disappears, (struct obj *));
E void FDECL(food_substitution, (struct obj *,struct obj *)); E void FDECL(food_substitution, (struct obj *,struct obj *));
E void NDECL(fix_petrification); E void NDECL(fix_petrification);
E void FDECL(consume_oeaten, (struct obj *,int));
E boolean FDECL(maybe_finished_meal, (BOOLEAN_P));
/* ### end.c ### */ /* ### end.c ### */
@@ -751,7 +753,7 @@ E void FDECL(identify_pack, (int));
E int FDECL(askchain, (struct obj **,const char *,int,int (*)(OBJ_P), E int FDECL(askchain, (struct obj **,const char *,int,int (*)(OBJ_P),
int (*)(OBJ_P),int,const char *)); int (*)(OBJ_P),int,const char *));
E void FDECL(prinv, (const char *,struct obj *,long)); E void FDECL(prinv, (const char *,struct obj *,long));
E char *FDECL(xprname, (struct obj *,const char *,CHAR_P,BOOLEAN_P,long)); E char *FDECL(xprname, (struct obj *,const char *,CHAR_P,BOOLEAN_P,long,long));
E int NDECL(ddoinv); E int NDECL(ddoinv);
E char FDECL(display_inventory, (const char *,BOOLEAN_P)); E char FDECL(display_inventory, (const char *,BOOLEAN_P));
E int FDECL(display_binventory, (int,int,BOOLEAN_P)); E int FDECL(display_binventory, (int,int,BOOLEAN_P));
+3
View File
@@ -216,6 +216,9 @@ struct instance_flags {
boolean lan_mail_fetched; /* mail is awaiting display */ boolean lan_mail_fetched; /* mail is awaiting display */
#endif #endif
uchar bouldersym; /* alternative boulder symbol */ uchar bouldersym; /* alternative boulder symbol */
#ifdef TTY_GRAPHICS
boolean prevmsg_window; /* show more old messages at a time */
#endif
}; };
extern NEARDATA struct flag flags; extern NEARDATA struct flag flags;
+1
View File
@@ -138,6 +138,7 @@ NEARDATA extern coord bhitpos; /* place where throw or zap hits or stops */
#define MM_EMIN 0x08 /* add emin structure */ #define MM_EMIN 0x08 /* add emin structure */
#define MM_ANGRY 0x10 /* monster is created angry */ #define MM_ANGRY 0x10 /* monster is created angry */
#define MM_NONAME 0x20 /* monster is not christened */ #define MM_NONAME 0x20 /* monster is not christened */
#define MM_NOCOUNTBIRTH 0x40 /* don't increment born counter (for revival) */
/* flags for special ggetobj status returns */ /* flags for special ggetobj status returns */
#define ALL_FINISHED 0x01 /* called routine already finished the job */ #define ALL_FINISHED 0x01 /* called routine already finished the job */
+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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -415,7 +415,8 @@ void
stop_occupation() stop_occupation()
{ {
if(occupation) { if(occupation) {
You("stop %s.", occtxt); if (!maybe_finished_meal(TRUE))
You("stop %s.", occtxt);
occupation = 0; occupation = 0;
flags.botl = 1; /* in case u.uhs changed */ flags.botl = 1; /* in case u.uhs changed */
/* fainting stops your occupation, there's no reason to sync. /* fainting stops your occupation, there's no reason to sync.
+2 -2
View File
@@ -936,7 +936,7 @@ register struct obj *obj;
return; return;
} else { } else {
if ((long)otmp->spe + obj->quan > 7L) 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.", You("attach %ld%s candle%s to %s.",
obj->quan, !otmp->spe ? "" : " more", obj->quan, !otmp->spe ? "" : " more",
plur(obj->quan), the(xname(otmp))); plur(obj->quan), the(xname(otmp)));
@@ -1107,7 +1107,7 @@ light_cocktail(obj)
makeknown(obj->otyp); makeknown(obj->otyp);
if (obj->quan > 1L) { if (obj->quan > 1L) {
(void) splitobj(obj, 1L); obj = splitobj(obj, 1L);
begin_burn(obj, FALSE); /* burn before free to get position */ begin_burn(obj, FALSE); /* burn before free to get position */
obj_extract_self(obj); /* free from inv */ 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 /* 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 boolean
drag_ball(x, y, bc_control, ballx, bally, chainx, chainy, cause_delay) drag_ball(x, y, bc_control, ballx, bally, chainx, chainy, cause_delay)
@@ -368,27 +369,108 @@ boolean *cause_delay;
return TRUE; return TRUE;
} }
if (carried(uball) || dist2(x, y, uball->ox, uball->oy) < 3 || /* only need to move the chain? */
(uball->ox == uchain->ox && uball->oy == uchain->oy)) { if (carried(uball) || distmin(x, y, uball->ox, uball->oy) <= 2) {
/*
* 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
*/
*bc_control = BC_CHAIN; *bc_control = BC_CHAIN;
move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy); move_bc(1, *bc_control, *ballx, *bally, *chainx, *chainy);
if (dist2(x, y, uball->ox, uball->oy) == 2 && if (carried(uball)) {
dist2(x, y, uchain->ox, uchain->oy) == 4) { /* move chain only if necessary; assume they didn't teleport */
if (uchain->oy == y) if (distmin(x, y, uchain->ox, uchain->oy) > 1) {
*chainx = uball->ox; *chainx = u.ux;
else *chainy = u.uy;
*chainy = uball->oy; }
} else { return TRUE;
*chainx = u.ux;
*chainy = u.uy;
} }
#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; return TRUE;
} }
+3
View File
@@ -48,6 +48,9 @@ NEARDATA char *save_cm = 0;
NEARDATA int killer_format = 0; NEARDATA int killer_format = 0;
const char *killer = 0; const char *killer = 0;
const char *delayed_killer = 0; const char *delayed_killer = 0;
#ifdef GOLDOBJ
NEARDATA long done_money = 0;
#endif
char killer_buf[BUFSZ] = DUMMY; char killer_buf[BUFSZ] = DUMMY;
const char *nomovemsg = 0; const char *nomovemsg = 0;
const char nul[40] = DUMMY; /* contains zeros */ const char nul[40] = DUMMY; /* contains zeros */
+31 -27
View File
@@ -171,9 +171,10 @@ const char *verb;
if (mtmp) { if (mtmp) {
if (!passes_walls(mtmp->data) && if (!passes_walls(mtmp->data) &&
!throws_rocks(mtmp->data)) { !throws_rocks(mtmp->data)) {
if (hmon(mtmp, obj, TRUE)) if (hmon(mtmp, obj, TRUE) && !is_whirly(mtmp->data))
return FALSE; /* still alive */ return FALSE; /* still alive */
} else mtmp->mtrapped = 0; }
mtmp->mtrapped = 0;
} else { } else {
if (!Passes_walls && !throws_rocks(youmonst.data)) { if (!Passes_walls && !throws_rocks(youmonst.data)) {
losehp(rnd(15), "squished under a boulder", losehp(rnd(15), "squished under a boulder",
@@ -523,31 +524,35 @@ void
dropy(obj) dropy(obj)
register struct obj *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; if (!u.uswallow && flooreffects(obj,u.ux,u.uy,"drop")) return;
/* uswallow check done by GAN 01/29/87 */ /* uswallow check done by GAN 01/29/87 */
obj_no_longer_held(obj); obj_no_longer_held(obj);
if(u.uswallow) { if(u.uswallow) {
boolean could_petrify; boolean could_petrify;
if (obj != uball) { /* mon doesn't pick up ball */ if (obj != uball) { /* mon doesn't pick up ball */
could_petrify = obj->otyp == CORPSE && could_petrify = obj->otyp == CORPSE &&
touch_petrifies(&mons[obj->corpsenm]); touch_petrifies(&mons[obj->corpsenm]);
(void) mpickobj(u.ustuck,obj); (void) mpickobj(u.ustuck,obj);
if (could_petrify && is_animal(u.ustuck->data)) { if (could_petrify && is_animal(u.ustuck->data)) {
minstapetrify(u.ustuck, TRUE); minstapetrify(u.ustuck, TRUE);
/* Don't leave a cockatrice corpse available in a statue */ /* Don't leave a cockatrice corpse available in a statue */
if (!u.uswallow) delobj(obj); if (!u.uswallow) delobj(obj);
}
} }
}
} else { } else {
place_object(obj, u.ux, u.uy); place_object(obj, u.ux, u.uy);
if (obj == uball) if (obj == uball)
drop_ball(u.ux,u.uy); drop_ball(u.ux,u.uy);
else else
sellobj(obj, u.ux, u.uy); sellobj(obj, u.ux, u.uy);
stackobj(obj); stackobj(obj);
if(Blind && Levitation) if(Blind && Levitation)
map_object(obj, 0); map_object(obj, 0);
newsym(u.ux,u.uy); /* remap location under self */ newsym(u.ux,u.uy); /* remap location under self */
} }
} }
@@ -597,7 +602,10 @@ int retry;
{ {
int n, i, n_dropped = 0; int n, i, n_dropped = 0;
long cnt; 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; menu_item *pick_list;
boolean all_categories = TRUE; boolean all_categories = TRUE;
boolean drop_everything = FALSE; boolean drop_everything = FALSE;
@@ -657,11 +665,7 @@ int retry;
cnt = pick_list[i].count; cnt = pick_list[i].count;
if (cnt < otmp->quan && !welded(otmp) && if (cnt < otmp->quan && !welded(otmp) &&
(!otmp->cursed || otmp->otyp != LOADSTONE)) { (!otmp->cursed || otmp->otyp != LOADSTONE)) {
otmp2 = splitobj(otmp, cnt); otmp = 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);
} }
n_dropped += drop(otmp); n_dropped += drop(otmp);
} }
+10 -1
View File
@@ -431,6 +431,11 @@ xchar x, y;
result = "cracking"; result = "cracking";
} }
if (result) { 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); You_hear("a muffled %s.",result);
if(costly) loss += stolen_value(otmp, x, y, if(costly) loss += stolen_value(otmp, x, y,
(boolean)shkp->mpeaceful, TRUE); (boolean)shkp->mpeaceful, TRUE);
@@ -512,7 +517,7 @@ xchar x, y;
return(!rn2(3) || martial()); 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) if (slide && !Blind)
pline("Whee! %s slide%s across the %s.", Doname2(kickobj), pline("Whee! %s slide%s across the %s.", Doname2(kickobj),
@@ -1267,6 +1272,10 @@ boolean shop_floor_obj;
otmp->no_charge = 0; 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); add_to_migration(otmp);
otmp->ox = cc.x; otmp->ox = cc.x;
otmp->oy = cc.y; otmp->oy = cc.y;
+16 -6
View File
@@ -52,7 +52,12 @@ int shotlimit;
if(obj->oclass == GOLD_CLASS) return(throw_gold(obj)); if(obj->oclass == GOLD_CLASS) return(throw_gold(obj));
#else #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 Throwing money is usually for getting rid of it when
@@ -157,8 +162,7 @@ int shotlimit;
twoweap = u.twoweap; twoweap = u.twoweap;
/* split this object off from its slot if necessary */ /* split this object off from its slot if necessary */
if (obj->quan > 1L) { if (obj->quan > 1L) {
otmp = splitobj(obj, obj->quan - 1L); otmp = splitobj(obj, 1L);
otmp->owornmask = 0L;
} else { } else {
otmp = obj; otmp = obj;
if (otmp->owornmask && otmp != uball) 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 (is_ammo(obj)) {
if (ammo_and_launcher(obj, uwep)) if (ammo_and_launcher(obj, uwep))
range++; range++;
else else if (obj->oclass != GEM_CLASS)
range /= 2; range /= 2;
} }
@@ -1482,9 +1486,10 @@ breaktest(obj)
struct obj *obj; struct obj *obj;
{ {
if (obj_resists(obj, 1, 99)) return 0; 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) { switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) {
case MIRROR:
case CRYSTAL_BALL:
#ifdef TOURIST #ifdef TOURIST
case EXPENSIVE_CAMERA: case EXPENSIVE_CAMERA:
#endif #endif
@@ -1508,6 +1513,11 @@ boolean in_view;
to_pieces = ""; to_pieces = "";
switch (obj->oclass == POTION_CLASS ? POT_WATER : obj->otyp) { 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 MIRROR:
case CRYSTAL_BALL: case CRYSTAL_BALL:
#ifdef TOURIST #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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* 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 int FDECL(rottenfood, (struct obj *));
STATIC_DCL void NDECL(eatspecial); STATIC_DCL void NDECL(eatspecial);
STATIC_DCL void FDECL(eataccessory, (struct obj *)); 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]; char msgbuf[BUFSZ];
@@ -303,9 +303,9 @@ register struct obj *otmp;
{ {
if (otmp->quan > 1L) { if (otmp->quan > 1L) {
if(!carried(otmp)) if(!carried(otmp))
(void) splitobj(otmp, 1L); (void) splitobj(otmp, otmp->quan - 1L);
else else
otmp = splitobj(otmp, otmp->quan - 1L); otmp = splitobj(otmp, 1L);
#ifdef DEBUG #ifdef DEBUG
debugpline("split object,"); debugpline("split object,");
#endif #endif
@@ -1097,11 +1097,7 @@ no_opener:
pline_The("tin slips from your %s.", pline_The("tin slips from your %s.",
makeplural(body_part(FINGER))); makeplural(body_part(FINGER)));
if(otmp->quan > 1L) { if(otmp->quan > 1L) {
register struct obj *obj; otmp = splitobj(otmp, 1L);
obj = splitobj(otmp, 1L);
if (otmp == uwep) setuwep(obj);
if (otmp == uswapwep) setuswapwep(obj);
if (otmp == uquiver) setuqwep(obj);
} }
if (carried(otmp)) dropx(otmp); if (carried(otmp)) dropx(otmp);
else stackobj(otmp); else stackobj(otmp);
@@ -1233,7 +1229,7 @@ eatcorpse(otmp) /* called when a corpse is selected as food */
(void)touchfood(otmp); (void)touchfood(otmp);
retcode = 1; retcode = 1;
} else } else
otmp->oeaten >>= 2; consume_oeaten(otmp, 2); /* oeaten >>= 2 */
} else { } else {
pline("%s%s %s!", pline("%s%s %s!",
!uniq ? "This " : !type_is_pname(&mons[mnum]) ? "The " : "", !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) { u.umonnum == PM_RUST_MONSTER && otmp->oerodeproof) {
otmp->rknown = TRUE; otmp->rknown = TRUE;
if (otmp->quan > 1L) { if (otmp->quan > 1L) {
if(!carried(otmp)) if(!carried(otmp))
(void) splitobj(otmp, 1L); (void) splitobj(otmp, otmp->quan - 1L);
else else
otmp = splitobj(otmp, otmp->quan - 1L); otmp = splitobj(otmp, 1L);
} }
pline("Ulch - That %s was rustproofed!", xname(otmp)); pline("Ulch - That %s was rustproofed!", xname(otmp));
/* The regurgitated object's rustproofing is gone now */ /* The regurgitated object's rustproofing is gone now */
@@ -1926,7 +1922,7 @@ doeat() /* generic "eat" command funtion (see cmd.c) */
otmp->orotten = TRUE; otmp->orotten = TRUE;
dont_start = TRUE; dont_start = TRUE;
} }
otmp->oeaten >>= 1; consume_oeaten(otmp, 1); /* oeaten >>= 1 */
} else fprefx(otmp); } else fprefx(otmp);
} }
@@ -1979,10 +1975,10 @@ bite()
force_save_hs = TRUE; force_save_hs = TRUE;
if(victual.nmod < 0) { if(victual.nmod < 0) {
lesshungry(-victual.nmod); lesshungry(-victual.nmod);
victual.piece->oeaten -= -victual.nmod; consume_oeaten(victual.piece, victual.nmod); /* -= -nmod */
} else if(victual.nmod > 0 && (victual.usedtime % victual.nmod)) { } else if(victual.nmod > 0 && (victual.usedtime % victual.nmod)) {
lesshungry(1); lesshungry(1);
victual.piece->oeaten--; consume_oeaten(victual.piece, -1); /* -= 1 */
} }
force_save_hs = FALSE; force_save_hs = FALSE;
recalc_wt(); 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 we can't touch floor objects then use invent food only */
if (!can_reach_floor() || if (!can_reach_floor() ||
#ifdef STEED #ifdef STEED
u.usteed || /* can't eat off floor while riding */ (feeding && u.usteed) || /* can't eat off floor while riding */
#endif #endif
((is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) && ((is_pool(u.ux, u.uy) || is_lava(u.ux, u.uy)) &&
(Wwalking || is_clinger(youmonst.data) || (Wwalking || is_clinger(youmonst.data) ||
@@ -2382,6 +2378,74 @@ register struct obj *obj;
return (base < 1) ? 1 : base; 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 */ #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*/ /*eat.c*/
+1 -1
View File
@@ -662,7 +662,7 @@ die:
#ifndef GOLDOBJ #ifndef GOLDOBJ
u.ugold = umoney; u.ugold = umoney;
#else #else
/* FIXME */ done_money = umoney;
#endif #endif
/* clean up unneeded windows */ /* clean up unneeded windows */
+9 -11
View File
@@ -416,20 +416,18 @@ struct obj *obj; /* only scatter this obj */
qtmp = otmp->quan - 1; qtmp = otmp->quan - 1;
if (qtmp > LARGEST_INT) qtmp = LARGEST_INT; if (qtmp > LARGEST_INT) qtmp = LARGEST_INT;
qtmp = (long)rnd((int)qtmp); qtmp = (long)rnd((int)qtmp);
(void) splitobj(otmp, qtmp); otmp = splitobj(otmp, qtmp);
if (qtmp < otmp->quan) if (rn2(qtmp))
split_up = TRUE; split_up = TRUE;
else else
split_up = FALSE; split_up = FALSE;
} } else
split_up = FALSE;
if (individual_object) { if (individual_object) {
if (split_up) { if (split_up) {
if (otmp->where == OBJ_FLOOR) obj = otmp;
obj = otmp->nexthere;
else
obj = otmp->nobj;
} else } else
obj = (struct obj *)0; obj = (struct obj *)0;
} }
obj_extract_self(otmp); obj_extract_self(otmp);
used_up = FALSE; used_up = FALSE;
+2 -2
View File
@@ -730,7 +730,7 @@ boolean uncomp;
* end up being displayed after the error message. * end up being displayed after the error message.
*/ */
if (istty) if (istty)
fflush(stdout); wait_synch();
# endif # endif
if (f == 0) { /* child */ if (f == 0) { /* child */
# ifdef TTY_GRAPHICS # ifdef TTY_GRAPHICS
@@ -740,7 +740,7 @@ boolean uncomp;
* invisible if there are no error messages. * invisible if there are no error messages.
*/ */
if (istty) if (istty)
raw_printf(""); raw_print("");
# endif # endif
/* run compressor without privileges, in case other programs /* run compressor without privileges, in case other programs
* have surprises along the line of gzip once taking filenames * have surprises along the line of gzip once taking filenames
+5 -1
View File
@@ -160,7 +160,11 @@ moverock()
continue; continue;
case HOLE: case HOLE:
case TRAPDOOR: 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)), The(xname(otmp)),
(ttmp->ttyp == TRAPDOOR) ? "triggers" : "falls into", (ttmp->ttyp == TRAPDOOR) ? "triggers" : "falls into",
(ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole", (ttmp->ttyp == TRAPDOOR) ? "trap door" : "hole",
+44 -48
View File
@@ -51,8 +51,10 @@ register struct obj *otmp;
#ifdef GOLDOBJ #ifdef GOLDOBJ
/* There is only one of these in inventory... */ /* There is only one of these in inventory... */
if (otmp->oclass == GOLD_CLASS) otmp->invlet = GOLD_SYM; if (otmp->oclass == GOLD_CLASS) {
return; otmp->invlet = GOLD_SYM;
return;
}
#endif #endif
for(i = 0; i < 52; i++) inuse[i] = FALSE; 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); if (drop_fmt) pline(drop_fmt, drop_arg);
/* undo any merge which took place */ /* undo any merge which took place */
if (obj->quan > oquan) { if (obj->quan > oquan) {
struct obj *otmp = splitobj(obj, oquan); obj = splitobj(obj, oquan);
/* might have merged with weapon */
if (obj->owornmask)
setworn(otmp, obj->owornmask);
} }
dropx(obj); dropx(obj);
} else { } else {
@@ -914,23 +913,26 @@ register const char *let,*word;
pline_The("LRS would be very interested to know you have that much."); pline_The("LRS would be very interested to know you have that much.");
return(struct obj *)0; return(struct obj *)0;
} }
#ifndef GOLDOBJ
#ifndef GOLDOBJ
if(!(allowcnt == 2 && cnt < u.ugold)) if(!(allowcnt == 2 && cnt < u.ugold))
cnt = u.ugold; cnt = u.ugold;
return(mkgoldobj(cnt)); return(mkgoldobj(cnt));
#endif #endif
} }
if(allowcnt == 2 && !strcmp(word,"throw")) { if(allowcnt == 2 && !strcmp(word,"throw")) {
/* permit counts for throwing gold, but don't accept /* permit counts for throwing gold, but don't accept
* counts for other things since the throw code will * counts for other things since the throw code will
* split off a single item anyway */ * split off a single item anyway */
#ifdef GOLDOBJ
if (ilet != def_oc_syms[GOLD_CLASS])
#endif
allowcnt = 1; allowcnt = 1;
if(cnt == 0 && prezero) return((struct obj *)0); if(cnt == 0 && prezero) return((struct obj *)0);
if(cnt > 1) { if(cnt > 1) {
You("can only throw one item at a time."); You("can only throw one item at a time.");
continue; continue;
} }
} }
#ifdef GOLDOBJ #ifdef GOLDOBJ
flags.botl = 1; /* May have changed the amount of money */ flags.botl = 1; /* May have changed the amount of money */
@@ -975,20 +977,17 @@ register const char *let,*word;
return((struct obj *)0); return((struct obj *)0);
} }
if(allowcnt == 2) { /* cnt given */ if(allowcnt == 2) { /* cnt given */
if(cnt == 0) return (struct obj *)0; if(cnt == 0) return (struct obj *)0;
if(cnt != otmp->quan) { if(cnt != otmp->quan) {
register struct obj *obj = splitobj(otmp, cnt); otmp = splitobj(otmp, cnt);
/* Very ugly kludge necessary to prevent someone from trying /* Very ugly kludge necessary to prevent someone from trying
* to drop one of several loadstones and having the loadstone * to drop one of several loadstones and having the loadstone
* now be separate. * now be separate.
*/ */
if (!strcmp(word, "drop") && if (!strcmp(word, "drop") &&
obj->otyp == LOADSTONE && obj->cursed) otmp->otyp == LOADSTONE && otmp->cursed)
otmp->corpsenm = obj->invlet; otmp->corpsenm = otmp->invlet;
if(otmp == uwep) setuwep(obj); }
else if (otmp == uquiver) setuqwep(obj);
if (otmp == uswapwep) setuswapwep(obj);
}
} }
return(otmp); return(otmp);
} }
@@ -1230,7 +1229,7 @@ nextclass:
if (ckfn && !(*ckfn)(otmp)) continue; if (ckfn && !(*ckfn)(otmp)) continue;
if (!allflag) { if (!allflag) {
Strcpy(qbuf, !ininv ? doname(otmp) : Strcpy(qbuf, !ininv ? doname(otmp) :
xprname(otmp, (char *)0, ilet, !nodot, 0L)); xprname(otmp, (char *)0, ilet, !nodot, 0L, 0L));
Strcat(qbuf, "?"); Strcat(qbuf, "?");
sym = (takeoff || ident || otmp->quan < 2L) ? sym = (takeoff || ident || otmp->quan < 2L) ?
nyaq(qbuf) : nyNaq(qbuf); nyaq(qbuf) : nyNaq(qbuf);
@@ -1250,13 +1249,7 @@ nextclass:
sym = 'y'; sym = 'y';
if (yn_number < otmp->quan && !welded(otmp) && if (yn_number < otmp->quan && !welded(otmp) &&
(!otmp->cursed || otmp->otyp != LOADSTONE)) { (!otmp->cursed || otmp->otyp != LOADSTONE)) {
struct obj *otmpx = splitobj(otmp, yn_number); otmp = 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);
} }
} }
} }
@@ -1411,32 +1404,33 @@ const char *prefix;
register struct obj *obj; register struct obj *obj;
long quan; long quan;
{ {
long savequan = obj->quan;
if (quan) obj->quan = quan;
if (!prefix) prefix = ""; if (!prefix) prefix = "";
pline("%s%s%s", pline("%s%s%s",
prefix, *prefix ? " " : "", prefix, *prefix ? " " : "",
xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L)); xprname(obj, (char *)0, obj_to_let(obj), TRUE, 0L, quan));
if (quan) obj->quan = savequan;
} }
#endif /* OVL2 */ #endif /* OVL2 */
#ifdef OVL1 #ifdef OVL1
char * char *
xprname(obj, txt, let, dot, cost) xprname(obj, txt, let, dot, cost, quan)
struct obj *obj; struct obj *obj;
const char *txt; /* text to print instead of obj */ const char *txt; /* text to print instead of obj */
char let; /* inventory letter */ char let; /* inventory letter */
boolean dot; /* append period; (dot && cost => Iu) */ boolean dot; /* append period; (dot && cost => Iu) */
long cost; /* cost (for inventory of unpaid or expended items) */ 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]; */ #ifdef LINT /* handle static char li[BUFSZ]; */
char li[BUFSZ]; char li[BUFSZ];
#else #else
static char li[BUFSZ]; static char li[BUFSZ];
#endif #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: * If let is:
* * Then obj == null and we are printing a total amount. * * 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), (use_invlet ? obj->invlet : let),
(txt ? txt : doname(obj)), (dot ? "." : "")); (txt ? txt : doname(obj)), (dot ? "." : ""));
} }
if (quan) obj->quan = savequan;
return li; return li;
} }
@@ -1566,8 +1562,8 @@ boolean want_reply;
for (otmp = invent; otmp; otmp = otmp->nobj) { for (otmp = invent; otmp; otmp = otmp->nobj) {
if (otmp->invlet == lets[0]) { if (otmp->invlet == lets[0]) {
ret = message_menu(lets[0], ret = message_menu(lets[0],
want_reply ? PICK_ONE : PICK_NONE, want_reply ? PICK_ONE : PICK_NONE,
xprname(otmp, (char *)0, lets[0], TRUE, 0L)); xprname(otmp, (char *)0, lets[0], TRUE, 0L, 0L));
break; break;
} }
} }
@@ -1658,7 +1654,7 @@ dounpaid()
pline("%s", xprname(otmp, distant_name(otmp, doname), pline("%s", xprname(otmp, distant_name(otmp, doname),
marker ? otmp->invlet : CONTAINED_SYM, marker ? otmp->invlet : CONTAINED_SYM,
TRUE, unpaid_cost(otmp))); TRUE, unpaid_cost(otmp), 0L));
return; return;
} }
@@ -1683,7 +1679,7 @@ dounpaid()
save_unpaid = otmp->unpaid; save_unpaid = otmp->unpaid;
otmp->unpaid = 0; otmp->unpaid = 0;
putstr(win, 0, xprname(otmp, distant_name(otmp, doname), putstr(win, 0, xprname(otmp, distant_name(otmp, doname),
ilet, TRUE, cost)); ilet, TRUE, cost, 0L));
otmp->unpaid = save_unpaid; otmp->unpaid = save_unpaid;
num_so_far++; num_so_far++;
} }
@@ -1709,7 +1705,7 @@ dounpaid()
marker->unpaid = 0; /* suppress "(unpaid)" suffix */ marker->unpaid = 0; /* suppress "(unpaid)" suffix */
putstr(win, 0, putstr(win, 0,
xprname(marker, distant_name(marker, doname), xprname(marker, distant_name(marker, doname),
CONTAINED_SYM, TRUE, cost)); CONTAINED_SYM, TRUE, cost, 0L));
marker->unpaid = save_unpaid; marker->unpaid = save_unpaid;
} }
} }
@@ -1717,7 +1713,7 @@ dounpaid()
} }
putstr(win, 0, ""); 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); display_nhwindow(win, FALSE);
destroy_nhwindow(win); destroy_nhwindow(win);
} }
@@ -2291,7 +2287,7 @@ long numused;
/* burn_floor_paper() keeps an object pointer that it tries to /* burn_floor_paper() keeps an object pointer that it tries to
* useupf() multiple times, so obj must survive if plural */ * useupf() multiple times, so obj must survive if plural */
if (obj->quan > numused) if (obj->quan > numused)
otmp = splitobj(obj, obj->quan - numused); otmp = splitobj(obj, numused);
else else
otmp = obj; otmp = obj;
if(costly_spot(otmp->ox, otmp->oy)) { if(costly_spot(otmp->ox, otmp->oy)) {
+3 -2
View File
@@ -751,6 +751,7 @@ register int mmflags;
boolean anymon = (!ptr); boolean anymon = (!ptr);
boolean byyou = (x == u.ux && y == u.uy); boolean byyou = (x == u.ux && y == u.uy);
boolean allow_minvent = ((mmflags & NO_MINVENT) == 0); boolean allow_minvent = ((mmflags & NO_MINVENT) == 0);
boolean countbirth = ((mmflags & MM_NOCOUNTBIRTH) == 0);
uchar lim; uchar lim;
/* if caller wants random location, do it here */ /* 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 * the caller manually decrement mvitals if the monster is created
* under circumstances where one would not logically expect the * under circumstances where one would not logically expect the
* creation to reduce the supply of wild monsters. Monster cloning * 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. * 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); lim = mbirth_limit(mndx);
if ((int) mvitals[mndx].born >= lim && !(mons[mndx].geno & G_NOGEN) && if ((int) mvitals[mndx].born >= lim && !(mons[mndx].geno & G_NOGEN) &&
!(mvitals[mndx].mvflags & G_EXTINCT)) { !(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 * Split obj so that it gets size gets reduced by num. The quantity num is
* structure delivered by this call. The object is positioned just * put in the object structure delivered by this call. The returned object
* following the original in the nobj chain (and nexthere chain when on * has its wornmask cleared and is positioned just following the original
* the floor). * in the nobj chain (and nexthere chain when on the floor).
*/ */
struct obj * struct obj *
splitobj(obj, num) splitobj(obj, num)
@@ -229,7 +229,7 @@ long num;
{ {
struct obj *otmp; 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 */ panic("splitobj"); /* can't split containers */
otmp = newobj(obj->oxlth + obj->onamelth); otmp = newobj(obj->oxlth + obj->onamelth);
*otmp = *obj; /* copies whole structure */ *otmp = *obj; /* copies whole structure */
@@ -237,9 +237,10 @@ long num;
if (!otmp->o_id) otmp->o_id = flags.ident++; /* ident overflowed */ if (!otmp->o_id) otmp->o_id = flags.ident++; /* ident overflowed */
otmp->timed = 0; /* not timed, yet */ otmp->timed = 0; /* not timed, yet */
otmp->lamplit = 0; /* ditto */ otmp->lamplit = 0; /* ditto */
obj->quan = num; otmp->owornmask = 0L; /* new object isn't worn */
obj->quan -= num;
obj->owt = weight(obj); obj->owt = weight(obj);
otmp->quan -= num; otmp->quan = num;
otmp->owt = weight(otmp); /* -= obj->owt ? */ otmp->owt = weight(otmp); /* -= obj->owt ? */
obj->nobj = otmp; obj->nobj = otmp;
/* Only set nexthere when on the floor, nexthere is also used */ /* 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; register int tmp=0;
int inrange, nearby, scared; int inrange, nearby, scared;
#ifdef GOLDOBJ #ifdef GOLDOBJ
struct obj *ygold, *lepgold; struct obj *ygold = 0, *lepgold = 0;
#endif #endif
/* Pre-movement adjustments */ /* Pre-movement adjustments */
@@ -474,8 +474,8 @@ toofar:
(mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) || (mdat->mlet == S_LEPRECHAUN && !u.ugold && (mtmp->mgold || rn2(2))) ||
#else #else
if (mdat->mlet == S_LEPRECHAUN) { if (mdat->mlet == S_LEPRECHAUN) {
ygold = findgold(invent); ygold = findgold(invent);
lepgold = findgold(mtmp->minvent); lepgold = findgold(mtmp->minvent);
} }
if(!nearby || mtmp->mflee || scared || if(!nearby || mtmp->mflee || scared ||
+3 -3
View File
@@ -1987,7 +1987,7 @@ struct permonst _mons2[] = {
* Vampires * Vampires
*/ */
MON("vampire", S_VAMPIRE, 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), A(ATTK(AT_CLAW, AD_PHYS, 1, 6), ATTK(AT_BITE, AD_DRLI, 1, 6),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0, 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, M2_UNDEAD|M2_STALK|M2_HOSTILE|M2_STRONG|M2_NASTY, M3_INFRAVISIBLE,
CLR_RED), CLR_RED),
MON("vampire lord", S_VAMPIRE, 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), A(ATTK(AT_CLAW, AD_PHYS, 1, 8), ATTK(AT_BITE, AD_DRLI, 1, 8),
NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK), NO_ATTK, NO_ATTK, NO_ATTK, NO_ATTK),
SIZ(WT_HUMAN, 400, 0, MS_VAMPIRE, MZ_HUMAN), MR_SLEEP|MR_POISON, 0, 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), M3_INFRAVISIBLE, CLR_BLUE),
#if 0 /* DEFERRED */ #if 0 /* DEFERRED */
MON("vampire mage", S_VAMPIRE, 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), 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), 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, 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; singleobj = obj;
obj = (struct obj *) 0; obj = (struct obj *) 0;
} else { } else {
singleobj = splitobj(obj, obj->quan - 1L); singleobj = splitobj(obj, 1L);
obj_extract_self(singleobj); obj_extract_self(singleobj);
} }
@@ -557,6 +557,7 @@ struct monst *mtmp;
case PM_ROGUE: case PM_ROGUE:
if (skill == P_DAGGER) multishot++; if (skill == P_DAGGER) multishot++;
break; break;
case PM_NINJA:
case PM_SAMURAI: case PM_SAMURAI:
if (otmp->otyp == YA && mwep && if (otmp->otyp == YA && mwep &&
mwep->otyp == YUMI) multishot++; 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 #undef WAND
/* coins ... - so far, gold is all there is */ /* 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, \ 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 ) GOLD_CLASS, prob, 0, 1, worth, 0, 0, 0, 0, 0, HI_GOLD )
COIN("gold piece", 1000, GOLD), COIN("gold piece", 1000, GOLD,1),
#undef COIN #undef COIN
/* gems ... - includes stones and rocks but not boulders */ /* 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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* NetHack may be freely redistributed. See license for details. */
@@ -2430,17 +2430,16 @@ typfnd:
makeplural(body_part(HAND))); 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 (halfeaten && otmp->oclass == FOOD_CLASS) {
if (otmp->otyp == CORPSE) if (otmp->otyp == CORPSE)
otmp->oeaten = mons[otmp->corpsenm].cnutrit; otmp->oeaten = mons[otmp->corpsenm].cnutrit;
else otmp->oeaten = objects[otmp->otyp].oc_nutrition; else otmp->oeaten = objects[otmp->otyp].oc_nutrition;
otmp->owt /= 2; /* (do this adjustment before setting up object's weight) */
otmp->oeaten /= 2; consume_oeaten(otmp, 1);
if (!otmp->owt) otmp->owt = 1;
if (!otmp->oeaten) otmp->oeaten = 1;
} }
otmp->owt = weight(otmp);
if (very && otmp->otyp == HEAVY_IRON_BALL) otmp->owt += 160;
return(otmp); return(otmp);
} }
+5
View File
@@ -115,6 +115,11 @@ static struct Bool_Opt
#else #else
{"mail", (boolean *)0, TRUE}, {"mail", (boolean *)0, TRUE},
#endif #endif
#ifdef TTY_GRAPHICS
{"msg_window", &iflags.prevmsg_window, FALSE},
#else
{"msg_window", (boolean *)0, FALSE},
#endif
#ifdef NEWS #ifdef NEWS
{"news", &iflags.news, TRUE}, {"news", &iflags.news, TRUE},
#else #else
+19 -16
View File
@@ -1081,11 +1081,10 @@ long count;
boolean telekinesis; /* not picking it up directly by hand */ boolean telekinesis; /* not picking it up directly by hand */
{ {
int res, nearload; int res, nearload;
#ifdef GOLDOBJ #ifndef GOLDOBJ
long umoney = money_cnt(invent);
#endif
const char *where = (obj->ox == u.ux && obj->oy == u.uy) ? const char *where = (obj->ox == u.ux && obj->oy == u.uy) ?
"here" : "there"; "here" : "there";
#endif
if (obj->quan < count) { if (obj->quan < count) {
impossible("pickup_object: count %ld > quan %ld?", 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; if (obj->oclass == GOLD_CLASS) flags.botl = 1;
#endif #endif
if (obj->quan != count && obj->otyp != LOADSTONE) if (obj->quan != count && obj->otyp != LOADSTONE)
(void) splitobj(obj, count); obj = splitobj(obj, count);
obj = pick_obj(obj); obj = pick_obj(obj);
if (uwep && uwep == obj) mrg_to_wielded = TRUE; if (uwep && uwep == obj) mrg_to_wielded = TRUE;
nearload = near_capacity(); 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; mrg_to_wielded = FALSE;
return 1; return 1;
} }
@@ -1406,12 +1406,15 @@ lootcont:
struct obj *goldob = mkgoldobj(contribution); struct obj *goldob = mkgoldobj(contribution);
#else #else
struct obj *goldob; struct obj *goldob;
/* Find a money object to mess with */ /* Find a money object to mess with */
for (goldob = invent; goldob; goldob = goldob->nobj) ; for (goldob = invent; goldob; goldob = goldob->nobj) {
if (goldob->oclass == GOLD_CLASS) break;
}
if (goldob){ if (goldob){
long contribution = rnd((int)min(LARGEST_INT, goldob->quan)); long contribution = rnd((int)min(LARGEST_INT, goldob->quan));
if (contribution < goldob->quan) (void)splitobj(goldob, contribution); if (contribution < goldob->quan)
freeinv(goldob); goldob = splitobj(goldob, contribution);
freeinv(goldob);
#endif #endif
if (IS_THRONE(levl[u.ux][u.uy].typ)){ if (IS_THRONE(levl[u.ux][u.uy].typ)){
struct obj *coffers; struct obj *coffers;
@@ -1515,11 +1518,12 @@ struct monst *mtmp;
int *passed_info; int *passed_info;
boolean *prev_loot; boolean *prev_loot;
{ {
struct obj *otmp;
int c = -1; int c = -1;
int timepassed = 0; int timepassed = 0;
char qbuf[QBUFSZ];
#ifdef STEED #ifdef STEED
struct obj *otmp;
char qbuf[QBUFSZ];
/* 3.3.1 introduced the ability to remove saddle from a steed */ /* 3.3.1 introduced the ability to remove saddle from a steed */
/* *passed_info is set to TRUE if a loot query was given. */ /* *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. */ /* *prev_loot is set to TRUE if something was actually acquired in here. */
@@ -1789,7 +1793,7 @@ register struct obj *obj;
return res; return res;
if (obj->quan != count && obj->otyp != LOADSTONE) if (obj->quan != count && obj->otyp != LOADSTONE)
(void) splitobj(obj, count); obj = splitobj(obj, count);
/* Remove the object from the list. */ /* Remove the object from the list. */
obj_extract_self(obj); obj_extract_self(obj);
@@ -1822,7 +1826,9 @@ register struct obj *obj;
otmp, count); otmp, count);
if (is_gold) { if (is_gold) {
#ifndef GOLDOBJ
dealloc_obj(obj); dealloc_obj(obj);
#endif
bot(); /* update character's gold piece count immediately */ bot(); /* update character's gold piece count immediately */
} }
return 1; return 1;
@@ -2109,11 +2115,8 @@ boolean put_in;
otmp = pick_list[i].item.a_obj; otmp = pick_list[i].item.a_obj;
count = pick_list[i].count; count = pick_list[i].count;
if (count > 0 && count < otmp->quan) { if (count > 0 && count < otmp->quan) {
otmp2 = splitobj(otmp, count); otmp = splitobj(otmp, count);
/* special split case also handled by askchain() */ /* 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); res = put_in ? in_container(otmp) : out_container(otmp);
if (res < 0) if (res < 0)
+1 -1
View File
@@ -1817,7 +1817,7 @@ dodip()
/* with multiple merged potions, split off one and /* with multiple merged potions, split off one and
just clear it */ just clear it */
if (potion->quan > 1L) { if (potion->quan > 1L) {
singlepotion = splitobj(potion, potion->quan - 1L); singlepotion = splitobj(potion, 1L);
} else singlepotion = potion; } else singlepotion = potion;
if(singlepotion->unpaid && costly_spot(u.ux, u.uy)) { if(singlepotion->unpaid && costly_spot(u.ux, u.uy)) {
+1 -4
View File
@@ -111,10 +111,7 @@ int how;
#ifndef GOLDOBJ #ifndef GOLDOBJ
Sprintf(buf, "%ld Au", u.ugold); Sprintf(buf, "%ld Au", u.ugold);
#else #else
/* FIXME: this neglects gold in containers (which will be gone by Sprintf(buf, "%ld Au", done_money);
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));
#endif #endif
buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */ buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */
center(GOLD_LINE, buf); center(GOLD_LINE, buf);
+7 -2
View File
@@ -146,11 +146,16 @@ int mechanism;
boolean reading = (mechanism == BY_COOKIE || boolean reading = (mechanism == BY_COOKIE ||
mechanism == BY_PAPER); 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) if (mechanism == BY_COOKIE)
pline(fortune_msg); pline(fortune_msg);
pline("What a pity that you cannot read it!"); pline("What a pity that you cannot read it!");
return; return;
}
} }
line = getrumor(truth, buf, reading ? FALSE : TRUE); line = getrumor(truth, buf, reading ? FALSE : TRUE);
if (!*line) if (!*line)
+5 -7
View File
@@ -103,7 +103,7 @@ long amount;
return 0; return 0;
} }
if (ygold->quan > amount) splitobj(ygold, amount); if (ygold->quan > amount) ygold = splitobj(ygold, amount);
freeinv(ygold); freeinv(ygold);
add_to_minv(mon, ygold); add_to_minv(mon, ygold);
flags.botl = 1; flags.botl = 1;
@@ -131,7 +131,7 @@ long amount;
return; return;
} }
if (mongold->quan > amount) splitobj(mongold, amount); if (mongold->quan > amount) mongold = splitobj(mongold, amount);
obj_extract_self(mongold); obj_extract_self(mongold);
if (!merge_choice(invent, mongold) && inv_cnt() >= 52) { 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); uquan = (bp->useup ? bp->bquan : bp->bquan - oquan);
thisused = bp->price * uquan; thisused = bp->price * uquan;
totused += thisused; totused += thisused;
obj->quan = uquan; /* cheat doname */
obj->unpaid = 0; /* ditto */ obj->unpaid = 0; /* ditto */
/* Why 'x'? To match `I x', more or less. */ /* Why 'x'? To match `I x', more or less. */
buf_p = xprname(obj, (char *)0, 'x', FALSE, thisused); buf_p = xprname(obj, (char *)0, 'x', FALSE, thisused, uquan);
obj->quan = oquan; /* restore value */
#ifdef __SASC #ifdef __SASC
/* SAS/C 6.2 can't cope for some reason */ /* SAS/C 6.2 can't cope for some reason */
sasc_bug(obj,save_unpaid); sasc_bug(obj,save_unpaid);
@@ -2768,10 +2766,10 @@ int mode; /* 0: deliver count 1: paged */
totused += eshkp->debit; totused += eshkp->debit;
buf_p = xprname((struct obj *)0, buf_p = xprname((struct obj *)0,
"usage charges and/or other fees", "usage charges and/or other fees",
GOLD_SYM, FALSE, eshkp->debit); GOLD_SYM, FALSE, eshkp->debit, 0L);
putstr(datawin, 0, buf_p); 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, "");
putstr(datawin, 0, buf_p); putstr(datawin, 0, buf_p);
display_nhwindow(datawin, FALSE); display_nhwindow(datawin, FALSE);
+2 -2
View File
@@ -850,8 +850,8 @@ struct mkroom *croom;
case M_AP_OBJECT: case M_AP_OBJECT:
for (i = 0; i < NUM_OBJECTS; i++) for (i = 0; i < NUM_OBJECTS; i++)
if (!strcmp(OBJ_NAME(objects[i]), if (OBJ_NAME(objects[i]) &&
m->appear_as.str)) !strcmp(OBJ_NAME(objects[i]),m->appear_as.str))
break; break;
if (i == NUM_OBJECTS) { if (i == NUM_OBJECTS) {
impossible( 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. */ /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */ /* 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; const int gold_price = objects[GOLD_PIECE].oc_cost;
tmp = (somegold(money_cnt(invent)) + gold_price - 1) / gold_price; tmp = (somegold(money_cnt(invent)) + gold_price - 1) / gold_price;
tmp = min(tmp, ygold->quan); tmp = min(tmp, ygold->quan);
if (tmp < ygold->quan) splitobj(ygold, tmp); if (tmp < ygold->quan) ygold = splitobj(ygold, tmp);
freeinv(ygold); freeinv(ygold);
add_to_minv(mtmp, ygold); add_to_minv(mtmp, ygold);
Your("purse feels lighter."); Your("purse feels lighter.");
@@ -229,6 +229,11 @@ char *objnambuf;
/* the following is true if successful on first of two attacks. */ /* the following is true if successful on first of two attacks. */
if(!monnear(mtmp, u.ux, u.uy)) return(0); 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)) { if (!invent || (inv_cnt() == 1 && uskin)) {
nothing_to_steal: nothing_to_steal:
/* Not even a thousand men in armor can strip a naked man. */ /* Not even a thousand men in armor can strip a naked man. */
+26 -2
View File
@@ -204,7 +204,19 @@ void
teleds(nux, nuy) teleds(nux, nuy)
register int 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.utrap = 0;
u.ustuck = 0; u.ustuck = 0;
u.ux0 = u.ux; u.ux0 = u.ux;
@@ -228,7 +240,19 @@ register int nux,nuy;
u.uswldtim = u.uswallow = 0; u.uswldtim = u.uswallow = 0;
docrt(); 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 */ initrack(); /* teleports mess up tracking monsters without this */
update_player_regions(); update_player_regions();
#ifdef STEED #ifdef STEED
+1 -1
View File
@@ -1160,7 +1160,7 @@ int style;
singleobj = otmp; singleobj = otmp;
otmp = (struct obj *) 0; otmp = (struct obj *) 0;
} else { } else {
singleobj = splitobj(otmp, otmp->quan - 1L); singleobj = splitobj(otmp, 1L);
obj_extract_self(singleobj); obj_extract_self(singleobj);
} }
newsym(x1,y1); newsym(x1,y1);
+1 -1
View File
@@ -634,7 +634,7 @@ int thrown;
} }
} else if(obj->oclass == POTION_CLASS) { } else if(obj->oclass == POTION_CLASS) {
if (obj->quan > 1L) if (obj->quan > 1L)
setworn(splitobj(obj, 1L), W_WEP); obj = splitobj(obj, 1L);
else else
setuwep((struct obj *)0); setuwep((struct obj *)0);
freeinv(obj); 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_lose_armor, (struct monst *,struct obj *));
STATIC_DCL void FDECL(m_dowear_type, (struct monst *,long,BOOLEAN_P)); 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 { const struct worn {
long w_mask; long w_mask;
@@ -114,16 +115,16 @@ register struct obj *obj;
if (!obj) return; if (!obj) return;
if (obj == uwep || obj == uswapwep) u.twoweap = 0; if (obj == uwep || obj == uswapwep) u.twoweap = 0;
for(wp = worn; wp->w_mask; wp++) for(wp = worn; wp->w_mask; wp++)
if(obj == *(wp->w_obj)) { if(obj == *(wp->w_obj)) {
*(wp->w_obj) = 0; *(wp->w_obj) = 0;
p = objects[obj->otyp].oc_oprop; p = objects[obj->otyp].oc_oprop;
u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask; u.uprops[p].extrinsic = u.uprops[p].extrinsic & ~wp->w_mask;
obj->owornmask &= ~wp->w_mask; obj->owornmask &= ~wp->w_mask;
if (obj->oartifact) if (obj->oartifact)
set_artifact_intrinsic(obj, 0, wp->w_mask); set_artifact_intrinsic(obj, 0, wp->w_mask);
if ((p = w_blocks(obj,wp->w_mask)) != 0) if ((p = w_blocks(obj,wp->w_mask)) != 0)
u.uprops[p].blocked &= ~wp->w_mask; u.uprops[p].blocked &= ~wp->w_mask;
} }
update_inventory(); update_inventory();
} }
@@ -404,7 +405,8 @@ boolean creation;
* it would forget spe and once again think the object is better * it would forget spe and once again think the object is better
* than what it already has. * 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; best = obj;
} }
outer_break: outer_break:
@@ -667,4 +669,16 @@ boolean polyspot;
return; 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*/ /*worn.c*/
+17 -9
View File
@@ -140,6 +140,7 @@ struct obj *otmp;
case SPE_SLOW_MONSTER: case SPE_SLOW_MONSTER:
if (!resist(mtmp, otmp->oclass, 0, NOTELL)) { if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
mon_adjust_speed(mtmp, -1); mon_adjust_speed(mtmp, -1);
m_dowear(mtmp, FALSE); /* might want speed boots */
if (u.uswallow && (mtmp == u.ustuck) && if (u.uswallow && (mtmp == u.ustuck) &&
is_whirly(mtmp->data)) { is_whirly(mtmp->data)) {
You("disrupt %s!", mon_nam(mtmp)); You("disrupt %s!", mon_nam(mtmp));
@@ -149,8 +150,10 @@ struct obj *otmp;
} }
break; break;
case WAN_SPEED_MONSTER: case WAN_SPEED_MONSTER:
if (!resist(mtmp, otmp->oclass, 0, NOTELL)) if (!resist(mtmp, otmp->oclass, 0, NOTELL)) {
mon_adjust_speed(mtmp, 1); mon_adjust_speed(mtmp, 1);
m_dowear(mtmp, FALSE); /* might want speed boots */
}
break; break;
case WAN_UNDEAD_TURNING: case WAN_UNDEAD_TURNING:
case SPE_TURN_UNDEAD: case SPE_TURN_UNDEAD:
@@ -450,7 +453,7 @@ coord *cc;
if (mtmp2->mhpmax <= 0 && !is_rider(mtmp2->data)) if (mtmp2->mhpmax <= 0 && !is_rider(mtmp2->data))
return (struct monst *)0; return (struct monst *)0;
mtmp = makemon(mtmp2->data, 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; if (!mtmp) return mtmp;
/* heal the monster */ /* heal the monster */
@@ -610,7 +613,7 @@ register struct obj *obj;
wary_dog(mtmp, TRUE); wary_dog(mtmp, TRUE);
} else } else
mtmp = makemon(&mons[montype], x, y, mtmp = makemon(&mons[montype], x, y,
NO_MINVENT|MM_NOWAIT); NO_MINVENT|MM_NOWAIT|MM_NOCOUNTBIRTH);
if (mtmp) { if (mtmp) {
if (obj->oxlth && (obj->oattached == OATTACHED_M_ID)) { if (obj->oxlth && (obj->oattached == OATTACHED_M_ID)) {
unsigned m_id; unsigned m_id;
@@ -666,7 +669,7 @@ register struct obj *obj;
x = obj->ox, y = obj->oy; x = obj->ox, y = obj->oy;
/* not useupf(), which charges */ /* not useupf(), which charges */
if (obj->quan > 1L) if (obj->quan > 1L)
(void) splitobj(obj, 1L); obj = splitobj(obj, 1L);
delobj(obj); delobj(obj);
newsym(x, y); newsym(x, y);
break; break;
@@ -1134,9 +1137,9 @@ struct obj *obj;
/* if quan > 1 then some will survive intact */ /* if quan > 1 then some will survive intact */
if (obj->quan > 1L) { if (obj->quan > 1L) {
if (obj->quan > LARGEST_INT) if (obj->quan > LARGEST_INT)
(void) splitobj(obj, (long)rnd(30000)); obj = splitobj(obj, (long)rnd(30000));
else else
(void) splitobj(obj, (long)rnd((int)obj->quan - 1)); obj = splitobj(obj, (long)rnd((int)obj->quan - 1));
} }
/* appropriately add damage to bill */ /* appropriately add damage to bill */
@@ -2504,10 +2507,13 @@ register const char *str;
register struct monst *mtmp; register struct monst *mtmp;
register const char *force; /* usually either "." or "!" */ register const char *force; /* usually either "." or "!" */
{ {
int pl = strcmp(str, makesingular(str));
if((!cansee(bhitpos.x,bhitpos.y) && !canspotmon(mtmp)) if((!cansee(bhitpos.x,bhitpos.y) && !canspotmon(mtmp))
|| !flags.verbose) || !flags.verbose)
pline("%s hits it.", The(str)); pline("%s %s it.", The(str), pl ? "hit" : "hits");
else pline("%s hits %s%s", The(str), mon_nam(mtmp), force); else pline("%s %s %s%s", The(str), pl ? "hit" : "hits",
mon_nam(mtmp), force);
} }
void void
@@ -2515,7 +2521,9 @@ miss(str,mtmp)
register const char *str; register const char *str;
register struct monst *mtmp; 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)) ((cansee(bhitpos.x,bhitpos.y) || canspotmon(mtmp))
&& flags.verbose) ? && flags.verbose) ?
mon_nam(mtmp) : "it"); mon_nam(mtmp) : "it");
+1 -1
View File
@@ -199,7 +199,7 @@ int how;
#ifndef GOLDOBJ #ifndef GOLDOBJ
u.ugold); u.ugold);
#else #else
money_cnt(invent)); done_money);
#endif #endif
buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */ buf[STONE_LINE_LEN] = 0; /* It could be a *lot* of gold :-) */
tomb_text(buf); tomb_text(buf);
+9 -1
View File
@@ -2441,7 +2441,11 @@ void NetHackQtStatusWindow::updateStats()
dlevel.setLabel(buf,(long)depth(&u.uz)); dlevel.setLabel(buf,(long)depth(&u.uz));
} }
gold.setLabel("Au:",(long)u.ugold); #ifndef GOLDOBJ
gold.setLabel("Au:", u.ugold);
#else
gold.setLabel("Au:", money_cnt(invent));
#endif
if (u.mtimedone) { if (u.mtimedone) {
// You're a monster! // You're a monster!
@@ -3166,7 +3170,11 @@ static char** rip_line=0;
Sprintf(rip_line[NAME_LINE], "%s", plname); Sprintf(rip_line[NAME_LINE], "%s", plname);
/* Put $ on stone */ /* Put $ on stone */
#ifndef GOLDOBJ
Sprintf(rip_line[GOLD_LINE], "%ld Au", u.ugold); Sprintf(rip_line[GOLD_LINE], "%ld Au", u.ugold);
#else
Sprintf(rip_line[GOLD_LINE], "%ld Au", done_money);
#endif
/* Put together death description */ /* Put together death description */
switch (killer_format) { switch (killer_format) {
+4 -4
View File
@@ -59,10 +59,10 @@ NetHack*message*translations: <KeyPress>: input()
! It is not guaranteed that the window manager will honor the icon selection. ! It is not guaranteed that the window manager will honor the icon selection.
!NetHack*icon: nh56 !NetHack*icon: nh56
! !
! If True, a popup for single character prompts such as y/n questions is _not_ ! If True, the default, a popup for single character prompts such as y/n
! used. ! questions is _not_ used.
!NetHack*slow: True NetHack*slow: True
!
! The number of lines the message window will show without scrolling. ! The number of lines the message window will show without scrolling.
!NetHack*message_lines: 12 !NetHack*message_lines: 12
! !
+1 -1
View File
@@ -902,7 +902,7 @@ static XtActionsRec actions[] = {
static XtResource resources[] = { static XtResource resources[] = {
{ "slow", "Slow", XtRBoolean, sizeof(Boolean), { "slow", "Slow", XtRBoolean, sizeof(Boolean),
XtOffset(AppResources *,slow), XtRString, "False" }, XtOffset(AppResources *,slow), XtRString, "True" },
{ "autofocus", "AutoFocus", XtRBoolean, sizeof(Boolean), { "autofocus", "AutoFocus", XtRBoolean, sizeof(Boolean),
XtOffset(AppResources *,autofocus), XtRString, "False" }, XtOffset(AppResources *,autofocus), XtRString, "False" },
{ "message_line", "Message_line", XtRBoolean, sizeof(Boolean), { "message_line", "Message_line", XtRBoolean, sizeof(Boolean),
+1 -1
View File
@@ -471,7 +471,7 @@ calculate_rip_text(int how)
#ifndef GOLDOBJ #ifndef GOLDOBJ
u.ugold); u.ugold);
#else #else
money_cnt(invent)); done_money);
#endif #endif
/* Put together death description */ /* Put together death description */
switch (killer_format) { switch (killer_format) {
+1 -1
View File
@@ -977,7 +977,7 @@ void gnome_outrip(winid wid, int how)
#ifndef GOLDOBJ #ifndef GOLDOBJ
u.ugold); u.ugold);
#else #else
money_cnt(invent)); done_money);
#endif #endif
Strcat(ripString, buf); Strcat(ripString, buf);
+16 -6
View File
@@ -72,12 +72,22 @@ getlin_hook_proc hook;
*bufp = 0; *bufp = 0;
} }
if(c == '\020') { /* ctrl-P */ if(c == '\020') { /* ctrl-P */
if(!doprev) if (iflags.prevmsg_window) {
(void) tty_doprev_message(); /* need two initially */ (void) tty_doprev_message();
(void) tty_doprev_message(); tty_clear_nhwindow(WIN_MESSAGE);
doprev = 1; cw->maxcol = cw->maxrow;
continue; addtopl(query);
} else if(doprev) { addtopl(" ");
*bufp = 0;
addtopl(obufp);
} else {
if (!doprev)
(void) tty_doprev_message();/* need two initially */
(void) tty_doprev_message();
doprev = 1;
continue;
}
} else if (doprev && !iflags.prevmsg_window) {
tty_clear_nhwindow(WIN_MESSAGE); tty_clear_nhwindow(WIN_MESSAGE);
cw->maxcol = cw->maxrow; cw->maxcol = cw->maxrow;
doprev = 0; doprev = 0;
+45 -18
View File
@@ -26,19 +26,37 @@ tty_doprev_message()
{ {
register struct WinDesc *cw = wins[WIN_MESSAGE]; register struct WinDesc *cw = wins[WIN_MESSAGE];
ttyDisplay->dismiss_more = C('p'); /* <ctrl/P> allowed at --More-- */ winid prevmsg_win;
do { int i;
morc = 0;
if (cw->maxcol == cw->maxrow) if (iflags.prevmsg_window) {
redotoplin(toplines); prevmsg_win = create_nhwindow(NHW_MENU);
else if (cw->data[cw->maxcol]) putstr(prevmsg_win, 0, "Message History");
redotoplin(cw->data[cw->maxcol]); putstr(prevmsg_win, 0, "");
cw->maxcol--; i = cw->maxcol;
if (cw->maxcol < 0) cw->maxcol = cw->rows-1; do {
if (!cw->data[cw->maxcol]) if(cw->data[i] && strcmp(cw->data[i], "") )
cw->maxcol = cw->maxrow; putstr(prevmsg_win, 0, cw->data[i]);
} while (morc == C('p')); i = (i + 1) % cw->rows;
ttyDisplay->dismiss_more = 0; } while (i != cw->maxcol);
putstr(prevmsg_win, 0, toplines);
display_nhwindow(prevmsg_win, TRUE);
destroy_nhwindow(prevmsg_win);
} else {
ttyDisplay->dismiss_more = C('p'); /* <ctrl/P> allowed at --More-- */
do {
morc = 0;
if (cw->maxcol == cw->maxrow)
redotoplin(toplines);
else if (cw->data[cw->maxcol])
redotoplin(cw->data[cw->maxcol]);
cw->maxcol--;
if (cw->maxcol < 0) cw->maxcol = cw->rows-1;
if (!cw->data[cw->maxcol])
cw->maxcol = cw->maxrow;
} while (morc == C('p'));
ttyDisplay->dismiss_more = 0;
}
return 0; return 0;
} }
@@ -147,7 +165,9 @@ update_topl(bp)
/* If there is room on the line, print message on same line */ /* If there is room on the line, print message on same line */
/* But messages like "You die..." deserve their own line */ /* But messages like "You die..." deserve their own line */
n0 = strlen(bp); n0 = strlen(bp);
if(ttyDisplay->toplin == 1 && cw->cury == 0 && if( (ttyDisplay->toplin == 1 ||
(cw->flags & WIN_STOP && iflags.prevmsg_window)) &&
cw->cury == 0 &&
n0 + (int)strlen(toplines) + 3 < CO-8 && /* room for --More-- */ n0 + (int)strlen(toplines) + 3 < CO-8 && /* room for --More-- */
(notdied = strncmp(bp, "You die", 7))) { (notdied = strncmp(bp, "You die", 7))) {
Strcat(toplines, " "); Strcat(toplines, " ");
@@ -156,7 +176,7 @@ update_topl(bp)
if(!(cw->flags & WIN_STOP)) if(!(cw->flags & WIN_STOP))
addtopl(bp); addtopl(bp);
return; return;
} else if(!(cw->flags & WIN_STOP)) { } else if (!(cw->flags & WIN_STOP && !iflags.prevmsg_window)) {
if(ttyDisplay->toplin == 1) more(); if(ttyDisplay->toplin == 1) more();
else if(cw->cury) { /* for when flags.toplin == 2 && cury > 1 */ else if(cw->cury) { /* for when flags.toplin == 2 && cury > 1 */
docorner(1, cw->cury+1); /* reset cury = 0 if redraw screen */ docorner(1, cw->cury+1); /* reset cury = 0 if redraw screen */
@@ -279,9 +299,16 @@ char def;
do { /* loop until we get valid input */ do { /* loop until we get valid input */
q = lowc(readchar()); q = lowc(readchar());
if (q == '\020') { /* ctrl-P */ if (q == '\020') { /* ctrl-P */
if(!doprev) (void) tty_doprev_message(); /* need two initially */ if (iflags.prevmsg_window) {
(void) tty_doprev_message(); (void) tty_doprev_message();
doprev = 1; tty_clear_nhwindow(WIN_MESSAGE);
cw->maxcol = cw->maxrow;
addtopl(prompt);
} else {
if(!doprev) (void) tty_doprev_message(); /* need two initially */
(void) tty_doprev_message();
doprev = 1;
}
q = '\0'; /* force another loop iteration */ q = '\0'; /* force another loop iteration */
continue; continue;
} else if (doprev) { } else if (doprev) {
+5 -2
View File
@@ -1732,7 +1732,9 @@ tty_putstr(window, attr, str)
return; return;
} }
if(str == (const char*)0 || (cw->flags & WIN_CANCELLED)) if(str == (const char*)0 ||
( (cw->flags & WIN_CANCELLED) &&
(cw->type != NHW_MESSAGE || !iflags.prevmsg_window) ))
return; return;
if(cw->type != NHW_MESSAGE) if(cw->type != NHW_MESSAGE)
str = compress_str(str); str = compress_str(str);
@@ -2215,7 +2217,8 @@ tty_wait_synch()
/* this can only happen if we were reading and got interrupted */ /* this can only happen if we were reading and got interrupted */
ttyDisplay->toplin = 3; ttyDisplay->toplin = 3;
/* do this twice; 1st time gets the Quit? message again */ /* do this twice; 1st time gets the Quit? message again */
(void) tty_doprev_message(); if (!iflags.prevmsg_window)
(void) tty_doprev_message();
(void) tty_doprev_message(); (void) tty_doprev_message();
ttyDisplay->intr++; ttyDisplay->intr++;
(void) fflush(stdout); (void) fflush(stdout);