]> granicus.if.org Git - nethack/commitdiff
Rolling boulder traps and pacifism
authorcohrs <cohrs>
Fri, 29 Mar 2002 17:56:13 +0000 (17:56 +0000)
committercohrs <cohrs>
Fri, 29 Mar 2002 17:56:13 +0000 (17:56 +0000)
If you stepped on an unknown rolling boulder trap, and that rolling boulder
hit a monster and killed it, you would be called a killer.  This makes
playing a pacifism conduct game rather difficult.
- track boulders from unknown rolling boulder traps, and don't charge/credit
hero if they kill monsters. This is done by temporarily setting otrapped on
such boulders.
- boulders from known traps are still charged/credited to the hero
- fix a couple places in ohitmon where is_poisonable wasn't checked along
with opoisoned.

doc/fixes34.1
include/hack.h
include/obj.h
src/dokick.c
src/mthrowu.c
src/trap.c

index 3af3739afd565df8214a6dd4c6e1a4ae378a7632..9e381ded1f2c2498a429194afba9b5bc94af96dc 100644 (file)
@@ -29,6 +29,7 @@ let lev_comp and dgn_comp accept optional carriage return character prior to
 Wizard of Yendor will start harassing you after the invocation if you've
        managed to get that far without ever killing him
 characters polymorphed into centaurs can't wear boots
+if an unknown rolling boulder trap kills a monster, you shouldn't be a murderer
 
 
 Platform- and/or Interface-Specific Fixes
index 6529f4f609b559506c33282c8f0008389c92c31f..3a3aadffb68288af998633cf0b33a4b8cd50b125 100644 (file)
@@ -195,8 +195,9 @@ NEARDATA extern coord bhitpos;      /* place where throw or zap hits or stops */
 #define MAY_FRACTURE   0x10    /* boulders & statues may fracture */
 
 /* Macros for launching objects */
-#define ROLL   1
-#define FLING  2
+#define ROLL           0x01    /* the object is rolling */
+#define FLING          0x02    /* the object is flying thru the air */
+#define LAUNCH_KNOWN   0x80    /* the hero caused this by explicit action */
 
 /* Macros for explosion types */
 #define EXPL_DARK      0
index e118b1d2e670b252dd0adb69126d3bdcf814100e..324a1409da505fe834a7a961cdbd91cb1e422b6d 100644 (file)
@@ -70,6 +70,7 @@ struct obj {
        Bitfield(olocked,1);    /* object is locked */
        Bitfield(obroken,1);    /* lock has been broken */
        Bitfield(otrapped,1);   /* container is trapped */
+                               /* or accidental tripped rolling boulder trap */
 #define opoisoned otrapped     /* object (weapon) is coated with poison */
 
        Bitfield(recharged,3);  /* number of times it's been recharged */
index 9cf1acfae65d91f866c6784023fe569dc2615b0e..aff4e29870b549d096f05c834a872f9f747549a3 100644 (file)
@@ -1313,6 +1313,8 @@ boolean shop_floor_obj;
        otmp->ox = cc.x;
        otmp->oy = cc.y;
        otmp->owornmask = (long)toloc;
+       /* boulder from rolling boulder trap, no longer part of the trap */
+       if (otmp->otyp == BOULDER) otmp->otrapped = 0;
 
        if(impact) {
            /* the objs impacted may be in a shop other than
index 1943b3d82754ab9fe87f7e5d315844ef192c03f8..a397191cbd083666c4d2f229a8fcd19744c6145c 100644 (file)
@@ -188,7 +188,7 @@ boolean verbose;  /* give message(s) even when you can't see what happened */
            if (vis) hit(distant_name(otmp,mshot_xname), mtmp, exclam(damage));
            else if (verbose) pline("It is hit%s", exclam(damage));
 
-           if (otmp->opoisoned) {
+           if (otmp->opoisoned && is_poisonable(otmp)) {
                if (resists_poison(mtmp)) {
                    if (vis) pline_The("poison doesn't seem to affect %s.",
                                   mon_nam(mtmp));
@@ -223,7 +223,10 @@ boolean verbose;  /* give message(s) even when you can't see what happened */
                    pline("%s is %s!", Monnam(mtmp),
                        (nonliving(mtmp->data) || !vis)
                        ? "destroyed" : "killed");
-               if (!flags.mon_moving) xkilled(mtmp,0);
+               /* don't blame hero for unknown rolling boulder trap */
+               if (!flags.mon_moving &&
+                   (otmp->otyp != BOULDER || range >= 0 || !otmp->otrapped))
+                   xkilled(mtmp,0);
                else mondied(mtmp);
            }
 
@@ -377,7 +380,8 @@ m_throw(mon, x, y, dx, dy, range, obj)
                            if (dam < 1) dam = 1;
                            hitu = thitu(hitv, dam, singleobj, (char *)0);
                    }
-                   if (hitu && singleobj->opoisoned) {
+                   if (hitu && singleobj->opoisoned &&
+                       is_poisonable(singleobj)) {
                        char onmbuf[BUFSZ], knmbuf[BUFSZ];
                        struct obj otmp;
                        unsigned save_ocknown;
index 82d07456f22e5970feff1d93120d6b5fb44f9ea4..be96ae52e823b3c3de7af9e7b3d69aadce2f050c 100644 (file)
@@ -1000,17 +1000,19 @@ glovecheck:             (void) rust_dmg(uarmg, "gauntlets", 1, TRUE, &youmonst);
                fill_pit(u.ux, u.uy);
                break;
 
-           case ROLLING_BOULDER_TRAP:
+           case ROLLING_BOULDER_TRAP: {
+               int style = ROLL | (trap->tseen ? LAUNCH_KNOWN : 0);
+
                seetrap(trap);
                pline("Click! You trigger a rolling boulder trap!");
                if(!launch_obj(BOULDER, trap->launch.x, trap->launch.y,
-                     trap->launch2.x,trap->launch2.y, ROLL)) {
+                     trap->launch2.x, trap->launch2.y, style)) {
                    deltrap(trap);
                    newsym(u.ux,u.uy);  /* get rid of trap symbol */
                    pline("Fortunately for you, no boulder was released.");
                }
                break;
-
+           }
            case MAGIC_PORTAL:
                seetrap(trap);
                domagicportal(trap);
@@ -1194,6 +1196,11 @@ int style;
        dx = sgn(x2 - x1);
        dy = sgn(y2 - y1);
        switch (style) {
+           case ROLL|LAUNCH_KNOWN:
+                       /* use otrapped as a flag to ohitmon */
+                       singleobj->otrapped = 1;
+                       style &= ~LAUNCH_KNOWN;
+                       /* fall through */
            case ROLL:
                        delaycnt = 2;
                        /* fall through */
@@ -1223,6 +1230,7 @@ int style;
                            if (rn2(3)) {
                                pline("%s snatches the boulder.",
                                        Monnam(mtmp));
+                               singleobj->otrapped = 0;
                                (void) mpickobj(mtmp, singleobj);
                                used_up = TRUE;
                                break;
@@ -1242,7 +1250,7 @@ int style;
                }
                if (style == ROLL) {
                    if (down_gate(bhitpos.x, bhitpos.y) != -1) {
-                      if (ship_object(singleobj, bhitpos.x, bhitpos.y, FALSE)){
+                       if(ship_object(singleobj, bhitpos.x, bhitpos.y, FALSE)){
                                used_up = TRUE;
                                break;
                        }
@@ -1258,6 +1266,7 @@ int style;
                                deltrap(t);
                                del_engr_at(bhitpos.x,bhitpos.y);
                                place_object(singleobj, bhitpos.x, bhitpos.y);
+                               singleobj->otrapped = 0;
                                fracture_rock(singleobj);
                                scatter(bhitpos.x,bhitpos.y, 4,
                                        MAY_DESTROY|MAY_HIT|MAY_FRACTURE|VIS_EFFECTS,
@@ -1273,6 +1282,7 @@ int style;
                                pline("Suddenly the rolling boulder disappears!");
                            else
                                You_hear("a rumbling stop abruptly.");
+                           singleobj->otrapped = 0;
                            if (t->ttyp == TELEP_TRAP)
                                rloco(singleobj);
                            else {
@@ -1304,6 +1314,9 @@ int style;
                        You_hear("a loud crash%s!",
                                cansee(bhitpos.x, bhitpos.y) ? bmsg : "");
                        obj_extract_self(otmp2);
+                       /* pass off the otrapped flag to the next boulder */
+                       otmp2->otrapped = singleobj->otrapped;
+                       singleobj->otrapped = 0;
                        place_object(singleobj, bhitpos.x, bhitpos.y);
                        singleobj = otmp2;
                        otmp2 = (struct obj *)0;
@@ -1319,6 +1332,7 @@ int style;
        }
        tmp_at(DISP_END, 0);
        if (!used_up) {
+               singleobj->otrapped = 0;
                place_object(singleobj, x2,y2);
                newsym(x2,y2);
                return 1;