diff -ru nethack-3.4.3.orig/include/config.h nethack-3.4.3/include/config.h --- nethack-3.4.3.orig/include/config.h Sun Dec 7 18:39:13 2003 +++ nethack-3.4.3/include/config.h Fri May 27 15:40:43 2005 @@ -351,6 +351,16 @@ /*#define GOLDOBJ */ /* Gold is kept on obj chains - Helge Hafting */ /*#define AUTOPICKUP_EXCEPTIONS */ /* exceptions to autopickup */ +/* + * Drunken boxing: + * + * Make the monk have neat features when confused ("drunk"). + * Originally the idea of Stephen Crim. + * + * -- WXS + * wxs@csh.rit.edu +*/ +#define DRUNKEN_BOXING /* End of Section 5 */ #include "global.h" /* Define everything else according to choices above */ diff -ru nethack-3.4.3.orig/include/extern.h nethack-3.4.3/include/extern.h --- nethack-3.4.3.orig/include/extern.h Sun Dec 7 18:39:13 2003 +++ nethack-3.4.3/include/extern.h Fri Jun 3 23:02:00 2005 @@ -752,6 +752,7 @@ /* ### invent.c ### */ +E struct obj *FDECL(random_type, (int, struct monst *)); E void FDECL(assigninvlet, (struct obj *)); E struct obj *FDECL(merge_choice, (struct obj *,struct obj *)); E int FDECL(merged, (struct obj **,struct obj **)); diff -ru nethack-3.4.3.orig/src/dokick.c nethack-3.4.3/src/dokick.c --- nethack-3.4.3.orig/src/dokick.c Sun Dec 7 18:39:13 2003 +++ nethack-3.4.3/src/dokick.c Fri May 27 15:28:40 2005 @@ -121,6 +121,7 @@ register boolean clumsy = FALSE; register struct monst *mon = m_at(x, y); register int i, j; + int kc = 1; bhitpos.x = x; bhitpos.y = y; @@ -194,8 +195,16 @@ else if(uarm && objects[uarm->otyp].oc_bulky && ACURR(A_DEX) < rnd(25)) clumsy = TRUE; doit: - You("kick %s.", mon_nam(mon)); - if(!rn2(clumsy ? 3 : 4) && (clumsy || !bigmonst(mon->data)) && +#ifdef DRUNKEN_BOXING + if (drunkenboxing()) { + You ("deliver a flurry of sharp kicks!"); + kc = d(2, 2); /* 2 to 4 kicks (see d(n,x) in rnd.c) */ + } else +#endif /* DRUNKEN_BOXING */ + You("kick %s.", mon_nam(mon)); + + for (kc; kc >= 1; kc--) { + if(!rn2(clumsy ? 3 : 4) && (clumsy || !bigmonst(mon->data)) && mon->mcansee && !mon->mtrapped && !thick_skinned(mon->data) && mon->data->mlet != S_EEL && haseyes(mon->data) && mon->mcanmove && !mon->mstun && !mon->mconf && !mon->msleeping && @@ -224,6 +233,7 @@ return; } } + } } kickdmg(mon, clumsy); } diff -ru nethack-3.4.3.orig/src/invent.c nethack-3.4.3/src/invent.c --- nethack-3.4.3.orig/src/invent.c Sun Dec 7 18:39:13 2003 +++ nethack-3.4.3/src/invent.c Sat Jun 4 01:03:45 2005 @@ -85,6 +85,42 @@ /* note: assumes ASCII; toggling a bit puts lowercase in front of uppercase */ #define inv_rank(o) ((o)->invlet ^ 040) +/* Return a random item from the specified monster's inventory. */ +/* NOTE: This can be you or a monster. */ +/* Types are defined in include/objclass.h. */ +struct obj * +random_type(type, monster) +int type; +struct monst *monster; +{ + struct obj *otmp; + int count = 0, matches = 0; + int sel; + + if (!monster->minvent || type > MAXOCLASSES) + return(NULL); + + for (otmp = monster->minvent; otmp; otmp = otmp->nobj) { + count++; + if (otmp->oclass == type) + matches++; + } + + if (matches == 0) + return(NULL); + + sel = rnd(matches); + for (otmp = monster->minvent; otmp; otmp = otmp->nobj) { + if (otmp->oclass == type) { + sel--; + if (sel == 0) + break; + } + } + + return(otmp); +} + /* sort the inventory; used by addinv() and doorganize() */ STATIC_OVL void reorder_invent() diff -ru nethack-3.4.3.orig/src/mon.c nethack-3.4.3/src/mon.c --- nethack-3.4.3.orig/src/mon.c Sun Dec 7 18:39:13 2003 +++ nethack-3.4.3/src/mon.c Thu Jun 30 21:39:33 2005 @@ -317,6 +317,16 @@ obj->oinvis = mtmp->minvis; #endif +#ifdef DRUNKEN_BOXING + /* 1/20 chance to grab the corpse as it's falling. */ + int chance = rnd(20); + if (chance == 1) { + obj_extract_self(obj); + hold_another_object(obj, "You try to catch %s but drop it.", doname(obj), "You catch and wield a "); + setuwep(obj); + } +#endif /* DRUNKEN_BOXING */ + stackobj(obj); newsym(x, y); return obj; diff -ru nethack-3.4.3.orig/src/uhitm.c nethack-3.4.3/src/uhitm.c --- nethack-3.4.3.orig/src/uhitm.c Sun Dec 7 18:39:13 2003 +++ nethack-3.4.3/src/uhitm.c Fri Jul 1 10:25:22 2005 @@ -29,6 +29,21 @@ #define PROJECTILE(obj) ((obj) && is_ammo(obj)) +#ifdef DRUNKEN_BOXING +/* Drunken Boxing non-damage conditions */ +#define DRUNK_THEFT 1 +#define DRUNK_BLIND 2 +#define DRUNK_ENTANGLE 3 +#define DRUNK_THROW 4 +/* + * This should always be the last item, and should be increased + * when adding a new drunken boxing outcome. + */ +#define DRUNK_NOTHING 4 + +#define BLIND_TIME 25 /* Must be less than 127 (mon->mblinded is only 7 bits) */ +#endif /* DRUNKEN_BOXING */ + /* modified from hurtarmor() in mhitu.c */ /* This is not static because it is also used for monsters rusting monsters */ void @@ -408,6 +423,24 @@ return(TRUE); } +#ifdef DRUNKEN_BOXING +boolean +drunkenboxing() +{ + /* + * Drunken Boxing: + * Monks are the only class that can reach GRAND MASTER + * status for Martial Arts (Bare Handed Combat), so we + * don't have to explictly check if the player is a monk + * using Role_if(PM_MONK). + * + * -- WXS + * wxs@csh.rit.edu + */ + return(Confusion && !uwep && u.weapon_skills[P_MARTIAL_ARTS].skill == P_GRAND_MASTER && !Upolyd); +} +#endif /* DRUNKEN_BOXING */ + STATIC_OVL boolean known_hitum(mon, mhit, uattk) /* returns TRUE if monster still lives */ register struct monst *mon; @@ -415,6 +448,7 @@ struct attack *uattk; { register boolean malive = TRUE; + int chance; if (override_confirmation) { /* this may need to be generalized if weapons other than @@ -465,6 +499,86 @@ cutworm(mon, x, y, uwep); } } + +#ifdef DRUNKEN_BOXING + /* Don't do these on pets, or on dead things. */ + if (drunkenboxing() && !mon->mtame && malive && *mhit) { + int tmp; + char msg[BUFSZ]; + struct obj *dbobj; + struct monst *mtmp; + + /* You get a 1/4 chance to do *something* when attacking. */ + chance = rnd((DRUNK_NOTHING - 1) * 4); + chance = DRUNK_THROW; /* Debug. */ + switch(chance) { + case DRUNK_THEFT: + Sprintf(msg, "Siezing an opportunity, you rifle through the %s's pack!", mon->data->mname); + dbobj = display_minventory(mon, MINV_ALL, msg); + if (dbobj) { + if (!dbobj->owornmask) { + /* + * Free it from the monster's inventory + * chain before we add it to the + * hero's. Don't use steal_it() as + * that is too complicated for our + * purposes. + */ + obj_extract_self(dbobj); + hold_another_object(dbobj, "You stole but dropped %s.", doname(dbobj), "You stole a "); + } + else + You("can't steal that item."); + } + else + You("stole nothing."); + + return(malive); + break; + case DRUNK_BLIND: + if (can_blnd(&youmonst, mon, AT_CLAW, NULL)) { + You("poke the %s in the eye for good measure.", mon->data->mname); + mon->mcansee = 0; + tmp = rn1(25, 21); + /* + * Continuous blinding strikes + * accumulate, but never more + * than 127. + */ + if(((int) mon->mblinded + tmp) > 127) + mon->mblinded = 127; + else + mon->mblinded += tmp; + } + else + You("try to poke the %s in the eye, but can't.", mon->data->mname); + + return(malive); + break; + case DRUNK_ENTANGLE: + dbobj = random_type(ARMOR_CLASS, mon); + if (dbobj) { + if (dbobj->owornmask) { + pline("You grapple with the %s and remove %s.", mon->data->mname, doname(dbobj)); + update_mon_intrinsics(mon, dbobj, FALSE, FALSE); + dbobj->owornmask = 0L; + } + } + else + pline("You attempt to disrobe the %s but fail.", mon->data->mname); + + return(malive); + break; + case DRUNK_THROW: + pline ("DRUNK THROW!"); + remove_monster(mon->mx, mon->my); + pline ("REMOVED!"); + place_monster(mtmp, u.ux, u.uy); + break; + } + } +#endif /* DRUNKEN_BOXING */ + return(malive); }