diff -Naur -x Makefile nethack-3.4.0/CHANGES-mirror-of-entrapment nethack-mirror/CHANGES-mirror-of-entrapment --- nethack-3.4.0/CHANGES-mirror-of-entrapment Thu Jan 1 10:00:00 1970 +++ nethack-mirror/CHANGES-mirror-of-entrapment Sun Jun 30 18:14:36 2002 @@ -0,0 +1,40 @@ +Implementation notes for Mirror of Entrapment +--------------------------------------------- + +30/6/02: + +* objects.c + + Added mirror of entrapment, slightly descreasing probability of + ordinary mirror to compensate. Made it charged and magical. + +* apply.c + + Applying mirror on self causes paralysis. + Applying mirror on a monster sucks it into the mirror. + +* mkobj.c + + Mirrors initially have 6-12 charges. + +* mkobj.c mkmaze.c mklev.c mon.c trap.c + + Changed mkcorpstat to take a 'where' parameter. + Currently only either OBJ_FREE or OBJ_FLOOR are + acceptable. + All previous calls now have added OBJ_FLOOR. + +* dokick.c dothrow.c extern.h uhitm.c + + Whenever a mirror shatters, call release_entrapped_monsters() + to release the baddies. + +* invent.c + + Allow "invocation" of mirrors of entrapment (does nothing). + +* shk.c + + Shopkeepers no longer id mirrors for you. + + diff -Naur -x Makefile nethack-3.4.0/include/extern.h nethack-mirror/include/extern.h --- nethack-3.4.0/include/extern.h Thu Mar 21 10:42:46 2002 +++ nethack-mirror/include/extern.h Sun Jun 30 17:33:26 2002 @@ -42,6 +42,7 @@ E boolean FDECL(wield_tool, (struct obj *)); E boolean FDECL(um_dist, (XCHAR_P,XCHAR_P,XCHAR_P)); E boolean FDECL(snuff_candle, (struct obj *)); +E void FDECL(release_entrapped_monsters, (struct obj *)); E boolean FDECL(snuff_lit, (struct obj *)); E boolean FDECL(catch_lit, (struct obj *)); E void FDECL(use_unicorn_horn, (struct obj *)); @@ -1013,7 +1014,7 @@ E int FDECL(weight, (struct obj *)); E struct obj *FDECL(mkgold, (long,int,int)); E struct obj *FDECL(mkcorpstat, - (int,struct monst *,struct permonst *,int,int,BOOLEAN_P)); + (int,struct monst *,struct permonst *,xchar,int,int,BOOLEAN_P)); E struct obj *FDECL(obj_attach_mid, (struct obj *, unsigned)); E struct monst *FDECL(get_mtraits, (struct obj *, BOOLEAN_P)); E struct obj *FDECL(mk_tt_object, (int,int,int)); diff -Naur -x Makefile nethack-3.4.0/src/apply.c nethack-mirror/src/apply.c --- nethack-3.4.0/src/apply.c Thu Mar 21 10:43:00 2002 +++ nethack-mirror/src/apply.c Sun Jun 30 18:02:16 2002 @@ -7,9 +7,13 @@ #ifdef OVLB -static const char tools[] = { TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, 0 }; +static const char tools[] = { TOOL_CLASS, WEAPON_CLASS, WAND_CLASS, + FOOD_CLASS, + 0 }; static const char tools_too[] = { ALL_CLASSES, TOOL_CLASS, POTION_CLASS, - WEAPON_CLASS, WAND_CLASS, GEM_CLASS, 0 }; + WEAPON_CLASS, WAND_CLASS, GEM_CLASS, + FOOD_CLASS, + 0 }; #ifdef TOURIST STATIC_DCL int FDECL(use_camera, (struct obj *)); @@ -21,6 +25,7 @@ STATIC_DCL void FDECL(use_magic_whistle, (struct obj *)); STATIC_DCL void FDECL(use_leash, (struct obj *)); STATIC_DCL int FDECL(use_mirror, (struct obj *)); +STATIC_DCL int FDECL(entrap_monster, (struct obj *, struct monst *)); STATIC_DCL void FDECL(use_bell, (struct obj *)); STATIC_DCL void FDECL(use_candelabrum, (struct obj *)); STATIC_DCL void FDECL(use_candle, (struct obj *)); @@ -325,7 +330,9 @@ if (mintrap(mtmp) == 2) change_luck(-1); } } - if (pet_cnt > 0) makeknown(MAGIC_WHISTLE); + if (pet_cnt > 0 && obj->otyp == MAGIC_WHISTLE) { + makeknown(MAGIC_WHISTLE); + } } } @@ -642,6 +649,33 @@ } else You("stiffen momentarily under your gaze."); } else if (youmonst.data->mlet == S_VAMPIRE) You("don't have a reflection."); + else if (obj->otyp == MIRROR_OF_ENTRAPMENT) { + if (Antimagic) { + You("resist the mirror's charms."); + } + else { + if (Hallucination) { + switch (poly_gender()) { + case 0: + pline("Huh? Who is that guy?"); + break; + case 1: + pline("Huh? Who is that gal?"); + break; + default: + pline("Huh? Who is that creature?"); + break; + } + } + else { + You("are captivated by your %s.", + (ACURR(A_CHA) > 14 ? "beauty" : + (ACURR(A_CHA) < 9 ? "ugliness" : + "reflection"))); + } + nomul(-rnd(ACURR(A_CHA))*4); + } + } else if (u.umonnum == PM_UMBER_HULK) { pline("Huh? That doesn't look like you!"); make_confused(HConfusion + d(3,4),FALSE); @@ -720,6 +754,8 @@ if ( (int) mtmp->mfrozen + tmp > 127) mtmp->mfrozen = 127; else mtmp->mfrozen += tmp; + } else if (!mtmp->minvis && obj->otyp == MIRROR_OF_ENTRAPMENT) { + entrap_monster(obj, mtmp); } else if(!mtmp->mcan && !mtmp->minvis && mtmp->data == &mons[PM_UMBER_HULK]) { if (vis) @@ -754,6 +790,73 @@ return 1; } +STATIC_OVL int +entrap_monster(obj, mtmp) +register struct obj *obj; +register struct monst *mtmp; +{ + struct obj *corpse; + + if (obj->spe > 0) { + int charges_used = mtmp->m_lev*2 + 1; + + setmangry(mtmp); + + if (!resists_magm(mtmp) && rn2(charges_used) < obj->spe) { + + obj->spe -= charges_used; + if (obj->spe < 0) obj->spe = 0; + + pline("%s is sucked into the mirror!", Monnam(mtmp)); + xkilled(mtmp, 2); /* don't print message or create a corpse */ + + if (mtmp->mhp > 0) { + /* Its life was saved */ + return 0; + } + + /* Store monsters in the mirror, for later revival. */ + corpse = mkcorpstat(CORPSE, mtmp, mtmp->data, OBJ_FREE, 0, 0, TRUE); + add_to_container(obj, corpse); + + return 1; + } + else { + pline("%s resists the mirror's charms.", Monnam(mtmp)); + /* remove a charge to stop the player trying repeatedly */ + obj->spe--; + return 0; + } + } + else { + pline_The("mirror is full."); // FIXME: Something more appropriate + return 0; + } +} + +void +release_entrapped_monsters(obj) +register struct obj *obj; +{ + struct obj *curr; + struct obj *otmp; + + pline("obj->where = %d, obj->ox = %d, obj->oy = %d", + obj->where, obj->ox, obj->oy); + + for (curr = obj->cobj; curr; curr = otmp) { + otmp = curr->nobj; + + if (curr->otyp == CORPSE) { + revive(curr); + } + else { + impossible("How did %s get in here?", an(xname(curr))); + obfree(curr, (struct obj *) 0); + } + } +} + STATIC_OVL void use_bell(obj) register struct obj *obj; @@ -2706,10 +2809,20 @@ case TIN_WHISTLE: use_whistle(obj); break; + case EUCALYPTUS_LEAF: + /* MRKR: Every Australian knows that a gum leaf makes an */ + /* excellent whistle, especially if your pet is a */ + /* tame kangaroo named Skippy. */ + if (obj->blessed) + use_magic_whistle(obj); + else + use_whistle(obj); + break; case STETHOSCOPE: res = use_stethoscope(obj); break; case MIRROR: + case MIRROR_OF_ENTRAPMENT: res = use_mirror(obj); break; case BELL: @@ -2872,3 +2985,8 @@ #endif /* OVLB */ /*apply.c*/ + + + + + diff -Naur -x Makefile nethack-3.4.0/src/dokick.c nethack-mirror/src/dokick.c --- nethack-3.4.0/src/dokick.c Thu Mar 21 10:43:04 2002 +++ nethack-mirror/src/dokick.c Sun Jun 30 16:48:46 2002 @@ -431,6 +431,7 @@ if (result) { if (otmp->otyp == MIRROR) change_luck(-2); + /* eggs laid by you */ /* penalty is -1 per egg, max 5, but it's always exactly 1 that breaks */ @@ -439,6 +440,11 @@ You_hear("a muffled %s.",result); if(costly) loss += stolen_value(otmp, x, y, (boolean)shkp->mpeaceful, TRUE); + + if (otmp->otyp == MIRROR_OF_ENTRAPMENT) { + release_entrapped_monsters(otmp); + } + if (otmp->quan > 1L) useup(otmp); else { @@ -1302,6 +1308,10 @@ result = "splat"; } You_hear("a muffled %s.",result); + if (otmp->otyp == MIRROR_OF_ENTRAPMENT) { + release_entrapped_monsters(otmp); + } + obj_extract_self(otmp); obfree(otmp, (struct obj *) 0); return TRUE; diff -Naur -x Makefile nethack-3.4.0/src/dothrow.c nethack-mirror/src/dothrow.c --- nethack-3.4.0/src/dothrow.c Thu Mar 21 10:43:04 2002 +++ nethack-mirror/src/dothrow.c Sun Jun 30 17:49:58 2002 @@ -1495,6 +1495,18 @@ if (heros_fault) change_luck(-2); break; + case MIRROR_OF_ENTRAPMENT: { + /* MRKR: Temporarilty put the mirror on the floor */ + /* so we know where to release the monsters */ + xchar where = obj->where; + + obj->ox = x; + obj->oy = y; + obj->where = OBJ_FLOOR; + release_entrapped_monsters(obj); + obj->where = where; + break; + } case POT_WATER: /* really, all potions */ if (obj->otyp == POT_OIL && obj->lamplit) { splatter_burning_oil(x,y); @@ -1593,6 +1605,7 @@ case CRYSTAL_PLATE_MAIL: case LENSES: case MIRROR: + case MIRROR_OF_ENTRAPMENT: case CRYSTAL_BALL: #ifdef TOURIST case EXPENSIVE_CAMERA: diff -Naur -x Makefile nethack-3.4.0/src/invent.c nethack-mirror/src/invent.c --- nethack-3.4.0/src/invent.c Thu Mar 21 10:43:08 2002 +++ nethack-mirror/src/invent.c Sun Jun 30 16:50:58 2002 @@ -834,6 +834,8 @@ /* Picks, axes, pole-weapons, bullwhips */ ((otmp->oclass == WEAPON_CLASS && !is_pick(otmp) && !is_pole(otmp) && otyp != BULLWHIP) + || (otmp->oclass == FOOD_CLASS && + otmp->otyp != EUCALYPTUS_LEAF) || (otmp->oclass == POTION_CLASS && /* only applicable potion is oil, and it will only be offered as a choice when already discovered */ @@ -846,7 +848,8 @@ otyp != CRYSTAL_BALL && /* #invoke synonym for apply */ /* note: presenting the possibility of invoking non-artifact mirrors and/or lamps is a simply a cruel deception... */ - otyp != MIRROR && otyp != MAGIC_LAMP && + otyp != MIRROR && otyp != MIRROR_OF_ENTRAPMENT && + otyp != MAGIC_LAMP && (otyp != OIL_LAMP || /* don't list known oil lamp */ (otmp->dknown && objects[OIL_LAMP].oc_name_known)))) || (!strcmp(word, "untrap with") && diff -Naur -x Makefile nethack-3.4.0/src/mklev.c nethack-mirror/src/mklev.c --- nethack-3.4.0/src/mklev.c Thu Mar 21 10:43:10 2002 +++ nethack-mirror/src/mklev.c Sun Jun 30 16:00:50 2002 @@ -790,7 +790,7 @@ /* put statues inside */ if(!rn2(20)) (void) mkcorpstat(STATUE, (struct monst *)0, - (struct permonst *)0, + (struct permonst *)0, OBJ_FLOOR, somex(croom), somey(croom), TRUE); /* put box/chest inside; * 40% chance for at least 1 box, regardless of number diff -Naur -x Makefile nethack-3.4.0/src/mkmaze.c nethack-mirror/src/mkmaze.c --- nethack-3.4.0/src/mkmaze.c Thu Mar 21 10:43:10 2002 +++ nethack-mirror/src/mkmaze.c Sun Jun 30 16:01:02 2002 @@ -426,7 +426,7 @@ otmp = mk_tt_object(STATUE, somex(croom), somey(croom)); else /* Medusa statues don't contain books */ otmp = mkcorpstat(STATUE, (struct monst *)0, (struct permonst *)0, - somex(croom), somey(croom), FALSE); + OBJ_FLOOR, somex(croom), somey(croom), FALSE); if (otmp) { while (pm_resistance(&mons[otmp->corpsenm],MR_STONE) || poly_when_stoned(&mons[otmp->corpsenm])) { diff -Naur -x Makefile nethack-3.4.0/src/mkobj.c nethack-mirror/src/mkobj.c --- nethack-3.4.0/src/mkobj.c Thu Mar 21 10:43:10 2002 +++ nethack-mirror/src/mkobj.c Sun Jun 30 16:01:52 2002 @@ -520,6 +520,9 @@ case DRUM_OF_EARTHQUAKE: otmp->spe = rn1(5,4); break; + case MIRROR_OF_ENTRAPMENT: + otmp->spe = rn1(7, 6); + break; } break; case AMULET_CLASS: @@ -886,10 +889,11 @@ * resurrection. */ struct obj * -mkcorpstat(objtype, mtmp, ptr, x, y, init) +mkcorpstat(objtype, mtmp, ptr, where, x, y, init) int objtype; /* CORPSE or STATUE */ struct monst *mtmp; struct permonst *ptr; +xchar where; int x, y; boolean init; { @@ -897,7 +901,20 @@ if (objtype != CORPSE && objtype != STATUE) impossible("making corpstat type %d", objtype); - otmp = mksobj_at(objtype, x, y, init, FALSE); + + otmp = mksobj(objtype, init, FALSE); + + switch (where) { + case OBJ_FREE: + break; + case OBJ_FLOOR: + place_object(otmp, x, y); + break; + default: + impossible("mkcorpstat: where = %d", where); + break; + } + if (otmp) { if (mtmp) { struct obj *otmp2; @@ -1037,7 +1054,7 @@ struct obj *otmp; otmp = mkcorpstat(objtype, (struct monst *)0, ptr, - x, y, (boolean)(objtype != STATUE)); + OBJ_FLOOR, x, y, (boolean)(objtype != STATUE)); if (nm) otmp = oname(otmp, nm); return(otmp); diff -Naur -x Makefile nethack-3.4.0/src/mon.c nethack-mirror/src/mon.c --- nethack-3.4.0/src/mon.c Thu Mar 21 10:43:10 2002 +++ nethack-mirror/src/mon.c Sun Jun 30 15:59:30 2002 @@ -167,7 +167,7 @@ case PM_VAMPIRE_LORD: /* include mtmp in the mkcorpstat() call */ num = undead_to_corpse(mndx); - obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, TRUE); + obj = mkcorpstat(CORPSE, mtmp, &mons[num], OBJ_FLOOR, x, y, TRUE); obj->age -= 100; /* this is an *OLD* corpse */ break; case PM_KOBOLD_MUMMY: @@ -187,7 +187,7 @@ case PM_GIANT_ZOMBIE: case PM_ETTIN_ZOMBIE: num = undead_to_corpse(mndx); - obj = mkcorpstat(CORPSE, mtmp, &mons[num], x, y, TRUE); + obj = mkcorpstat(CORPSE, mtmp, &mons[num], OBJ_FLOOR, x, y, TRUE); obj->age -= 100; /* this is an *OLD* corpse */ break; case PM_IRON_GOLEM: @@ -210,7 +210,7 @@ break; case PM_STONE_GOLEM: obj = mkcorpstat(STATUE, (struct monst *)0, - mdat, x, y, FALSE); + mdat, OBJ_FLOOR, x, y, FALSE); break; case PM_WOOD_GOLEM: num = d(2,4); @@ -242,7 +242,7 @@ return (struct obj *)0; else /* preserve the unique traits of some creatures */ obj = mkcorpstat(CORPSE, KEEPTRAITS(mtmp) ? mtmp : 0, - mdat, x, y, TRUE); + mdat, OBJ_FLOOR, x, y, TRUE); break; } /* All special cases should precede the G_NOCORPSE check */ @@ -453,6 +453,7 @@ mcalcdistress() { struct monst *mtmp; + int mndx; for (mtmp = fmon; mtmp; mtmp = mtmp->nmon) { if (DEADMONSTER(mtmp)) continue; @@ -473,6 +474,33 @@ if (mtmp->mfleetim && !--mtmp->mfleetim) mtmp->mflee = 0; + /* MRKR: Healthy molds spread */ + + mndx = monsndx(mtmp->data); + + if ((mndx == PM_YELLOW_MOLD || mndx == PM_RED_MOLD + || mndx == PM_BROWN_MOLD || mndx == PM_GREEN_MOLD) + && mtmp->mhp == mtmp->mhpmax && !rn2(100)) { + /* The clone will be added to the beginning of */ + /* the list, so will not be processed in this loop */ + + int x,y; + boolean space = 0; + + /* Only clone if there is empty space nearby */ + + for (x = -1; x <= 1; x++) { + for (y = -1; y <= 1; y++) { + if (x == 0 && y == 0) continue; + if (goodpos(mtmp->mx+x, mtmp->my+y, mtmp)) { + space++; + } + } + } + if (rn2(8) < space) clone_mon(mtmp); + } + + /* FIXME: mtmp->mlstmv ought to be updated here */ } } @@ -1516,7 +1544,7 @@ if ((int)mdef->data->msize > MZ_TINY || !rn2(2 + ((int) (mdef->data->geno & G_FREQ) > 2))) { otmp = mkcorpstat(STATUE, KEEPTRAITS(mdef) ? mdef : 0, - mdef->data, x, y, FALSE); + mdef->data, OBJ_FLOOR, x, y, FALSE); if (mdef->mnamelth) otmp = oname(otmp, NAME(mdef)); /* some objects may end up outside the statue */ while ((obj = mdef->minvent) != 0) { diff -Naur -x Makefile nethack-3.4.0/src/objects.c nethack-mirror/src/objects.c --- nethack-3.4.0/src/objects.c Thu Mar 21 10:43:12 2002 +++ nethack-mirror/src/objects.c Sun Jun 30 14:07:36 2002 @@ -601,10 +601,12 @@ #ifdef TOURIST TOOL("expensive camera", (char *)0, 1, 0, 0, 1, 15, 12, 200, PLASTIC, CLR_BLACK), -TOOL("mirror", "looking glass", 0, 0, 0, 0, 45, 13, 10, GLASS, HI_SILVER), +TOOL("mirror", "looking glass", 0, 0, 0, 0, 40, 13, 10, GLASS, HI_SILVER), #else -TOOL("mirror", "looking glass", 0, 0, 0, 0, 60, 13, 10, GLASS, HI_SILVER), +TOOL("mirror", "looking glass", 0, 0, 0, 0, 55, 13, 10, GLASS, HI_SILVER), #endif +TOOL("mirror of entrapment", "looking glass", + 0, 0, 1, 1, 5, 13, 200, GLASS, HI_SILVER), TOOL("crystal ball", "glass orb", 0, 0, 1, 1, 15,150, 60, GLASS, HI_GLASS), TOOL("lenses", (char *)0, 1, 0, 0, 0, 5, 3, 80, GLASS, HI_GLASS), diff -Naur -x Makefile nethack-3.4.0/src/shk.c nethack-mirror/src/shk.c --- nethack-3.4.0/src/shk.c Thu Mar 21 10:43:18 2002 +++ nethack-mirror/src/shk.c Sun Jun 30 16:59:48 2002 @@ -2121,8 +2121,7 @@ */ if (!objects[obj->otyp].oc_magic && saleable(shkp, obj) && (obj->oclass == WEAPON_CLASS || obj->oclass == ARMOR_CLASS || - obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS || - obj->otyp == MIRROR)) { + obj->oclass == SCROLL_CLASS || obj->oclass == SPBOOK_CLASS)) { was_unknown |= !objects[obj->otyp].oc_name_known; makeknown(obj->otyp); } diff -Naur -x Makefile nethack-3.4.0/src/trap.c nethack-mirror/src/trap.c --- nethack-3.4.0/src/trap.c Thu Mar 21 10:43:20 2002 +++ nethack-mirror/src/trap.c Sun Jun 30 16:00:14 2002 @@ -258,7 +258,8 @@ struct obj *otmp, *statue; statue = mkcorpstat(STATUE, (struct monst *)0, - &mons[rndmonnum()], x, y, FALSE); + &mons[rndmonnum()], OBJ_FLOOR, + x, y, FALSE); mtmp = makemon(&mons[statue->corpsenm], 0, 0, NO_MM_FLAGS); if (!mtmp) break; /* should never happen */ while(mtmp->minvent) { diff -Naur -x Makefile nethack-3.4.0/src/uhitm.c nethack-mirror/src/uhitm.c --- nethack-3.4.0/src/uhitm.c Thu Mar 21 10:43:20 2002 +++ nethack-mirror/src/uhitm.c Sun Jun 30 17:02:16 2002 @@ -673,6 +673,18 @@ } tmp = 1; break; + + case MIRROR_OF_ENTRAPMENT: + if (breaktest(obj)) { + You("break %s mirror.", + shk_your(yourbuf, obj)); + release_entrapped_monsters(obj); + useup(obj); + obj = (struct obj *) 0; + hittxt = TRUE; + } + tmp = 1; + break; #ifdef TOURIST case EXPENSIVE_CAMERA: You("succeed in destroying %s camera. Congratulations!",