diff --git a/doc/fixes37.0 b/doc/fixes37.0 index c83af6c37..465eef81d 100644 --- a/doc/fixes37.0 +++ b/doc/fixes37.0 @@ -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 diff --git a/include/extern.h b/include/extern.h index 78c7647da..10d7335d5 100644 --- a/include/extern.h +++ b/include/extern.h @@ -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 *)); diff --git a/src/dog.c b/src/dog.c index 93a33716e..051a46f26 100644 --- a/src/dog.c +++ b/src/dog.c @@ -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; diff --git a/src/dogmove.c b/src/dogmove.c index 1c8f4dd79..8a3cd1b04 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -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); diff --git a/src/makemon.c b/src/makemon.c index d78363130..9c6bd6b43 100644 --- a/src/makemon.c +++ b/src/makemon.c @@ -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; diff --git a/src/monmove.c b/src/monmove.c index fbc2d419d..a59963aec 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -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)