fix #2468 - killer bees without a queen

Seven year old suggestion was to have a killer bee eat royal jelly if
there was no queen around, then after a short delay it would become a
queen.  This does that, with "no queen around" being "no queen bee on
current dungeon level" and the transformation happening immediately
with the "short delay" taking place after.

Pet killer bees will target nearby royal jelly if there's no queen,
hostile killer bees will only eat it if they happen to walk on the
same spot as one.  Both types accept either tame or hostile queen bee
as an existing queen.

Killer bees eating royal jelly will drop dead if queen bees have been
genocided, and aren't smart enough to avoid the instinct to eat such
if/when that happens to be the situation.
This commit is contained in:
PatR
2018-12-21 16:59:01 -08:00
parent bba5d14dca
commit 4159dd985a
6 changed files with 93 additions and 17 deletions

View File

@@ -14,6 +14,8 @@ Platform- and/or Interface-Specific Fixes
General New Features
--------------------
if a killer bee encounters a lump of royal jelly and there is no queen bee on
the level, the bee will eat the jelly and become a new queen
Platform- and/or Interface-Specific New Features

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1545383614 2018/12/21 09:13:34 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.675 $ */
/* NetHack 3.6 extern.h $NHDT-Date: 1545439142 2018/12/22 00:39:02 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.676 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1487,6 +1487,7 @@ E boolean FDECL(monhaskey, (struct monst *, BOOLEAN_P));
E void FDECL(mon_regen, (struct monst *, BOOLEAN_P));
E int FDECL(dochugw, (struct monst *));
E boolean FDECL(onscary, (int, int, struct monst *));
E int FDECL(bee_eat_jelly, (struct monst *, struct obj *));
E void FDECL(monflee, (struct monst *, int, BOOLEAN_P, BOOLEAN_P));
E void FDECL(mon_yells, (struct monst *, const char *));
E int FDECL(dochug, (struct monst *));

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 dog.c $NHDT-Date: 1543052701 2018/11/24 09:45:01 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.84 $ */
/* NetHack 3.6 dog.c $NHDT-Date: 1545439150 2018/12/22 00:39:10 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.85 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2011. */
/* NetHack may be freely redistributed. See license for details. */
@@ -757,6 +757,21 @@ register struct obj *obj;
if ((obj->otyp == CORPSE || obj->otyp == EGG) && touch_petrifies(fptr)
&& !resists_ston(mon))
return POISON;
if (obj->otyp == LUMP_OF_ROYAL_JELLY
&& mon->data == &mons[PM_KILLER_BEE]) {
struct monst *mtmp = 0;
/* if there's a queen bee on the level, don't eat royal jelly;
if there isn't, do eat it and grow into a queen */
if ((mvitals[PM_QUEEN_BEE].mvflags & G_GENOD) == 0)
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp))
continue;
if (mtmp->data == &mons[PM_QUEEN_BEE])
break;
}
return !mtmp ? DOGFOOD : TABU;
}
if (!carni && !herbi)
return obj->cursed ? UNDEF : APPORT;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 dogmove.c $NHDT-Date: 1502753407 2017/08/14 23:30:07 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.63 $ */
/* NetHack 3.6 dogmove.c $NHDT-Date: 1545439152 2018/12/22 00:39:12 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.72 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -211,7 +211,7 @@ boolean devour;
{
register struct edog *edog = EDOG(mtmp);
boolean poly, grow, heal, eyes, slimer, deadmimic;
int nutrit;
int nutrit, res;
long oprice;
char objnambuf[BUFSZ];
@@ -250,6 +250,11 @@ boolean devour;
newsym(x, y);
newsym(mtmp->mx, mtmp->my);
}
if (mtmp->data == &mons[PM_KILLER_BEE]
&& obj->otyp == LUMP_OF_ROYAL_JELLY
&& (res = bee_eat_jelly(mtmp, obj)) >= 0)
/* bypass most of dog_eat(), including apport update */
return (res + 1); /* 1 -> 2, 0 -> 1; -1, keep going */
/* food items are eaten one at a time; entire stack for other stuff */
if (obj->quan > 1L && obj->oclass == FOOD_CLASS)
@@ -379,8 +384,9 @@ struct edog *edog;
else
You_feel("worried about %s.", y_monnam(mtmp));
stop_occupation();
} else if (monstermoves > edog->hungrytime + 750 || DEADMONSTER(mtmp)) {
dog_died:
} else if (monstermoves > edog->hungrytime + 750
|| DEADMONSTER(mtmp)) {
dog_died:
if (mtmp->mleashed && mtmp != u.usteed)
Your("leash goes slack.");
else if (cansee(mtmp->mx, mtmp->my))
@@ -1184,7 +1190,7 @@ int after; /* this is extra fast monster movement */
}
}
newdogpos:
newdogpos:
if (nix != omx || niy != omy) {
boolean wasseen;
@@ -1256,7 +1262,7 @@ newdogpos:
}
cc.x = mtmp->mx;
cc.y = mtmp->my;
dognext:
dognext:
if (!m_in_out_region(mtmp, nix, niy))
return 1;
remove_monster(mtmp->mx, mtmp->my);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 makemon.c $NHDT-Date: 1544998885 2018/12/16 22:21:25 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.131 $ */
/* NetHack 3.6 makemon.c $NHDT-Date: 1545439153 2018/12/22 00:39:13 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.132 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Robert Patrick Rankin, 2012. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1801,9 +1801,11 @@ struct monst *mtmp, *victim;
return (struct permonst *) 0;
/* note: none of the monsters with special hit point calculations
have both little and big forms */
have both little and big forms (killer bee can't grow into queen
bee by just killing things, so isn't in the little_to_big list) */
oldtype = monsndx(ptr);
newtype = little_to_big(oldtype);
newtype = (oldtype == PM_KILLER_BEE && !victim) ? PM_QUEEN_BEE
: little_to_big(oldtype);
if (newtype == PM_PRIEST && mtmp->female)
newtype = PM_PRIESTESS;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 monmove.c $NHDT-Date: 1544442712 2018/12/10 11:51:52 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.109 $ */
/* NetHack 3.6 monmove.c $NHDT-Date: 1545439153 2018/12/22 00:39:13 $ $NHDT-Branch: NetHack-3.6.2-beta01 $:$NHDT-Revision: 1.110 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/*-Copyright (c) Michael Allison, 2006. */
/* NetHack may be freely redistributed. See license for details. */
@@ -254,6 +254,48 @@ struct monst *mon;
}
}
/* killer bee 'mon' is on a spot containing lump of royal jelly 'obj' and
will eat it if there is no queen bee on the level; return 1: mon died,
0: mon ate jelly and lived; -1: mon didn't eat jelly to use its move */
int
bee_eat_jelly(mon, obj)
struct monst *mon;
struct obj *obj;
{
int m_delay;
struct monst *mtmp = 0;
/* find a queen bee */
if ((mvitals[PM_QUEEN_BEE].mvflags & G_GENOD) == 0)
for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) {
if (DEADMONSTER(mtmp))
continue;
if (mtmp->data == &mons[PM_QUEEN_BEE])
break;
}
/* if there's no queen on the level, eat the royal jelly and become one */
if (!mtmp) {
m_delay = obj->blessed ? 3 : !obj->cursed ? 5 : 7;
if (obj->quan > 1L)
obj = splitobj(obj, 1L);
if (canseemon(mon))
pline("%s eats %s.", Monnam(mon), an(xname(obj)));
delobj(obj);
if ((int) mon->m_lev < mons[PM_QUEEN_BEE].mlevel - 1)
mon->m_lev = (uchar) (mons[PM_QUEEN_BEE].mlevel - 1);
/* there should be delay after eating, but that's too much
hassle; transform immediately, then have a short delay */
(void) grow_up(mon, (struct monst *) 0);
if (DEADMONSTER(mon))
return 1; /* dead; apparently queen bees have been genocided */
mon->mfrozen = m_delay, mon->mcanmove = 0;
return 0; /* bee used its move */
}
return -1; /* a queen is already present; ordinary bee hasn't moved yet */
}
#define flees_light(mon) ((mon)->data == &mons[PM_GREMLIN] \
&& (uwep && artifact_light(uwep) && uwep->lamplit))
/* we could include this in the above macro, but probably overkill/overhead */
@@ -371,7 +413,8 @@ register struct monst *mtmp;
{
register struct permonst *mdat;
register int tmp = 0;
int inrange, nearby, scared;
int inrange, nearby, scared, res;
struct obj *otmp;
/* Pre-movement adjustments
*/
@@ -379,11 +422,10 @@ register struct monst *mtmp;
mdat = mtmp->data;
if (mtmp->mstrategy & STRAT_ARRIVE) {
int res = m_arrival(mtmp);
res = m_arrival(mtmp);
if (res >= 0)
return res;
}
/* check for waitmask status change */
if ((mtmp->mstrategy & STRAT_WAITFORU)
&& (m_canseeu(mtmp) || mtmp->mhp < mtmp->mhpmax))
@@ -541,9 +583,9 @@ register struct monst *mtmp;
}
}
}
toofar:
toofar:
/* If monster is nearby you, and has to wield a weapon, do so. This
/* If monster is nearby you, and has to wield a weapon, do so. This
* costs the monster a move, of course.
*/
if ((!mtmp->mpeaceful || Conflict) && inrange
@@ -571,6 +613,14 @@ toofar:
/* Now the actual movement phase
*/
if (mdat == &mons[PM_KILLER_BEE]
/* could be smarter and deliberately move to royal jelly, but
then we'd need to scan the level for queen bee in advance;
avoid that overhead and rely on serendipity... */
&& (otmp = sobj_at(LUMP_OF_ROYAL_JELLY, mtmp->mx, mtmp->my)) != 0
&& (res = bee_eat_jelly(mtmp, otmp)) >= 0)
return res;
if (!nearby || mtmp->mflee || scared || mtmp->mconf || mtmp->mstun
|| (mtmp->minvis && !rn2(3))
|| (mdat->mlet == S_LEPRECHAUN && !findgold(invent)