Skip to content

Commit

Permalink
Confused #loot (trunk only)
Browse files Browse the repository at this point in the history
     Attempting to loot while suffering from confusion and not on top
of a container will drop gold if hero is carrying some, but it behaved
differently for GOLDOBJ config (gold dropped over a hole or down stairs
always stayed on current level) than for !GOLDOBJ (gold had a chance to
fall to lower level) when done at some location other than a throne.
This makes GOLDOBJ use dropx() instead of dropy(), same as !GOLDOBJ.

     And with access to a throne it can be used to repeatedly summon
monsters until they're extinct.  This makes it check for confusion before
finding containers, but the chest/exchequer code doesn't always kick in
so can't be attempted as many times before confusion expires, throttling
summoning a little.  Also, when placing hero's gold into a chest, it now
clears the contents-known flag and relocks the chest.
  • Loading branch information
nethack.rankin committed Jan 25, 2007
1 parent e93303e commit 0bd89ff
Show file tree
Hide file tree
Showing 2 changed files with 90 additions and 57 deletions.
1 change: 1 addition & 0 deletions doc/fixes35.0
Expand Up @@ -30,6 +30,7 @@ class genocide recognizes species name as an example of the class to
internals: use Is_box rather than explicitly checking what it checks
fix some unreachable messages (either make then reachable or remove them)
can quiver coins when GOLDOBJ is defined
make #loot behave same for GOLDOBJ as for !GOLDOBJ
grammar, spelling and other typos
keep various delayed killers separate to avoid mixed up messages
don't place randomly-placed aquatic monsters in lava on special levels
Expand Down
146 changes: 89 additions & 57 deletions src/pickup.c
Expand Up @@ -40,6 +40,7 @@ STATIC_DCL char FDECL(in_or_out_menu, (const char *,struct obj *,
BOOLEAN_P,BOOLEAN_P,BOOLEAN_P));
STATIC_DCL int FDECL(container_at, (int, int, BOOLEAN_P));
STATIC_DCL boolean FDECL(able_to_loot, (int,int,BOOLEAN_P));
STATIC_DCL boolean NDECL(reverse_loot);
STATIC_DCL boolean FDECL(mon_beside, (int, int));
STATIC_DCL void FDECL(tipcontainer, (struct obj *));

Expand Down Expand Up @@ -1537,6 +1538,13 @@ doloot() /* loot a container on the floor or loot saddle from mon. */
You("have no hands!"); /* not `body_part(HAND)' */
return 0;
}
if (Confusion) {
if (rn2(6) && reverse_loot()) return 1;
if (rn2(2)) {
pline("Being confused, you find nothing to loot.");
return 1; /* costs a turn */
} /* else fallthrough to normal looting */
}
cc.x = u.ux; cc.y = u.uy;

lootcont:
Expand Down Expand Up @@ -1583,63 +1591,6 @@ doloot() /* loot a container on the floor or loot saddle from mon. */
}
}
if (any) c = 'y';
} else if (Confusion) {
#ifndef GOLDOBJ
if (u.ugold){
long contribution = rnd((int)min(LARGEST_INT,u.ugold));
struct obj *goldob = mkgoldobj(contribution);
#else
struct obj *goldob;
/* Find a money object to mess with */
for (goldob = invent; goldob; goldob = goldob->nobj) {
if (goldob->oclass == COIN_CLASS) break;
}
if (goldob){
long contribution = rnd((int)min(LARGEST_INT, goldob->quan));
if (contribution < goldob->quan)
goldob = splitobj(goldob, contribution);
freeinv(goldob);
#endif
if (IS_THRONE(levl[u.ux][u.uy].typ)){
struct obj *coffers;
int pass;
/* find the original coffers chest, or any chest */
for (pass = 2; pass > -1; pass -= 2)
for (coffers = fobj; coffers; coffers = coffers->nobj)
if (coffers->otyp == CHEST && coffers->spe == pass)
goto gotit; /* two level break */
gotit:
if (coffers) {
verbalize("Thank you for your contribution to reduce the debt.");
(void) add_to_container(coffers, goldob);
coffers->owt = weight(coffers);
} else {
struct monst *mon = makemon(courtmon(),
u.ux, u.uy, NO_MM_FLAGS);
if (mon) {
#ifndef GOLDOBJ
mon->mgold += goldob->quan;
delobj(goldob);
pline("The exchequer accepts your contribution.");
} else {
dropx(goldob);
}
}
} else {
dropx(goldob);
#else
add_to_minv(mon, goldob);
pline("The exchequer accepts your contribution.");
} else {
dropy(goldob);
}
}
} else {
dropy(goldob);
#endif
pline("Ok, now there is loot here.");
}
}
} else if (IS_GRAVE(levl[cc.x][cc.y].typ)) {
You("need to dig up the grave to effectively loot it...");
}
Expand Down Expand Up @@ -1690,6 +1641,87 @@ doloot() /* loot a container on the floor or loot saddle from mon. */
return (timepassed);
}

/* called when attempting to #loot while confused */
STATIC_OVL boolean
reverse_loot()
{
struct obj *goldob = 0, *coffers, *otmp, boxdummy;
struct monst *mon;
long contribution;
int n, x = u.ux, y = u.uy;

if (!rn2(3)) {
/* n objects: 1/(n+1) chance per object plus 1/(n+1) to fall off end */
for (n = inv_cnt(), otmp = invent; otmp; --n, otmp = otmp->nobj)
if (!rn2(n + 1)) {
prinv("You find old loot:", otmp, 0L);
return TRUE;
}
return FALSE;
}

#ifndef GOLDOBJ
if (u.ugold) {
contribution = ((long)rnd(5) * u.ugold + 4L) / 5L;
goldob = mkgoldobj(contribution);
}
#else
/* find a money object to mess with */
for (goldob = invent; goldob; goldob = goldob->nobj)
if (goldob->oclass == COIN_CLASS) {
contribution = ((long)rnd(5) * goldob->quan + 4L) / 5L;
if (contribution < goldob->quan)
goldob = splitobj(goldob, contribution);
break;
}
#endif
if (!goldob) return FALSE;

if (!IS_THRONE(levl[x][y].typ)) {
dropx(goldob);
/* the dropped gold might have fallen to lower level */
if (g_at(x, y)) pline("Ok, now there is loot here.");
} else {
/* find original coffers chest if present, otherwise use nearest one */
otmp = 0;
for (coffers = fobj; coffers; coffers = coffers->nobj)
if (coffers->otyp == CHEST) {
if (coffers->spe == 2) break; /* a throne room chest */
if (!otmp ||
distu(coffers->ox, coffers->oy) < distu(otmp->ox, otmp->oy))
otmp = coffers; /* remember closest ordinary chest */
}
if (!coffers) coffers = otmp;

if (coffers) {
verbalize("Thank you for your contribution to reduce the debt.");
#ifdef GOLDOBJ
freeinv(goldob);
#endif
(void)add_to_container(coffers, goldob);
coffers->owt = weight(coffers);
coffers->cknown = 0;
if (!coffers->olocked) {
boxdummy = zeroobj, boxdummy.otyp = SPE_WIZARD_LOCK;
(void)boxlock(coffers, &boxdummy);
}
} else if ((mon = makemon(courtmon(), x, y, NO_MM_FLAGS)) != 0) {
#ifndef GOLDOBJ
mon->mgold += goldob->quan;
delobj(goldob);
#else
freeinv(goldob);
add_to_minv(mon, goldob);
#endif
pline("The exchequer accepts your contribution.");
} else {
You("drop %s.", doname(goldob));
dropx(goldob);
}
}
return TRUE;
}

/* loot_mon() returns amount of time passed.
*/
int
Expand Down

0 comments on commit 0bd89ff

Please sign in to comment.