diff -u -N -X files.exc nethack-3.4.3-orig/include/extern.h nethack-3.4.3-tricks/include/extern.h --- nethack-3.4.3-orig/include/extern.h Sun Dec 07 16:39:14 2003 +++ nethack-3.4.3-tricks/include/extern.h Thu Dec 11 10:46:08 2003 @@ -937,7 +937,7 @@ #ifdef GOLDOBJ E void FDECL(mkmonmoney, (struct monst *, long)); #endif -E void FDECL(bagotricks, (struct obj *)); +E int FDECL(bagotricks, (struct obj *)); E boolean FDECL(propagate, (int, BOOLEAN_P,BOOLEAN_P)); /* ### mapglyph.c ### */ diff -u -N -X files.exc nethack-3.4.3-orig/src/apply.c nethack-3.4.3-tricks/src/apply.c --- nethack-3.4.3-orig/src/apply.c Sun Dec 07 16:39:14 2003 +++ nethack-3.4.3-tricks/src/apply.c Thu Dec 11 10:44:22 2003 @@ -2832,7 +2832,7 @@ res = use_container(obj, 1); break; case BAG_OF_TRICKS: - bagotricks(obj); + res = bagotricks(obj); break; case CAN_OF_GREASE: use_grease(obj); diff -u -N -X files.exc nethack-3.4.3-orig/src/end.c nethack-3.4.3-tricks/src/end.c --- nethack-3.4.3-orig/src/end.c Sun Dec 07 16:39:14 2003 +++ nethack-3.4.3-tricks/src/end.c Thu Dec 11 10:44:22 2003 @@ -925,8 +925,8 @@ for (box = list; box; box = box->nobj) { if (Is_container(box) || box->otyp == STATUE) { - if (box->otyp == BAG_OF_TRICKS) { - continue; /* wrong type of container */ + if (box->otyp == BAG_OF_TRICKS && box->spe) { + continue; /* bag of tricks with charges can't contain anything */ } else if (box->cobj) { winid tmpwin = create_nhwindow(NHW_MENU); Sprintf(buf, "Contents of %s:", the(xname(box))); diff -u -N -X files.exc nethack-3.4.3-orig/src/makemon.c nethack-3.4.3-tricks/src/makemon.c --- nethack-3.4.3-orig/src/makemon.c Sun Dec 07 16:39:14 2003 +++ nethack-3.4.3-tricks/src/makemon.c Sat Feb 03 18:04:12 2007 @@ -1771,28 +1771,134 @@ mtmp->mappearance = appear; } -/* release a monster from a bag of tricks */ -void +/* Bag of Tricks now trickier ... nda 5/13/2003 */ +int bagotricks(bag) struct obj *bag; { if (!bag || bag->otyp != BAG_OF_TRICKS) { impossible("bad bag o' tricks"); } else if (bag->spe < 1) { - pline(nothing_happens); + return use_container(bag, 1); } else { - boolean gotone = FALSE; - int cnt = 1; + + boolean gotone = TRUE; + int cnt; + struct monst *mtmp; + struct obj *otmp; consume_obj_charge(bag, TRUE); - if (!rn2(23)) cnt += rn1(7, 1); - while (cnt-- > 0) { - if (makemon((struct permonst *)0, u.ux, u.uy, NO_MM_FLAGS)) - gotone = TRUE; + switch(rn2(20)) { + case 0: + case 1: + if(bag->recharged==0 && !bag->cursed) { + for(cnt=3;cnt>0 && (otmp = mkobj(RANDOM_CLASS,FALSE));cnt--) { + if(otmp->owt<100 && !objects[otmp->otyp].oc_big) + break; + obj_extract_self(otmp); + obfree(otmp, (struct obj *)0); + otmp = (struct obj*)0; + } + if(!otmp) { + pline_The("bag coughs nervously."); + break; + } + } else { + otmp = mksobj(IRON_CHAIN,FALSE,FALSE); + } + pline("%s spits %s out.", The(xname(bag)),something); + otmp = hold_another_object(otmp, "It slips away from you.", (char*)0, (char*)0); + break; + case 2: + pline_The("bag wriggles away from you!"); + dropx(bag); + break; + case 3: + nomul(-1*(rnd(4))); + if(Hallucination) { + You("start climbing into the bag."); + nomovemsg = "You give up your attempt to climb into the bag."; + } else { + pline("%s tries to pull you into the bag!",Something); + nomovemsg = "You manage to free yourself."; + } + break; + case 4: + if(Blind) + You_hear("a loud eructation."); + else + pline_The("bag belches out %s.", + Hallucination ? "the alphabet":"a noxious cloud"); + (void)create_gas_cloud(u.ux,u.uy,2,8); + break; + case 5: + if(Blind) { + if(breathless(youmonst.data)) + You_feel("a puff of air."); + else + You("smell a musty odor."); + } else { + pline_The("bag exhales of puff of spores."); + } + if(!breathless(youmonst.data)) + (void) make_hallucinated(HHallucination + rn1(35, 10),TRUE,0L); + break; + case 6: + pline_The("bag yells \"%s\".", Hallucination ? "!ooB":"Boo!"); + for(mtmp = fmon; mtmp; mtmp = mtmp->nmon) { + if (DEADMONSTER(mtmp)) continue; + if(cansee(mtmp->mx,mtmp->my)) { + if (! resist(mtmp, bag->oclass, 0, NOTELL)) + monflee(mtmp, 0, FALSE, FALSE); + } + } + if((ACURR(A_WIS)blessed) || bag->cursed) { + You("are startled into immobility."); + nomul(-1*rnd(3)); + nomovemsg = "You regain your composure."; + } + break; + case 7: + pline_The("bag develops a huge set of %s you!", + Hallucination ? "lips and kisses":"teeth and bites"); + cnt = rnd(10); + if (Half_physical_damage) cnt = (cnt+1) / 2; + losehp(cnt, Hallucination ? "amorous bag":"carnivorous bag", KILLED_BY_AN); + break; + case 8: + if(uwep || uswapwep) { + otmp = rn2(2) ? uwep : uswapwep; + if(!otmp) otmp = uwep ? uwep : uswapwep; + if(Blind) + pline("%s grabs %s away from you.", Something, yname(otmp)); + else + pline_The("bag sprouts a tongue and flicks %s %s.", + yname(otmp), + (Is_airlevel(&u.uz) || + Is_waterlevel(&u.uz) || + levl[u.ux][u.uy].typ < IRONBARS || + levl[u.ux][u.uy].typ >= ICE) ? + "away from you":"to the floor"); + dropx(otmp); + } else { + pline("%s licks your %s.", + Blind ? Something : "The bag sprouts a tongue and", + body_part(HAND)); + } + break; + default: + cnt = 1; + gotone = FALSE; + if (!rn2(23)) cnt += rn1(7, 1); + while (cnt-- > 0) { + if (makemon((struct permonst *)0, u.ux, u.uy, NO_MM_FLAGS)) + gotone = TRUE; + } } if (gotone) makeknown(BAG_OF_TRICKS); } + return 1; } #endif /* OVLB */ diff -u -N -X files.exc nethack-3.4.3-orig/src/mkobj.c nethack-3.4.3-tricks/src/mkobj.c --- nethack-3.4.3-orig/src/mkobj.c Sun Dec 07 16:39:14 2003 +++ nethack-3.4.3-tricks/src/mkobj.c Thu Dec 11 10:44:22 2003 @@ -502,7 +502,7 @@ blessorcurse(otmp, 2); break; case HORN_OF_PLENTY: - case BAG_OF_TRICKS: otmp->spe = rnd(20); + case BAG_OF_TRICKS: otmp->spe = rnd(30); break; case FIGURINE: { int tryct2 = 0; do diff -u -N -X files.exc nethack-3.4.3-orig/src/pickup.c nethack-3.4.3-tricks/src/pickup.c --- nethack-3.4.3-orig/src/pickup.c Sun Dec 07 16:39:14 2003 +++ nethack-3.4.3-tricks/src/pickup.c Thu Dec 11 10:44:22 2003 @@ -1549,13 +1549,14 @@ pline("Hmmm, it seems to be locked."); continue; } - if (cobj->otyp == BAG_OF_TRICKS) { + if (cobj->otyp == BAG_OF_TRICKS && cobj->spe>0) { int tmp; You("carefully open the bag..."); - pline("It develops a huge set of teeth and bites you!"); + pline("It develops a huge set of %s you!", + Hallucination ? "lips and kisses":"teeth and bites"); tmp = rnd(10); if (Half_physical_damage) tmp = (tmp+1) / 2; - losehp(tmp, "carnivorous bag", KILLED_BY_AN); + losehp(tmp, Hallucination ? "amorous bag":"carnivorous bag", KILLED_BY_AN); makeknown(BAG_OF_TRICKS); timepassed = 1; continue; diff -u -N -X files.exc nethack-3.4.3-orig/src/read.c nethack-3.4.3-tricks/src/read.c --- nethack-3.4.3-orig/src/read.c Sun Dec 07 16:39:14 2003 +++ nethack-3.4.3-tricks/src/read.c Thu Dec 11 10:44:22 2003 @@ -381,8 +381,36 @@ } else pline(nothing_happens); } break; - case HORN_OF_PLENTY: case BAG_OF_TRICKS: + /* if there are any objects inside the bag, devour them */ + if (!is_cursed) { + struct obj *curr, *otmp; + struct monst *shkp; + int lcnt = 0; + long loss = 0L; + + makeknown(BAG_OF_TRICKS); + for (curr = obj->cobj; curr; curr = otmp) { + otmp = curr->nobj; + obj_extract_self(curr); + lcnt++; + if (*u.ushops && (shkp = shop_keeper(*u.ushops)) != 0) { + if(curr->unpaid) + loss += stolen_value(curr, u.ux, u.uy, + (boolean)shkp->mpeaceful, TRUE); + } + /* obfree() will free all contained objects */ + obfree(curr, (struct obj *) 0); + } + + if(lcnt) + You_hear("loud crunching sounds from inside %s.", yname(obj)); + if (lcnt && loss) + You("owe %ld %s for lost item%s.", + loss, currency(loss), lcnt > 1 ? "s" : ""); + } + /* fall through */ + case HORN_OF_PLENTY: case CAN_OF_GREASE: if (is_cursed) stripspe(obj); else if (is_blessed) {