Confused #loot (trunk only)

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.
This commit is contained in:
nethack.rankin
2007-01-25 05:01:01 +00:00
parent e93303eae4
commit 0bd89ff28d
2 changed files with 90 additions and 57 deletions
+1
View File
@@ -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 internals: use Is_box rather than explicitly checking what it checks
fix some unreachable messages (either make then reachable or remove them) fix some unreachable messages (either make then reachable or remove them)
can quiver coins when GOLDOBJ is defined can quiver coins when GOLDOBJ is defined
make #loot behave same for GOLDOBJ as for !GOLDOBJ
grammar, spelling and other typos grammar, spelling and other typos
keep various delayed killers separate to avoid mixed up messages keep various delayed killers separate to avoid mixed up messages
don't place randomly-placed aquatic monsters in lava on special levels don't place randomly-placed aquatic monsters in lava on special levels
+89 -57
View File
@@ -40,6 +40,7 @@ STATIC_DCL char FDECL(in_or_out_menu, (const char *,struct obj *,
BOOLEAN_P,BOOLEAN_P,BOOLEAN_P)); BOOLEAN_P,BOOLEAN_P,BOOLEAN_P));
STATIC_DCL int FDECL(container_at, (int, int, 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 FDECL(able_to_loot, (int,int,BOOLEAN_P));
STATIC_DCL boolean NDECL(reverse_loot);
STATIC_DCL boolean FDECL(mon_beside, (int, int)); STATIC_DCL boolean FDECL(mon_beside, (int, int));
STATIC_DCL void FDECL(tipcontainer, (struct obj *)); STATIC_DCL void FDECL(tipcontainer, (struct obj *));
@@ -1537,6 +1538,13 @@ doloot() /* loot a container on the floor or loot saddle from mon. */
You("have no hands!"); /* not `body_part(HAND)' */ You("have no hands!"); /* not `body_part(HAND)' */
return 0; 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; cc.x = u.ux; cc.y = u.uy;
lootcont: lootcont:
@@ -1583,63 +1591,6 @@ lootcont:
} }
} }
if (any) c = 'y'; 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)) { } else if (IS_GRAVE(levl[cc.x][cc.y].typ)) {
You("need to dig up the grave to effectively loot it..."); You("need to dig up the grave to effectively loot it...");
} }
@@ -1690,6 +1641,87 @@ gotit:
return (timepassed); 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. /* loot_mon() returns amount of time passed.
*/ */
int int