diff -Naur nethack-3.4.3/include/decl.h nethack-patched/include/decl.h --- nethack-3.4.3/include/decl.h 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/include/decl.h 2005-02-28 12:47:13.000000000 +1100 @@ -260,6 +260,9 @@ #endif E NEARDATA struct monst youmonst; /* init'd and defined in decl.c */ +#ifdef PARTIAL_XP +E NEARDATA struct monst *responsible; /* defined in decl.c */ +#endif E NEARDATA struct monst *mydogs, *migrating_mons; E NEARDATA struct mvitals { diff -Naur nethack-3.4.3/include/extern.h nethack-patched/include/extern.h --- nethack-3.4.3/include/extern.h 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/include/extern.h 2005-02-28 12:47:13.000000000 +1100 @@ -584,6 +584,10 @@ E int FDECL(experience, (struct monst *,int)); E void FDECL(more_experienced, (int,int)); +#ifdef PARTIAL_XP +E void FDECL(grant_experience, (struct monst *)); +E void FDECL(grant_partial_experience, (struct monst *,int,int)); +#endif E void FDECL(losexp, (const char *)); E void NDECL(newexplevel); E void FDECL(pluslvl, (BOOLEAN_P)); @@ -956,6 +960,10 @@ E int FDECL(noattacks, (struct permonst *)); E int FDECL(sleep_monst, (struct monst *,int,int)); E void FDECL(slept_monst, (struct monst *)); +#ifdef PARTIAL_XP +E int FDECL(confuse_monst, (struct monst *)); +E int FDECL(stun_monst, (struct monst *)); +#endif E long FDECL(attk_protection, (int)); /* ### mhitu.c ### */ diff -Naur nethack-3.4.3/include/monst.h nethack-patched/include/monst.h --- nethack-3.4.3/include/monst.h 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/include/monst.h 2005-02-28 12:47:13.000000000 +1100 @@ -137,7 +137,12 @@ struct obj *mw; long misc_worn_check; +#ifndef PARTIAL_XP xchar weapon_check; +#else + xchar weapon_check; + int exp_granted; /* XP already granted */ +#endif uchar mnamelth; /* length of name (following mxlth) */ short mxlth; /* length of following data */ diff -Naur nethack-3.4.3/src/allmain.c nethack-patched/src/allmain.c --- nethack-3.4.3/src/allmain.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/allmain.c 2005-02-28 12:47:13.000000000 +1100 @@ -60,6 +60,11 @@ youmonst.movement = NORMAL_SPEED; /* give the hero some movement points */ for(;;) { +#ifdef PARTIAL_XP + /* MRKR: The hero is responsible for actions */ + responsible = &youmonst; + +#endif get_nh_event(); #ifdef POSITIONBAR do_positionbar(); diff -Naur nethack-3.4.3/src/apply.c nethack-patched/src/apply.c --- nethack-3.4.3/src/apply.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/apply.c 2005-02-28 12:47:13.000000000 +1100 @@ -710,7 +710,11 @@ mtmp->data == &mons[PM_UMBER_HULK]) { if (vis) pline ("%s confuses itself!", Monnam(mtmp)); +#ifndef PARTIAL_XP mtmp->mconf = 1; +#else + confuse_monst(mtmp); +#endif } else if(!mtmp->mcan && !mtmp->minvis && (mlet == S_NYMPH || mtmp->data==&mons[PM_SUCCUBUS])) { if (vis) { diff -Naur nethack-3.4.3/src/artifact.c nethack-patched/src/artifact.c --- nethack-3.4.3/src/artifact.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/artifact.c 2005-02-28 12:47:13.000000000 +1100 @@ -889,7 +889,11 @@ if (youdefend) make_stunned((HStun + 3), FALSE); else +#ifndef PARTIAL_XP mdef->mstun = 1; +#else + stun_monst(mdef); +#endif /* avoid extra stun message below if we used mb_verb["stun"] above */ if (attack_indx == MB_INDEX_STUN) do_stun = FALSE; } @@ -899,7 +903,11 @@ if (youdefend) make_confused(HConfusion + 4, FALSE); else +#ifndef PARTIAL_XP mdef->mconf = 1; +#else + confuse_monst(mdef); +#endif } if (youattack || youdefend || vis) { diff -Naur nethack-3.4.3/src/bones.c nethack-patched/src/bones.c --- nethack-3.4.3/src/bones.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/bones.c 2005-02-28 12:47:13.000000000 +1100 @@ -296,6 +296,9 @@ resetobjs(mtmp->minvent,FALSE); /* do not zero out m_ids for bones levels any more */ mtmp->mlstmv = 0L; +#ifdef PARTIAL_XP + mtmp->exp_granted = 0; +#endif if(mtmp->mtame) mtmp->mtame = mtmp->mpeaceful = 0; } for(ttmp = ftrap; ttmp; ttmp = ttmp->ntrap) { diff -Naur nethack-3.4.3/src/decl.c nethack-patched/src/decl.c --- nethack-3.4.3/src/decl.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/decl.c 2005-02-28 12:47:13.000000000 +1100 @@ -143,6 +143,10 @@ NEARDATA struct flag flags = DUMMY; NEARDATA struct instance_flags iflags = DUMMY; NEARDATA struct you u = DUMMY; +#ifdef PARTIAL_XP +/* MRKR: who's repsonsible for the current action */ +NEARDATA struct monst *responsible = (struct monst*)0; +#endif NEARDATA struct obj *invent = (struct obj *)0, *uwep = (struct obj *)0, *uarm = (struct obj *)0, diff -Naur nethack-3.4.3/src/dogmove.c nethack-patched/src/dogmove.c --- nethack-3.4.3/src/dogmove.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/dogmove.c 2005-02-28 12:47:13.000000000 +1100 @@ -177,7 +177,11 @@ if (mtmp->data == &mons[PM_RUST_MONSTER] && obj->oerodeproof) { /* The object's rustproofing is gone now */ obj->oerodeproof = 0; +#ifndef PARTIAL_XP mtmp->mstun = 1; +#else + stun_monst(mtmp); +#endif if (canseemon(mtmp) && flags.verbose) { pline("%s spits %s out in disgust!", Monnam(mtmp), distant_name(obj,doname)); @@ -221,7 +225,11 @@ } else if (!edog->mhpmax_penalty) { /* starving pets are limited in healing */ int newmhpmax = mtmp->mhpmax / 3; +#ifndef PARTIAL_XP mtmp->mconf = 1; +#else + confuse_monst(mtmp); +#endif edog->mhpmax_penalty = mtmp->mhpmax - newmhpmax; mtmp->mhpmax = newmhpmax; if (mtmp->mhp > mtmp->mhpmax) diff -Naur nethack-3.4.3/src/dothrow.c nethack-patched/src/dothrow.c --- nethack-3.4.3/src/dothrow.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/dothrow.c 2005-02-28 12:47:13.000000000 +1100 @@ -655,7 +655,11 @@ /* At the very least, debilitate the monster */ mon->movement = 0; +#ifndef PARTIAL_XP mon->mstun = 1; +#else + stun_monst(mon); +#endif /* Is the monster stuck or too heavy to push? * (very large monsters have too much inertia, even floaters and flyers) diff -Naur nethack-3.4.3/src/exper.c nethack-patched/src/exper.c --- nethack-3.4.3/src/exper.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/exper.c 2005-02-28 12:47:13.000000000 +1100 @@ -91,10 +91,45 @@ /* Mail daemons put up no fight. */ if(mtmp->data == &mons[PM_MAIL_DAEMON]) tmp = 1; #endif +#ifdef PARTIAL_XP + /* MRKR: subtract any XP already granted */ + tmp -= mtmp->exp_granted; + if (tmp < 0) tmp = 0; +#endif return(tmp); } +#ifdef PARTIAL_XP +/* give experience points for killing a monster*/ +void grant_experience(mtmp) + register struct monst *mtmp; +{ + register struct permonst *mdat = mtmp->data; + int mndx = monsndx(mdat); + int tmp = experience(mtmp, (int)mvitals[mndx].died + 1); + mtmp->exp_granted += tmp; + more_experienced(tmp, 0); + newexplevel(); /* will decide if you go up */ +} + +/* Grant a fraction a/b of a monster's experience */ + +void grant_partial_experience(mtmp, a, b) + register struct monst *mtmp; + register int a; + register int b; +{ + register struct permonst *mdat = mtmp->data; + int mndx = monsndx(mdat); + int tmp = experience(mtmp, (int)mvitals[mndx].died + 1); + tmp = (tmp * a) / b; + mtmp->exp_granted += tmp; + more_experienced(tmp, 0); + newexplevel(); /* will decide if you go up */ +} + +#endif void more_experienced(exp, rexp) register int exp, rexp; diff -Naur nethack-3.4.3/src/makemon.c nethack-patched/src/makemon.c --- nethack-3.4.3/src/makemon.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/makemon.c 2005-02-28 12:47:13.000000000 +1100 @@ -1094,6 +1094,11 @@ if (!in_mklev) newsym(mtmp->mx,mtmp->my); /* make sure the mon shows up */ +#ifdef PARTIAL_XP + /* MRKR: No XP granted yet */ + mtmp->exp_granted = 0; + +#endif return(mtmp); } diff -Naur nethack-3.4.3/src/mhitm.c nethack-patched/src/mhitm.c --- nethack-3.4.3/src/mhitm.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/mhitm.c 2005-02-28 12:47:13.000000000 +1100 @@ -672,7 +672,11 @@ if (canseemon(mdef)) pline("%s %s for a moment.", Monnam(mdef), makeplural(stagger(mdef->data, "stagger"))); +#ifndef PARTIAL_XP mdef->mstun = 1; +#else + stun_monst(mdef); +#endif goto physical; case AD_LEGS: if (magr->mcan) { @@ -903,7 +907,11 @@ */ if (!magr->mcan && !mdef->mconf && !magr->mspec_used) { if (vis) pline("%s looks confused.", Monnam(mdef)); +#ifndef PARTIAL_XP mdef->mconf = 1; +#else + confuse_monst(mdef); +#endif mdef->mstrategy &= ~STRAT_WAITFORU; } break; @@ -925,7 +933,11 @@ if (!magr->mcan && haseyes(pd) && mdef->mcansee) { if (vis) pline("%s looks %sconfused.", Monnam(mdef), mdef->mconf ? "more " : ""); +#ifndef PARTIAL_XP mdef->mconf = 1; +#else + confuse_monst(mdef); +#endif mdef->mstrategy &= ~STRAT_WAITFORU; } tmp = 0; @@ -1193,14 +1205,29 @@ if (amt > 0) { /* sleep for N turns */ mon->mcanmove = 0; mon->mfrozen = min(amt, 127); +#ifdef PARTIAL_XP + if (responsible == &youmonst) { + /* MRKR: grant up to half remaining XP */ + grant_partial_experience(mon, amt, 256); + } +#endif } else { /* sleep until awakened */ mon->msleeping = 1; +#ifdef PARTIAL_XP + if (responsible == &youmonst) { + /* MRKR: grant half remaining XP */ + grant_partial_experience(mon, 1, 2); + } +#endif } return 1; } return 0; } +#ifdef PARTIAL_XP + +#endif /* sleeping grabber releases, engulfer doesn't; don't use for paralysis! */ void slept_monst(mon) @@ -1213,6 +1240,38 @@ } } +#ifdef PARTIAL_XP +/* `mon' is hit by a confuse attack; return 1 if it's affected, 0 otherwise */ +int +confuse_monst(mon) +struct monst *mon; +{ + if (!mon->mconf) { + mon->mconf = 1; + if (responsible == &youmonst) { + /* MRKR: grant 1/4 remaining XP */ + grant_partial_experience(mon, 1, 4); + } + } + return 1; +} + +/* `mon' is hit by a stun attack; return 1 if it's affected, 0 otherwise */ +int +stun_monst(mon) +struct monst *mon; +{ + if (!mon->mstun) { + mon->mstun = 1; + if (responsible == &youmonst) { + /* MRKR: grant 1/4 remaining XP */ + grant_partial_experience(mon, 1, 4); + } + } + return 1; +} + +#endif #endif /* OVL0 */ #ifdef OVLB @@ -1280,9 +1339,18 @@ register struct permonst *madat = magr->data; char buf[BUFSZ]; int i, tmp; +#ifdef PARTIAL_XP + /* The defender is responsible for passive effects */ + struct monst *was_responsible = responsible; + responsible = mdef; +#endif for(i = 0; ; i++) { +#ifndef PARTIAL_XP if(i >= NATTK) return (mdead | mhit); /* no passive attacks */ +#else + if(i >= NATTK) goto end; /* no passive attacks */ +#endif if(mddat->mattk[i].aatyp == AT_NONE) break; } if (mddat->mattk[i].damn) @@ -1317,7 +1385,11 @@ default: break; } +#ifndef PARTIAL_XP if (mdead || mdef->mcan) return (mdead|mhit); +#else + if (mdead || mdef->mcan) goto end; +#endif /* These affect the enemy only if defender is still alive */ if (rn2(3)) switch(mddat->mattk[i].adtyp) { @@ -1331,14 +1403,22 @@ s_suffix(mon_nam(mdef))); if (mon_reflects(magr, canseemon(magr) ? buf : (char *)0)) +#ifndef PARTIAL_XP return(mdead|mhit); +#else + goto end; +#endif Strcpy(buf, Monnam(magr)); if(canseemon(magr)) pline("%s is frozen by %s gaze!", buf, s_suffix(mon_nam(mdef))); magr->mcanmove = 0; magr->mfrozen = tmp; +#ifndef PARTIAL_XP return (mdead|mhit); +#else + goto end; +#endif } } else { /* gelatinous cube */ Strcpy(buf, Monnam(magr)); @@ -1346,9 +1426,17 @@ pline("%s is frozen by %s.", buf, mon_nam(mdef)); magr->mcanmove = 0; magr->mfrozen = tmp; +#ifndef PARTIAL_XP return (mdead|mhit); +#else + goto end; +#endif } +#ifndef PARTIAL_XP return 1; +#else + goto end; +#endif case AD_COLD: if (resists_cold(magr)) { if (canseemon(magr)) { @@ -1367,7 +1455,11 @@ break; case AD_STUN: if (!magr->mstun) { +#ifndef PARTIAL_XP magr->mstun = 1; +#else + stun_monst(magr); +#endif if (canseemon(magr)) pline("%s %s...", Monnam(magr), makeplural(stagger(magr->data, "stagger"))); @@ -1406,8 +1498,19 @@ assess_dmg: if((magr->mhp -= tmp) <= 0) { monkilled(magr, "", (int)mddat->mattk[i].adtyp); +#ifndef PARTIAL_XP return (mdead | mhit | MM_AGR_DIED); +#else + mdead |= MM_AGR_DIED; + goto end; +#endif } +#ifdef PARTIAL_XP + end: + /* Return responsibility to the attacker */ + responsible = was_responsible; + +#endif return (mdead | mhit); } diff -Naur nethack-3.4.3/src/mhitu.c nethack-patched/src/mhitu.c --- nethack-3.4.3/src/mhitu.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/mhitu.c 2005-02-28 12:47:13.000000000 +1100 @@ -2451,6 +2451,12 @@ register struct attack *mattk; { int i, tmp; +#ifdef PARTIAL_XP + /* MRKR: The defender is responsible for passive attacks */ + int result = 1; + struct monst *was_responsible = responsible; + responsible = &youmonst; +#endif for (i = 0; ; i++) { if (i >= NATTK) return 1; @@ -2491,26 +2497,48 @@ (wornitems & protector) != protector))) { if (poly_when_stoned(mtmp->data)) { mon_to_stone(mtmp); +#ifndef PARTIAL_XP return (1); +#else + goto end; +#endif } pline("%s turns to stone!", Monnam(mtmp)); stoned = 1; xkilled(mtmp, 0); +#ifndef PARTIAL_XP if (mtmp->mhp > 0) return 1; return 2; +#else + if (mtmp->mhp <= 0) result = 2; +#endif } +#ifndef PARTIAL_XP return 1; +#else + goto end; +#endif } case AD_ENCH: /* KMH -- remove enchantment (disenchanter) */ if (otmp) { (void) drain_item(otmp); /* No message */ } +#ifndef PARTIAL_XP return (1); +#else + goto end; +#endif default: break; } +#ifndef PARTIAL_XP if (!Upolyd) return 1; +#else + if (!Upolyd) { + goto end; + } +#endif /* These affect the enemy only if you are still a monster */ if (rn2(3)) switch(youmonst.data->mattk[i].adtyp) { @@ -2533,21 +2561,40 @@ youmonst.data->mname); else { if (mon_reflects(mtmp, +#ifndef PARTIAL_XP "Your gaze is reflected by %s %s.")) return 1; +#else + "Your gaze is reflected by %s %s.")) { + goto end; + } +#endif pline("%s is frozen by your gaze!", Monnam(mtmp)); mtmp->mcanmove = 0; mtmp->mfrozen = tmp; +#ifndef PARTIAL_XP return 3; +#else + result = 3; +#endif } } } else { /* gelatinous cube */ pline("%s is frozen by you.", Monnam(mtmp)); mtmp->mcanmove = 0; mtmp->mfrozen = tmp; +#ifndef PARTIAL_XP return 3; +#else + result = 3; +#endif } +#ifndef PARTIAL_XP return 1; +#else + goto end; + +#endif case AD_COLD: /* Brown mold or blue jelly */ if (resists_cold(mtmp)) { shieldeff(mtmp->mx, mtmp->my); @@ -2564,7 +2611,11 @@ break; case AD_STUN: /* Yellow mold */ if (!mtmp->mstun) { +#ifndef PARTIAL_XP mtmp->mstun = 1; +#else + stun_monst(mtmp); +#endif pline("%s %s.", Monnam(mtmp), makeplural(stagger(mtmp->data, "stagger"))); } @@ -2599,10 +2650,22 @@ if((mtmp->mhp -= tmp) <= 0) { pline("%s dies!", Monnam(mtmp)); xkilled(mtmp,0); +#ifndef PARTIAL_XP if (mtmp->mhp > 0) return 1; return 2; +#else + if (mtmp->mhp <= 0) result = 2; +#endif } +#ifndef PARTIAL_XP return 1; +#else + end: + /* MRKR: return responsibility to the attacker */ + responsible = was_responsible; + + return result; +#endif } #endif /* OVL1 */ diff -Naur nethack-3.4.3/src/mon.c nethack-patched/src/mon.c --- nethack-3.4.3/src/mon.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/mon.c 2005-02-28 12:47:13.000000000 +1100 @@ -582,6 +582,11 @@ for(mtmp = fmon; mtmp; mtmp = nmtmp) { nmtmp = mtmp->nmon; +#ifdef PARTIAL_XP + /* MRKR: The monster is responsible for actions */ + responsible = mtmp; + +#endif /* Find a monster that we have not treated yet. */ if(DEADMONSTER(mtmp)) continue; @@ -683,7 +688,11 @@ } /* The object's rustproofing is gone now */ otmp->oerodeproof = 0; +#ifndef PARTIAL_XP mtmp->mstun = 1; +#else + stun_monst(mtmp); +#endif if (canseemon(mtmp) && flags.verbose) { pline("%s spits %s out in disgust!", Monnam(mtmp), distant_name(otmp,doname)); @@ -1869,10 +1878,14 @@ You_feel("guilty..."); } +#ifndef PARTIAL_XP /* give experience points */ tmp = experience(mtmp, (int)mvitals[mndx].died + 1); more_experienced(tmp, 0); newexplevel(); /* will decide if you go up */ +#else + grant_experience(mtmp); +#endif /* adjust alignment points */ if (mtmp->m_id == quest_status.leader_m_id) { /* REAL BAD! */ diff -Naur nethack-3.4.3/src/monmove.c nethack-patched/src/monmove.c --- nethack-3.4.3/src/monmove.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/monmove.c 2005-02-28 12:47:13.000000000 +1100 @@ -30,7 +30,11 @@ You_hear("a distant explosion."); } wake_nearto(mtmp->mx, mtmp->my, 7*7); +#ifndef PARTIAL_XP mtmp->mstun = 1; +#else + stun_monst(mtmp); +#endif mtmp->mhp -= rnd(15); if(mtmp->mhp <= 0) { mondied(mtmp); diff -Naur nethack-3.4.3/src/polyself.c nethack-patched/src/polyself.c --- nethack-3.4.3/src/polyself.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/polyself.c 2005-02-28 12:47:13.000000000 +1100 @@ -986,12 +986,22 @@ * gazes at *you*--only medusa gaze gets reflected then. */ if (adtyp == AD_CONF) { +#ifndef PARTIAL_XP if (!mtmp->mconf) +#else + if (!mtmp->mconf) { +#endif Your("gaze confuses %s!", mon_nam(mtmp)); +#ifdef PARTIAL_XP + confuse_monst(mtmp); + } +#endif else pline("%s is getting more and more confused.", Monnam(mtmp)); +#ifndef PARTIAL_XP mtmp->mconf = 1; +#endif } else if (adtyp == AD_FIRE) { int dmg = d(2,6); You("attack %s with a fiery gaze!", mon_nam(mtmp)); diff -Naur nethack-3.4.3/src/uhitm.c nethack-patched/src/uhitm.c --- nethack-3.4.3/src/uhitm.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/uhitm.c 2005-02-28 12:47:13.000000000 +1100 @@ -1055,7 +1055,11 @@ } else if(u.umconf && !thrown) { nohandglow(mon); if (!mon->mconf && !resist(mon, SPBOOK_CLASS, 0, NOTELL)) { +#ifndef PARTIAL_XP mon->mconf = 1; +#else + confuse_monst(mon); +#endif if (!mon->mstun && mon->mcanmove && !mon->msleeping && canseemon(mon)) pline("%s appears confused.", Monnam(mon)); @@ -1296,7 +1300,11 @@ if(!Blind) pline("%s %s for a moment.", Monnam(mdef), makeplural(stagger(mdef->data, "stagger"))); +#ifndef PARTIAL_XP mdef->mstun = 1; +#else + stun_monst(mdef); +#endif goto physical; case AD_LEGS: /* if (u.ucancelled) { */ @@ -1631,7 +1639,11 @@ if (!mdef->mconf) { if (canseemon(mdef)) pline("%s looks confused.", Monnam(mdef)); +#ifndef PARTIAL_XP mdef->mconf = 1; +#else + confuse_monst(mdef); +#endif } break; default: tmp = 0; @@ -1675,7 +1687,11 @@ if (haseyes(mdef->data) && mdef->mcansee) { pline("%s is affected by your flash of light!", Monnam(mdef)); +#ifndef PARTIAL_XP mdef->mconf = 1; +#else + confuse_monst(mdef); +#endif } break; case AD_COLD: diff -Naur nethack-3.4.3/src/zap.c nethack-patched/src/zap.c --- nethack-3.4.3/src/zap.c 2003-12-08 10:39:13.000000000 +1100 +++ nethack-patched/src/zap.c 2005-02-28 12:47:13.000000000 +1100 @@ -689,7 +689,11 @@ } } /* was ghost, now alive, it's all very confusing */ +#ifndef PARTIAL_XP mtmp->mconf = 1; +#else + confuse_monst(mtmp); +#endif } switch (obj->where) {