diff -Naur nethack-3.4.2/include/obj.h nethack-poison/include/obj.h --- nethack-3.4.2/include/obj.h 2003-08-30 10:07:21.000000000 +1000 +++ nethack-poison/include/obj.h 2003-10-16 20:39:10.000000000 +1000 @@ -76,7 +76,14 @@ Bitfield(otrapped,1); /* container is trapped */ /* or accidental tripped rolling boulder trap */ #define opoisoned otrapped /* object (weapon) is coated with poison */ - +#define opoistype recharged +#define OPOISON_SICKNESS 0 +#define OPOISON_SLEEPING 1 +#define OPOISON_CONFUSION 2 +#define OPOISON_PARALYSIS 3 +#define OPOISON_KNOWN 4 +#define poison_type(otmp) ((otmp)->opoistype & 3) +#define poison_known(otmp) ((otmp)->opoistype & OPOISON_KNOWN) Bitfield(recharged,3); /* number of times it's been recharged */ Bitfield(lamplit,1); /* a light-source -- can be lit */ #ifdef INVISIBLE_OBJECTS diff -Naur nethack-3.4.2/src/CHANGES nethack-poison/src/CHANGES --- nethack-3.4.2/src/CHANGES 1970-01-01 10:00:00.000000000 +1000 +++ nethack-poison/src/CHANGES 2003-10-16 22:21:01.000000000 +1000 @@ -0,0 +1,56 @@ +* potion.c dodip() + + Dipping poisonable objects in potions of sleep, confusion and paralysis + also sets the opoisoned bit. And the opoistype field contains the type + of poison + +* obj.h + + Added opoistype as an alias for the recharged field (which is not used + on weapons). Added four constants for types of poison. + Extra bit is OPOISON_KNOWN which is true if you know what kind of + poison it is. + +* eat.c + + Filled out the effects of eating different types of poison weapons. + (I just copied the code from peffects in potion.c) + +* makemon.c + + Orcish arrows always have OPOISON_SICKNESS (the standard poison). + +* mkobj.c + + Randomly created poisoned objects can have any of the coatings. + +* mthrowu.c + + ohitmon: Different effects for poisoned missile weapons + m_throw: + +* objnam.c + + Different names for different kinds of coatings. + Just "coated" if the type is unknown. + Can wish for different types (including "poison coated") + Objects are not fully identified if their coating is unknown + +* invent.c + + Identify will reveal the type of poison. + Different poison types will not merge. + +* zap.c + + Polymorphing a weapon maintains its poison type. + +* trap.c + + Poison darts come in all varieties. + I increased the probability of some kind poison to make up for + the lower probabiliy of deadly poison (was 1/6, now 1/16) + +* uhitm.c + + Added appropriate poison effects when you hit a monster diff -Naur nethack-3.4.2/src/eat.c nethack-poison/src/eat.c --- nethack-3.4.2/src/eat.c 2003-08-30 10:07:30.000000000 +1000 +++ nethack-poison/src/eat.c 2003-10-16 20:32:49.000000000 +1000 @@ -1944,12 +1944,61 @@ (void) rottenfood(otmp); if (otmp->oclass == WEAPON_CLASS && otmp->opoisoned) { - pline("Ecch - that must have been poisonous!"); - if(!Poison_resistance) { - losestr(rnd(4)); - losehp(rnd(15), xname(otmp), KILLED_BY_AN); - } else - You("seem unaffected by the poison."); + switch (poison_type(otmp)) { + case OPOISON_SICKNESS: + pline("Ecch - that must have been poisonous!"); + if(!Poison_resistance) { + losestr(rnd(4)); + losehp(rnd(15), xname(otmp), KILLED_BY_AN); + } else + You("seem unaffected by the poison."); + break; + + case OPOISON_SLEEPING: + if(Sleep_resistance || Free_action) + You("yawn."); + else { + You("suddenly fall asleep!"); + fall_asleep(-rn1(10, 25 - 12*bcsign(otmp)), TRUE); + } + break; + + case OPOISON_CONFUSION: + if(!Confusion) { + if (Hallucination) { + pline("What a trippy feeling!"); + } else { + pline("Huh, What? Where am I?"); + } + } + make_confused(HConfusion + rn1(7, 16), FALSE); + break; + + case OPOISON_PARALYSIS: + if (Free_action) { + You("stiffen momentarily."); + } + else { + if (Levitation || + Is_airlevel(&u.uz)||Is_waterlevel(&u.uz)) { + You("are motionlessly suspended."); + } +#ifdef STEED + else if (u.usteed) { + You("are frozen in place!"); + } +#endif + else { + Your("%s are frozen to the %s!", + makeplural(body_part(FOOT)), surface(u.ux, u.uy)); + } + nomul(-(rn1(10, 25 - 12*bcsign(otmp)))); + nomovemsg = You_can_move_again; + exercise(A_DEX, FALSE); + } + + break; + } } else if (!otmp->cursed) pline("This %s is delicious!", otmp->oclass == COIN_CLASS ? foodword(otmp) : diff -Naur nethack-3.4.2/src/invent.c nethack-poison/src/invent.c --- nethack-3.4.2/src/invent.c 2003-08-30 10:07:32.000000000 +1000 +++ nethack-poison/src/invent.c 2003-10-16 21:25:33.000000000 +1000 @@ -1475,6 +1475,9 @@ otmp->known = otmp->dknown = otmp->bknown = otmp->rknown = 1; if (otmp->otyp == EGG && otmp->corpsenm != NON_PM) learn_egg_type(otmp->corpsenm); + if (otmp->opoisoned) { + otmp->opoistype |= OPOISON_KNOWN; + } } /* ggetobj callback routine; identify an object and give immediate feedback */ @@ -2345,6 +2348,12 @@ obj->bypass != otmp->bypass) return(FALSE); + /* MRKR: Don't merge different poisoned weapon types */ + /* or unknown coating with known. */ + if (is_poisonable(obj) && obj->opoistype != otmp->opoistype) { + return FALSE; + } + if ((obj->oclass==WEAPON_CLASS || obj->oclass==ARMOR_CLASS) && (obj->oerodeproof!=otmp->oerodeproof || obj->rknown!=otmp->rknown)) return FALSE; diff -Naur nethack-3.4.2/src/makemon.c nethack-poison/src/makemon.c --- nethack-3.4.2/src/makemon.c 2003-08-30 10:07:32.000000000 +1000 +++ nethack-poison/src/makemon.c 2003-10-16 19:23:40.000000000 +1000 @@ -153,7 +153,10 @@ otmp = mksobj(otyp, TRUE, FALSE); otmp->quan = (long) rn1(oquan, 3); otmp->owt = weight(otmp); - if (otyp == ORCISH_ARROW) otmp->opoisoned = TRUE; + if (otyp == ORCISH_ARROW) { + otmp->opoisoned = TRUE; + otmp->opoistype = OPOISON_SICKNESS; + } (void) mpickobj(mtmp, otmp); } diff -Naur nethack-3.4.2/src/mkobj.c nethack-poison/src/mkobj.c --- nethack-3.4.2/src/mkobj.c 2003-08-30 10:07:34.000000000 +1000 +++ nethack-poison/src/mkobj.c 2003-10-16 19:39:57.000000000 +1000 @@ -397,9 +397,10 @@ curse(otmp); otmp->spe = -rne(3); } else blessorcurse(otmp, 10); - if (is_poisonable(otmp) && !rn2(100)) + if (is_poisonable(otmp) && !rn2(100)) { otmp->opoisoned = 1; - + otmp->opoistype = rn2(4); + } if (artif && !rn2(20)) otmp = mk_artifact(otmp, (aligntyp)A_NONE); break; diff -Naur nethack-3.4.2/src/mthrowu.c nethack-poison/src/mthrowu.c --- nethack-3.4.2/src/mthrowu.c 2003-08-30 10:07:36.000000000 +1000 +++ nethack-poison/src/mthrowu.c 2003-10-16 20:33:37.000000000 +1000 @@ -179,17 +179,50 @@ else if (verbose) pline("%s is hit%s", Monnam(mtmp), exclam(damage)); if (otmp->opoisoned && is_poisonable(otmp)) { - if (resists_poison(mtmp)) { - if (vis) pline_The("poison doesn't seem to affect %s.", - mon_nam(mtmp)); - } else { - if (rn2(30)) { - damage += rnd(6); - } else { - if (vis) pline_The("poison was deadly..."); - damage = mtmp->mhp; + /* MRKR: Different types of poison */ + /* Stole code from potionhit() in potion.c */ + switch (poison_type(otmp)) { + case OPOISON_SICKNESS: + if (!resists_poison(mtmp)) { + if (rn2(30)) { + damage += rnd(6); + } else { + if (vis) { + pline_The("poison was deadly..."); + otmp->opoistype |= OPOISON_KNOWN; + } + damage = mtmp->mhp; + } } - } + break; + + case OPOISON_SLEEPING: + if (rn2(4) && sleep_monst(mtmp, rnd(12), POTION_CLASS)) { + if (vis) { + pline("%s falls asleep.", Monnam(mtmp)); + otmp->opoistype |= OPOISON_KNOWN; + } + slept_monst(mtmp); + otmp->opoistype |= OPOISON_KNOWN; + } + + break; + + case OPOISON_CONFUSION: + if(rn2(4) && !resist(mtmp, POTION_CLASS, 0, NOTELL)) { + mtmp->mconf = TRUE; + otmp->opoistype |= OPOISON_KNOWN; + } + break; + + case OPOISON_PARALYSIS: + if (rn2(4) && mtmp->mcanmove) { + mtmp->mcanmove = 0; + mtmp->mfrozen = rnd(25); + otmp->opoistype |= OPOISON_KNOWN; + } + break; + } } if (objects[otmp->otyp].oc_material == SILVER && hates_silver(mtmp->data)) { @@ -384,9 +417,55 @@ is_poisonable(singleobj)) { char onmbuf[BUFSZ], knmbuf[BUFSZ]; - Strcpy(onmbuf, xname(singleobj)); - Strcpy(knmbuf, killer_xname(singleobj)); - poisoned(onmbuf, A_STR, knmbuf, -10); + /* MRKR: Different kinds of poison */ + /* Stole effects from potionbreathe() */ + + switch (poison_type(singleobj)) { + case OPOISON_SICKNESS: + Strcpy(onmbuf, xname(singleobj)); + Strcpy(knmbuf, killer_xname(singleobj)); + + poisoned(onmbuf, A_STR, knmbuf, -10); + singleobj->opoistype |= OPOISON_KNOWN; + obj->opoistype |= OPOISON_KNOWN; + break; + + case OPOISON_SLEEPING: + if (!Free_action && !Sleep_resistance) { + You_feel("rather tired."); + nomul(-rnd(5)); + nomovemsg = You_can_move_again; + exercise(A_DEX, FALSE); + } else { + You("yawn."); + } + singleobj->opoistype |= OPOISON_KNOWN; + obj->opoistype |= OPOISON_KNOWN; + + break; + + case OPOISON_CONFUSION: + if(!Confusion) { + You_feel("somewhat dizzy."); + } + make_confused(HConfusion + rnd(5), FALSE); + singleobj->opoistype |= OPOISON_KNOWN; + obj->opoistype |= OPOISON_KNOWN; + break; + + case OPOISON_PARALYSIS: + if (!Free_action) { + pline("%s seems to be holding you.", Something); + nomul(-rnd(5)); + nomovemsg = You_can_move_again; + exercise(A_DEX, FALSE); + } else { + You("stiffen momentarily."); + } + singleobj->opoistype |= OPOISON_KNOWN; + obj->opoistype |= OPOISON_KNOWN; + break; + } } if(hitu && can_blnd((struct monst*)0, &youmonst, diff -Naur nethack-3.4.2/src/objnam.c nethack-poison/src/objnam.c --- nethack-3.4.2/src/objnam.c 2003-08-30 10:07:36.000000000 +1000 +++ nethack-poison/src/objnam.c 2003-10-16 21:15:23.000000000 +1000 @@ -54,6 +54,7 @@ #endif /* OVLB */ STATIC_DCL const char *FDECL(Japanese_item_name,(int i)); +STATIC_DCL const char *FDECL(poison_name, (struct obj* otmp)); #ifdef OVL1 @@ -274,8 +275,9 @@ Sprintf(buf,"%s amulet", dn); break; case WEAPON_CLASS: - if (is_poisonable(obj) && obj->opoisoned) - Strcpy(buf, "poisoned "); + if (is_poisonable(obj) && obj->opoisoned) { + Strcpy(buf, poison_name(obj)); + } case VENOM_CLASS: case TOOL_CLASS: if (typ == LENSES) @@ -571,9 +573,14 @@ * combining both into one function taking a parameter. */ /* must check opoisoned--someone can have a weirdly-named fruit */ - if (!strncmp(bp, "poisoned ", 9) && obj->opoisoned) { - bp += 9; + if (obj->opoisoned) { + const char* pname = poison_name(obj); + int len = strlen(pname); + + if (!strncmp(bp, pname, len)) { + bp += len; ispoisoned = TRUE; + } } if(obj->quan != 1L) @@ -631,7 +638,7 @@ break; case WEAPON_CLASS: if(ispoisoned) - Strcat(prefix, "poisoned "); + Strcat(prefix, poison_name(obj)); plus: add_erosion_words(obj, prefix); if(obj->known) { @@ -812,6 +819,11 @@ return TRUE; if (otmp->oartifact && undiscovered_artifact(otmp->oartifact)) return TRUE; + + /* MRKR: Unidentified poison coating */ + if (otmp->opoisoned && !poison_known(otmp)) { + return TRUE; + } /* otmp->rknown is the only item of interest if we reach here */ /* * Note: if a revision ever allows scrolls to become fireproof or @@ -1757,6 +1769,7 @@ register struct obj *otmp; int cnt, spe, spesgn, typ, very, rechrg; int blessed, uncursed, iscursed, ispoisoned, isgreased; + int poison; int eroded, eroded2, erodeproof; #ifdef INVISIBLE_OBJECTS int isinvisible; @@ -1786,7 +1799,7 @@ const char *name=0; cnt = spe = spesgn = typ = very = rechrg = - blessed = uncursed = iscursed = + blessed = uncursed = iscursed = poison = #ifdef INVISIBLE_OBJECTS isinvisible = #endif @@ -1860,12 +1873,28 @@ !strncmpi(bp,"unlabelled ", l=11) || !strncmpi(bp,"blank ", l=6)) { unlabeled = 1; - } else if(!strncmpi(bp, "poisoned ",l=9) + } else if(!strncmpi(bp, "coated ",l=7)) { + ispoisoned=1; + poison = rn2(4); + } else if(!strncmpi(bp, "poisoned ",l=9)) { + ispoisoned=1; + poison = OPOISON_SICKNESS; + } else if(!strncmpi(bp, "poison coated ",l=14)) { + ispoisoned=1; + poison = OPOISON_SICKNESS; + } else if(!strncmpi(bp, "sleep coated ",l=13)) { + ispoisoned=1; + poison = OPOISON_SLEEPING; + } else if(!strncmpi(bp, "paralysis coated ",l=17)) { + ispoisoned=1; + poison = OPOISON_SICKNESS; + } else if(!strncmpi(bp, "confusion coated ",l=17)) { + ispoisoned=1; + poison = OPOISON_SICKNESS; #ifdef WIZARD - || (wizard && !strncmpi(bp, "trapped ",l=8)) + } else if(wizard && !strncmpi(bp, "trapped ",l=8)) { + ispoisoned=1; #endif - ) { - ispoisoned=1; } else if(!strncmpi(bp, "greased ",l=8)) { isgreased=1; } else if (!strncmpi(bp, "very ", l=5)) { @@ -2659,8 +2688,10 @@ /* set poisoned */ if (ispoisoned) { - if (is_poisonable(otmp)) - otmp->opoisoned = (Luck >= 0); + if (is_poisonable(otmp) && Luck >= 0) { + otmp->opoisoned = 1; + otmp->opoistype = poison; + } else if (Is_box(otmp) || typ == TIN) otmp->otrapped = 1; else if (oclass == FOOD_CLASS) @@ -2675,7 +2706,7 @@ otmp->odiluted = 1; if (name) { - const char *aname; + const char *aname; short objtyp; /* an artifact name might need capitalization fixing */ @@ -2782,6 +2813,27 @@ } return "whatcha-may-callit"; } + +STATIC_OVL const char * +poison_name(otmp) +struct obj *otmp; +{ + if (poison_known(otmp)) { + switch (poison_type(otmp)) { + case OPOISON_SICKNESS: + return "poisoned "; + case OPOISON_SLEEPING: + return "sleep coated "; + case OPOISON_CONFUSION: + return "confusion coated "; + case OPOISON_PARALYSIS: + return "paralysis coated "; + } + } + else { + return "coated "; + } +} #endif /* OVLB */ /*objnam.c*/ diff -Naur nethack-3.4.2/src/potion.c nethack-poison/src/potion.c --- nethack-3.4.2/src/potion.c 2003-08-30 10:07:37.000000000 +1000 +++ nethack-poison/src/potion.c 2003-10-20 17:27:09.000000000 +1000 @@ -1744,7 +1744,14 @@ #endif if(is_poisonable(obj)) { - if(potion->otyp == POT_SICKNESS && !obj->opoisoned) { + + /* MRKR: More kinds of coated weapons */ + + if(!obj->opoisoned && + (potion->otyp == POT_SICKNESS || + potion->otyp == POT_SLEEPING || + potion->otyp == POT_CONFUSION || + potion->otyp == POT_PARALYSIS)) { char buf[BUFSZ]; if (potion->quan > 1L) Sprintf(buf, "One of %s", the(xname(potion))); @@ -1753,6 +1760,23 @@ pline("%s forms a coating on %s.", buf, the(xname(obj))); obj->opoisoned = TRUE; + switch (potion->otyp) { + case POT_SICKNESS: + obj->opoistype = OPOISON_SICKNESS; + break; + case POT_SLEEPING: + obj->opoistype = OPOISON_SLEEPING; + break; + case POT_CONFUSION: + obj->opoistype = OPOISON_CONFUSION; + break; + case POT_PARALYSIS: + obj->opoistype = OPOISON_PARALYSIS; + break; + } + if (objects[potion->otyp].oc_name_known) { + obj->opoistype |= OPOISON_KNOWN; + } goto poof; } else if(obj->opoisoned && (potion->otyp == POT_HEALING || diff -Naur nethack-3.4.2/src/trap.c nethack-poison/src/trap.c --- nethack-3.4.2/src/trap.c 2003-08-30 10:07:42.000000000 +1000 +++ nethack-poison/src/trap.c 2003-10-16 21:38:41.000000000 +1000 @@ -671,14 +671,54 @@ otmp = mksobj(DART, TRUE, FALSE); otmp->quan = 1L; otmp->owt = weight(otmp); - if (!rn2(6)) otmp->opoisoned = 1; + if (!rn2(4)) { + otmp->opoisoned = 1; + otmp->opoistype = rn2(4); + } #ifdef STEED if (u.usteed && !rn2(2) && steedintrap(trap, otmp)) /* nothing */; else #endif if (thitu(7, dmgval(otmp, &youmonst), otmp, "little dart")) { - if (otmp->opoisoned) - poisoned("dart", A_CON, "little dart", -10); + if (otmp->opoisoned) { + /* MRKR: Different kinds of poison */ + /* Stole effects from potionbreathe() */ + + switch (poison_type(otmp)) { + case OPOISON_SICKNESS: + poisoned("dart", A_CON, "little dart", -10); + break; + + case OPOISON_SLEEPING: + if (!Free_action && !Sleep_resistance) { + You_feel("rather tired."); + nomul(-rnd(5)); + nomovemsg = You_can_move_again; + exercise(A_DEX, FALSE); + } else { + You("yawn."); + } + break; + + case OPOISON_CONFUSION: + if(!Confusion) { + You_feel("somewhat dizzy."); + } + make_confused(HConfusion + rnd(5), FALSE); + break; + + case OPOISON_PARALYSIS: + if (!Free_action) { + pline("%s seems to be holding you.", Something); + nomul(-rnd(5)); + nomovemsg = You_can_move_again; + exercise(A_DEX, FALSE); + } else { + You("stiffen momentarily."); + } + break; + } + } obfree(otmp, (struct obj *)0); } else { place_object(otmp, u.ux, u.uy); @@ -1747,7 +1787,10 @@ otmp = mksobj(DART, TRUE, FALSE); otmp->quan = 1L; otmp->owt = weight(otmp); - if (!rn2(6)) otmp->opoisoned = 1; + if (!rn2(4)) { + otmp->opoisoned = 1; + otmp->opoistype = rn2(4); + } if (in_sight) seetrap(trap); if (thitm(7, mtmp, otmp, 0, FALSE)) trapkilled = TRUE; break; diff -Naur nethack-3.4.2/src/uhitm.c nethack-poison/src/uhitm.c --- nethack-3.4.2/src/uhitm.c 2003-08-30 10:07:42.000000000 +1000 +++ nethack-poison/src/uhitm.c 2003-10-16 22:00:06.000000000 +1000 @@ -892,6 +892,7 @@ } if (ispoisoned) { + int poison = poison_type(obj); int nopoison = (10 - (obj->owt/10)); if(nopoison < 2) nopoison = 2; if Role_if(PM_SAMURAI) { @@ -906,11 +907,46 @@ Your("%s %s no longer poisoned.", xname(obj), otense(obj, "are")); } - if (resists_poison(mon)) - needpoismsg = TRUE; - else if (rn2(10)) - tmp += rnd(6); - else poiskilled = TRUE; + + switch (poison) { + case OPOISON_SICKNESS: + if (resists_poison(mon)) { + needpoismsg = TRUE; + obj->opoistype |= OPOISON_KNOWN; + } + else if (rn2(10)) + tmp += rnd(6); + else { + poiskilled = TRUE; + obj->opoistype |= OPOISON_KNOWN; + } + + break; + + case OPOISON_SLEEPING: + if (rn2(4) && sleep_monst(mon, rnd(12), POTION_CLASS)) { + pline("%s falls asleep.", Monnam(mon)); + obj->opoistype |= OPOISON_KNOWN; + slept_monst(mon); + } + + break; + + case OPOISON_CONFUSION: + if(rn2(4) && !resist(mon, POTION_CLASS, 0, NOTELL)) { + mon->mconf = TRUE; + obj->opoistype |= OPOISON_KNOWN; + } + break; + + case OPOISON_PARALYSIS: + if (rn2(4) && mon->mcanmove) { + mon->mcanmove = 0; + mon->mfrozen = rnd(25); + obj->opoistype |= OPOISON_KNOWN; + } + break; + } } if (tmp < 1) { /* make sure that negative damage adjustment can't result diff -Naur nethack-3.4.2/src/zap.c nethack-poison/src/zap.c --- nethack-3.4.2/src/zap.c 2003-08-30 10:07:44.000000000 +1000 +++ nethack-poison/src/zap.c 2003-10-16 21:19:41.000000000 +1000 @@ -1289,8 +1289,10 @@ /* Keep chest/box traps and poisoned ammo if we may */ if (obj->otrapped && Is_box(otmp)) otmp->otrapped = TRUE; - if (obj->opoisoned && is_poisonable(otmp)) + if (obj->opoisoned && is_poisonable(otmp)) { otmp->opoisoned = TRUE; + otmp->opoistype = obj->opoistype; + } if (id == STRANGE_OBJECT && obj->otyp == CORPSE) { /* turn crocodile corpses into shoes */