From: nethack.allison Date: Wed, 12 Nov 2003 03:28:26 +0000 (+0000) Subject: B01004 No mimic corpse effect on pet (trunk only) X-Git-Tag: MOVE2GIT~1599 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=52490ee062cfb375c6605c82596d3fe5eb19e764;p=nethack B01004 No mimic corpse effect on pet (trunk only) Make a mimic effect that lasts only as long as the pet is still consuming the corpse. --- diff --git a/include/extern.h b/include/extern.h index 883aa3567..4c757a274 100644 --- a/include/extern.h +++ b/include/extern.h @@ -422,6 +422,7 @@ E int FDECL(dog_move, (struct monst *,int)); #ifdef USE_TRAMPOLI E void FDECL(wantdoor, (int,int,genericptr_t)); #endif +E void FDECL(finish_meating,(struct monst *)); /* ### dokick.c ### */ diff --git a/src/dog.c b/src/dog.c index 2104292f6..45073ff1e 100644 --- a/src/dog.c +++ b/src/dog.c @@ -436,7 +436,7 @@ long nmv; /* number of moves */ if (mtmp->mstun && rn2(imv + 1) > 10/2) mtmp->mstun = 0; /* might finish eating or be able to use special ability again */ - if (imv > mtmp->meating) mtmp->meating = 0; + if (imv > mtmp->meating) finish_meating(mtmp); else mtmp->meating -= imv; if (imv > mtmp->mspec_used) mtmp->mspec_used = 0; else mtmp->mspec_used -= imv; @@ -837,7 +837,8 @@ boolean was_dead; struct edog *edog; boolean quietly = was_dead; - mtmp->meating = 0; + finish_meating(mtmp); + if (!mtmp->mtame) return; edog = !mtmp->isminion ? EDOG(mtmp) : 0; diff --git a/src/dogmove.c b/src/dogmove.c index 2dd36f339..987d31f96 100644 --- a/src/dogmove.c +++ b/src/dogmove.c @@ -17,6 +17,7 @@ STATIC_DCL struct obj *FDECL(DROPPABLES, (struct monst *)); STATIC_DCL boolean FDECL(can_reach_location,(struct monst *,XCHAR_P,XCHAR_P, XCHAR_P,XCHAR_P)); STATIC_DCL boolean FDECL(could_reach_item,(struct monst *, XCHAR_P,XCHAR_P)); +STATIC_DCL void FDECL(quickmimic, (struct monst *)); STATIC_OVL struct obj * DROPPABLES(mon) @@ -124,10 +125,17 @@ boolean devour; register struct edog *edog = EDOG(mtmp); boolean poly = FALSE, grow = FALSE, heal = FALSE; int nutrit; + boolean deadmimic = FALSE; if(edog->hungrytime < monstermoves) edog->hungrytime = monstermoves; nutrit = dog_nutrition(mtmp, obj); + + deadmimic = (obj->otyp == CORPSE && + (obj->corpsenm == PM_SMALL_MIMIC || + obj->corpsenm == PM_LARGE_MIMIC || + obj->corpsenm == PM_GIANT_MIMIC)); + poly = polyfodder(obj); grow = mlevelgain(obj); heal = mhealup(obj); @@ -192,11 +200,13 @@ boolean devour; (void) newcham(mtmp, (struct permonst *)0, FALSE, cansee(mtmp->mx, mtmp->my)); } + /* limit "instant" growth to prevent potential abuse */ if (grow && (int) mtmp->m_lev < (int)mtmp->data->mlevel + 15) { if (!grow_up(mtmp, (struct monst *)0)) return 2; } if (heal) mtmp->mhp = mtmp->mhpmax; + if (deadmimic) quickmimic(mtmp); return 1; } @@ -853,4 +863,79 @@ genericptr_t distance; } } + +static struct qmchoices { + int mndx; /* type of pet, 0 means any */ + char mlet; /* symbol of pet, 0 means any */ + unsigned mappearance; /* mimic this */ + uchar m_ap_type; /* what is the thing it is mimicing? */ +} qm[] = { + /* Things that some pets might be thinking about at the time */ + {PM_LITTLE_DOG, 0, PM_KITTEN, M_AP_MONSTER}, + {PM_LARGE_DOG, 0, PM_LARGE_CAT, M_AP_MONSTER}, + {PM_KITTEN, 0, PM_LITTLE_DOG, M_AP_MONSTER}, + {PM_LARGE_CAT, 0, PM_LARGE_DOG, M_AP_MONSTER}, + {PM_HOUSECAT, 0, PM_DOG, M_AP_MONSTER}, + {PM_DOG, 0, PM_HOUSECAT, M_AP_MONSTER}, + {PM_HOUSECAT, 0, PM_GIANT_RAT, M_AP_MONSTER}, +#ifdef SINKS + {0, S_DOG, SINK, M_AP_FURNITURE}, /* sorry, no fire hydrants in NetHack */ +#endif + {0, 0, TRIPE_RATION, M_AP_OBJECT}, /* leave this at end */ +}; + +void +finish_meating(mtmp) +struct monst *mtmp; +{ + mtmp->meating = 0; + if (mtmp->m_ap_type && mtmp->mappearance && !mtmp->cham) { + /* was eating a mimic and now appearance needs resetting */ + mtmp->m_ap_type = 0; + mtmp->mappearance = 0; + newsym(mtmp->mx, mtmp->my); + } +} + +STATIC_OVL void +quickmimic(mtmp) +struct monst *mtmp; +{ + int idx = 0, trycnt = 5; + char buf[BUFSZ]; + + if (Protection_from_shape_changers || Blind || !mtmp->meating) return; + + do { + idx = rn2(SIZE(qm)); + if (qm[idx].mndx != 0 && monsndx(mtmp->data) == qm[idx].mndx) + break; + if (qm[idx].mlet != 0 && mtmp->data->mlet == qm[idx].mlet) + break; + if (qm[idx].mndx == 0 && qm[idx].mlet == 0) + break; + } while (--trycnt > 0); + if (trycnt == 0) idx = SIZE(qm)-1; + if (!idx) return; /* impossible */ + + Strcpy(buf, mon_nam(mtmp)); + + mtmp->m_ap_type = qm[idx].m_ap_type; + mtmp->mappearance = qm[idx].mappearance; + + newsym(mtmp->mx,mtmp->my); + You("see %s appear where %s was!", + (mtmp->m_ap_type == M_AP_FURNITURE) ? + an(defsyms[mtmp->mappearance].explanation) : + (mtmp->m_ap_type == M_AP_OBJECT && + OBJ_DESCR(objects[mtmp->mappearance])) ? + an(OBJ_DESCR(objects[mtmp->mappearance])) : + (mtmp->m_ap_type == M_AP_OBJECT && + OBJ_NAME(objects[mtmp->mappearance])) ? + an(OBJ_NAME(objects[mtmp->mappearance])) : + (mtmp->m_ap_type == M_AP_MONSTER) ? + an(mons[mtmp->mappearance].mname) : something, buf); + display_nhwindow(WIN_MAP, TRUE); +} + /*dogmove.c*/ diff --git a/src/dokick.c b/src/dokick.c index 07d0ebbb3..43169418d 100644 --- a/src/dokick.c +++ b/src/dokick.c @@ -250,7 +250,7 @@ register struct obj *gold; long value = gold->quan * objects[gold->otyp].oc_cost; #endif mtmp->msleeping = 0; - mtmp->meating = 0; + finish_meating(mtmp); if(!rn2(4)) setmangry(mtmp); /* not always pleasing */ /* greedy monsters catch gold */ diff --git a/src/mon.c b/src/mon.c index f5d73d97a..ffa2c66d8 100644 --- a/src/mon.c +++ b/src/mon.c @@ -2098,7 +2098,7 @@ wakeup(mtmp) register struct monst *mtmp; { mtmp->msleeping = 0; - mtmp->meating = 0; /* assume there's no salvagable food left */ + finish_meating(mtmp); setmangry(mtmp); if(mtmp->m_ap_type) seemimic(mtmp); else if (context.forcefight && !context.mon_moving && mtmp->mundetected) { diff --git a/src/monmove.c b/src/monmove.c index 37dddf336..9f2696a5d 100644 --- a/src/monmove.c +++ b/src/monmove.c @@ -141,7 +141,10 @@ boolean digest_meal; (moves % 20 == 0 || regenerates(mon->data))) mon->mhp++; if (mon->mspec_used) mon->mspec_used--; if (digest_meal) { - if (mon->meating) mon->meating--; + if (mon->meating) { + mon->meating--; + if (mon->meating <= 0) finish_meating(mon); + } } } @@ -603,6 +606,7 @@ register int after; if (mtmp->meating) { mtmp->meating--; + if (mtmp->meating <= 0) finish_meating(mtmp); return 3; /* still eating */ } if (hides_under(ptr) && OBJ_AT(mtmp->mx, mtmp->my) && rn2(10)) diff --git a/src/pline.c b/src/pline.c index ea863dd7e..2febc95f0 100644 --- a/src/pline.c +++ b/src/pline.c @@ -305,6 +305,21 @@ register struct monst *mtmp; } else if (mtmp->mpeaceful) Strcat(info, ", peaceful"); if (mtmp->meating) Strcat(info, ", eating"); + if (mtmp->meating && !mtmp->cham && + mtmp->mappearance && mtmp->m_ap_type) { + Sprintf(eos(info), ", mimicing %s", + (mtmp->m_ap_type == M_AP_FURNITURE) ? + an(defsyms[mtmp->mappearance].explanation) : + (mtmp->m_ap_type == M_AP_OBJECT && + OBJ_DESCR(objects[mtmp->mappearance])) ? + an(OBJ_DESCR(objects[mtmp->mappearance])) : + (mtmp->m_ap_type == M_AP_OBJECT && + OBJ_NAME(objects[mtmp->mappearance])) ? + an(OBJ_NAME(objects[mtmp->mappearance])) : + (mtmp->m_ap_type == M_AP_MONSTER) ? + an(mons[mtmp->mappearance].mname) : + something); + } if (mtmp->mcan) Strcat(info, ", cancelled"); if (mtmp->mconf) Strcat(info, ", confused"); if (mtmp->mblinded || !mtmp->mcansee)