Skip to content

Commit

Permalink
fix #2468 - killer bees without a queen
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
PatR committed Dec 22, 2018
1 parent bba5d14 commit 4159dd9
Show file tree
Hide file tree
Showing 6 changed files with 93 additions and 17 deletions.
2 changes: 2 additions & 0 deletions doc/fixes37.0
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
3 changes: 2 additions & 1 deletion include/extern.h
Original file line number Diff line number Diff line change
@@ -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. */

Expand Down Expand Up @@ -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 *));
Expand Down
17 changes: 16 additions & 1 deletion src/dog.c
Original file line number Diff line number Diff line change
@@ -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. */
Expand Down Expand Up @@ -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;

Expand Down
18 changes: 12 additions & 6 deletions src/dogmove.c
Original file line number Diff line number Diff line change
@@ -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. */
Expand Down Expand Up @@ -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];

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -1184,7 +1190,7 @@ int after; /* this is extra fast monster movement */
}
}

newdogpos:
newdogpos:
if (nix != omx || niy != omy) {
boolean wasseen;

Expand Down Expand Up @@ -1256,7 +1262,7 @@ int after; /* this is extra fast monster movement */
}
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);
Expand Down
8 changes: 5 additions & 3 deletions src/makemon.c
Original file line number Diff line number Diff line change
@@ -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. */
Expand Down Expand Up @@ -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;

Expand Down
62 changes: 56 additions & 6 deletions src/monmove.c
Original file line number Diff line number Diff line change
@@ -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. */
Expand Down Expand Up @@ -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 */
Expand Down Expand Up @@ -371,19 +413,19 @@ 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
*/

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))
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -571,6 +613,14 @@ register struct monst *mtmp;
/* 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)
Expand Down

0 comments on commit 4159dd9

Please sign in to comment.