]> granicus.if.org Git - nethack/commitdiff
more context (trunk only)
authornethack.allison <nethack.allison>
Wed, 8 Oct 2003 03:31:06 +0000 (03:31 +0000)
committernethack.allison <nethack.allison>
Wed, 8 Oct 2003 03:31:06 +0000 (03:31 +0000)
- reading spellbooks
- taking off

include/context.h
include/patchlevel.h
src/do_wear.c
src/eat.c
src/restore.c
src/save.c
src/spell.c

index f9abb107ab4560f3f2cf6346dccc09f483009f01..2a233fa85c950a1eecc5c3ee95ff8c5629d2f447 100644 (file)
@@ -9,6 +9,8 @@
 #ifndef CONTEXT_H
 #define CONTEXT_H
 
+#define CONTEXTVERBSZ 30
+
 /*
  * The context structure houses things that the game tracks
  * or adjusts during the game, to preserve game state or context.
@@ -31,6 +33,20 @@ struct tin_info {
        int     usedtime, reqtime;
 };
 
+struct book_info {
+       struct obj *book;       /* last/current book being xscribed */
+       unsigned o_id;          /* o_id of book in save file */
+       schar delay;            /* moves left for this spell */
+};
+
+struct takeoff_info {
+       long mask;
+       long what;
+       int delay;
+       boolean cancelled_don;
+       char disrobing[CONTEXTVERBSZ+1];
+};
+
 struct victual_info {
        struct  obj *piece;     /* the thing being eaten, or last thing that
                                 * was partially eaten, unless that thing was
@@ -73,6 +89,8 @@ struct context_info {
        struct dig_info digging;
        struct victual_info victual;
        struct tin_info tin;
+       struct book_info spbook;
+       struct takeoff_info takeoff;
 };
 
 extern NEARDATA struct context_info context;
index 53f883f0881f7b7424e3234c78fd9391ecaf1b62..a73f62c17a51a9a292f1b3690783b49cbeedbc9b 100644 (file)
@@ -13,7 +13,7 @@
  * Incrementing EDITLEVEL can be used to force invalidation of old bones
  * and save files.
  */
-#define EDITLEVEL      4
+#define EDITLEVEL      5
 
 #define COPYRIGHT_BANNER_A \
 "NetHack, Copyright 1985-2003"
index ef54c3410dfb1fc31b7abf403e5a3c65f3cb6b66..b412dc7e6837f2649ba933b75a9e7facf3c3f327 100644 (file)
@@ -4,12 +4,6 @@
 
 #include "hack.h"
 
-STATIC_OVL NEARDATA long takeoff_mask = 0L;
-static NEARDATA long taking_off = 0L;
-
-static NEARDATA int todelay;
-static boolean cancelled_don = FALSE;
-
 static NEARDATA const char see_yourself[] = "see yourself";
 static NEARDATA const char unknown_type[] = "Unknown type of %s (%d)";
 static NEARDATA const char c_armor[]  = "armor",
@@ -141,7 +135,7 @@ Boots_off()
     setworn((struct obj *)0, W_ARMF);
     switch (otyp) {
        case SPEED_BOOTS:
-               if (!Very_fast && !cancelled_don) {
+               if (!Very_fast && !context.takeoff.cancelled_don) {
                        makeknown(otyp);
                        You_feel("yourself slow down%s.",
                                Fast ? " a bit" : "");
@@ -149,14 +143,14 @@ Boots_off()
                break;
        case WATER_WALKING_BOOTS:
                if (is_pool(u.ux,u.uy) && !Levitation && !Flying &&
-                   !is_clinger(youmonst.data) && !cancelled_don) {
+                   !is_clinger(youmonst.data) && !context.takeoff.cancelled_don) {
                        makeknown(otyp);
                        /* make boots known in case you survive the drowning */
                        spoteffects(TRUE);
                }
                break;
        case ELVEN_BOOTS:
-               if (!oldprop && !HStealth && !BStealth && !cancelled_don) {
+               if (!oldprop && !HStealth && !BStealth && !context.takeoff.cancelled_don) {
                        makeknown(otyp);
                        You("sure are noisy.");
                }
@@ -166,7 +160,7 @@ Boots_off()
                        HFumbling = EFumbling = 0;
                break;
        case LEVITATION_BOOTS:
-               if (!oldprop && !HLevitation && !cancelled_don) {
+               if (!oldprop && !HLevitation && !context.takeoff.cancelled_don) {
                        (void) float_down(0L, 0L);
                        makeknown(otyp);
                }
@@ -179,7 +173,7 @@ Boots_off()
                break;
        default: impossible(unknown_type, c_boots, otyp);
     }
-    cancelled_don = FALSE;
+    context.takeoff.cancelled_don = FALSE;
     return 0;
 }
 
@@ -351,7 +345,7 @@ Helmet_off()
            context.botl = 1;
            break;
        case CORNUTHAUM:
-           if (!cancelled_don) {
+           if (!context.takeoff.cancelled_don) {
                ABON(A_CHA) += (Role_if(PM_WIZARD) ? -1 : 1);
                context.botl = 1;
            }
@@ -362,7 +356,7 @@ Helmet_off()
            see_monsters();
            return 0;
        case HELM_OF_BRILLIANCE:
-           if (!cancelled_don) adj_abon(uarmh, -uarmh->spe);
+           if (!context.takeoff.cancelled_don) adj_abon(uarmh, -uarmh->spe);
            break;
        case HELM_OF_OPPOSITE_ALIGNMENT:
            u.ualign.type = u.ualignbase[A_CURRENT];
@@ -372,7 +366,7 @@ Helmet_off()
        default: impossible(unknown_type, c_helmet, uarmh->otyp);
     }
     setworn((struct obj *)0, W_ARMH);
-    cancelled_don = FALSE;
+    context.takeoff.cancelled_don = FALSE;
     return 0;
 }
 
@@ -420,12 +414,12 @@ Gloves_off()
            context.botl = 1; /* taken care of in attrib.c */
            break;
        case GAUNTLETS_OF_DEXTERITY:
-           if (!cancelled_don) adj_abon(uarmg, -uarmg->spe);
+           if (!context.takeoff.cancelled_don) adj_abon(uarmg, -uarmg->spe);
            break;
        default: impossible(unknown_type, c_gloves, uarmg->otyp);
     }
     setworn((struct obj *)0, W_ARMG);
-    cancelled_don = FALSE;
+    context.takeoff.cancelled_don = FALSE;
     (void) encumber_msg();             /* immediate feedback for GoP */
 
     /* Prevent wielding cockatrice when not wearing gloves */
@@ -510,7 +504,7 @@ int
 Armor_off()
 {
     setworn((struct obj *)0, W_ARM);
-    cancelled_don = FALSE;
+    context.takeoff.cancelled_don = FALSE;
     return 0;
 }
 
@@ -521,7 +515,7 @@ int
 Armor_gone()
 {
     setnotworn(uarm);
-    cancelled_don = FALSE;
+    context.takeoff.cancelled_don = FALSE;
     return 0;
 }
 
@@ -947,7 +941,7 @@ cancel_don()
         * wasting time on it (and don't dereference it when donning would
         * otherwise finish)
         */
-       cancelled_don = (afternmv == Boots_on || afternmv == Helmet_on ||
+       context.takeoff.cancelled_don = (afternmv == Boots_on || afternmv == Helmet_on ||
                         afternmv == Gloves_on || afternmv == Armor_on);
        afternmv = 0;
        nomovemsg = (char *)0;
@@ -1011,10 +1005,10 @@ dotakeoff()
            return 0;
        }
 
-       reset_remarm();         /* clear takeoff_mask and taking_off */
+       reset_remarm();         /* clear context.takeoff.mask and context.takeoff.what */
        (void) select_off(otmp);
-       if (!takeoff_mask) return 0;
-       reset_remarm();         /* armoroff() doesn't use takeoff_mask */
+       if (!context.takeoff.mask) return 0;
+       reset_remarm();         /* armoroff() doesn't use context.takeoff.mask */
 
        (void) armoroff(otmp);
        return(1);
@@ -1050,9 +1044,9 @@ doremring()
                return(0);
        }
 
-       reset_remarm();         /* clear takeoff_mask and taking_off */
+       reset_remarm();         /* clear context.takeoff.mask and context.takeoff.what */
        (void) select_off(otmp);
-       if (!takeoff_mask) return 0;
+       if (!context.takeoff.mask) return 0;
        reset_remarm();         /* not used by Ring_/Amulet_/Blindf_off() */
 
        if (otmp == uright || otmp == uleft) {
@@ -1139,7 +1133,7 @@ register struct obj *otmp;
                else setworn((struct obj *)0, otmp->owornmask & W_ARMOR);
                off_msg(otmp);
        }
-       takeoff_mask = taking_off = 0L;
+       context.takeoff.mask = context.takeoff.what = 0L;
        return(1);
 }
 
@@ -1371,7 +1365,7 @@ dowear()
 /*             if(is_shield(otmp)) (void) Shield_on(); */
                on_msg(otmp);
        }
-       takeoff_mask = taking_off = 0L;
+       context.takeoff.mask = context.takeoff.what = 0L;
        return(1);
 }
 
@@ -1754,22 +1748,22 @@ register struct obj *otmp;
            if (cursed(otmp)) return 0;
        }
 
-       if(otmp == uarm) takeoff_mask |= WORN_ARMOR;
-       else if(otmp == uarmc) takeoff_mask |= WORN_CLOAK;
-       else if(otmp == uarmf) takeoff_mask |= WORN_BOOTS;
-       else if(otmp == uarmg) takeoff_mask |= WORN_GLOVES;
-       else if(otmp == uarmh) takeoff_mask |= WORN_HELMET;
-       else if(otmp == uarms) takeoff_mask |= WORN_SHIELD;
+       if(otmp == uarm) context.takeoff.mask |= WORN_ARMOR;
+       else if(otmp == uarmc) context.takeoff.mask |= WORN_CLOAK;
+       else if(otmp == uarmf) context.takeoff.mask |= WORN_BOOTS;
+       else if(otmp == uarmg) context.takeoff.mask |= WORN_GLOVES;
+       else if(otmp == uarmh) context.takeoff.mask |= WORN_HELMET;
+       else if(otmp == uarms) context.takeoff.mask |= WORN_SHIELD;
 #ifdef TOURIST
-       else if(otmp == uarmu) takeoff_mask |= WORN_SHIRT;
+       else if(otmp == uarmu) context.takeoff.mask |= WORN_SHIRT;
 #endif
-       else if(otmp == uleft) takeoff_mask |= LEFT_RING;
-       else if(otmp == uright) takeoff_mask |= RIGHT_RING;
-       else if(otmp == uamul) takeoff_mask |= WORN_AMUL;
-       else if(otmp == ublindf) takeoff_mask |= WORN_BLINDF;
-       else if(otmp == uwep) takeoff_mask |= W_WEP;
-       else if(otmp == uswapwep) takeoff_mask |= W_SWAPWEP;
-       else if(otmp == uquiver) takeoff_mask |= W_QUIVER;
+       else if(otmp == uleft) context.takeoff.mask |= LEFT_RING;
+       else if(otmp == uright) context.takeoff.mask |= RIGHT_RING;
+       else if(otmp == uamul) context.takeoff.mask |= WORN_AMUL;
+       else if(otmp == ublindf) context.takeoff.mask |= WORN_BLINDF;
+       else if(otmp == uwep) context.takeoff.mask |= W_WEP;
+       else if(otmp == uswapwep) context.takeoff.mask |= W_SWAPWEP;
+       else if(otmp == uquiver) context.takeoff.mask |= W_QUIVER;
 
        else impossible("select_off: %s???", doname(otmp));
 
@@ -1781,61 +1775,59 @@ do_takeoff()
 {
        register struct obj *otmp = (struct obj *)0;
 
-       if (taking_off == W_WEP) {
+       if (context.takeoff.what == W_WEP) {
          if(!cursed(uwep)) {
            setuwep((struct obj *) 0);
            You("are empty %s.", body_part(HANDED));
            u.twoweap = FALSE;
          }
-       } else if (taking_off == W_SWAPWEP) {
+       } else if (context.takeoff.what == W_SWAPWEP) {
          setuswapwep((struct obj *) 0);
          You("no longer have a second weapon readied.");
          u.twoweap = FALSE;
-       } else if (taking_off == W_QUIVER) {
+       } else if (context.takeoff.what == W_QUIVER) {
          setuqwep((struct obj *) 0);
          You("no longer have ammunition readied.");
-       } else if (taking_off == WORN_ARMOR) {
+       } else if (context.takeoff.what == WORN_ARMOR) {
          otmp = uarm;
          if(!cursed(otmp)) (void) Armor_off();
-       } else if (taking_off == WORN_CLOAK) {
+       } else if (context.takeoff.what == WORN_CLOAK) {
          otmp = uarmc;
          if(!cursed(otmp)) (void) Cloak_off();
-       } else if (taking_off == WORN_BOOTS) {
+       } else if (context.takeoff.what == WORN_BOOTS) {
          otmp = uarmf;
          if(!cursed(otmp)) (void) Boots_off();
-       } else if (taking_off == WORN_GLOVES) {
+       } else if (context.takeoff.what == WORN_GLOVES) {
          otmp = uarmg;
          if(!cursed(otmp)) (void) Gloves_off();
-       } else if (taking_off == WORN_HELMET) {
+       } else if (context.takeoff.what == WORN_HELMET) {
          otmp = uarmh;
          if(!cursed(otmp)) (void) Helmet_off();
-       } else if (taking_off == WORN_SHIELD) {
+       } else if (context.takeoff.what == WORN_SHIELD) {
          otmp = uarms;
          if(!cursed(otmp)) (void) Shield_off();
 #ifdef TOURIST
-       } else if (taking_off == WORN_SHIRT) {
+       } else if (context.takeoff.what == WORN_SHIRT) {
          otmp = uarmu;
          if(!cursed(otmp))
            setworn((struct obj *)0, uarmu->owornmask & W_ARMOR);
 #endif
-       } else if (taking_off == WORN_AMUL) {
+       } else if (context.takeoff.what == WORN_AMUL) {
          otmp = uamul;
          if(!cursed(otmp)) Amulet_off();
-       } else if (taking_off == LEFT_RING) {
+       } else if (context.takeoff.what == LEFT_RING) {
          otmp = uleft;
          if(!cursed(otmp)) Ring_off(uleft);
-       } else if (taking_off == RIGHT_RING) {
+       } else if (context.takeoff.what == RIGHT_RING) {
          otmp = uright;
          if(!cursed(otmp)) Ring_off(uright);
-       } else if (taking_off == WORN_BLINDF) {
+       } else if (context.takeoff.what == WORN_BLINDF) {
          if (!cursed(ublindf)) Blindf_off(ublindf);
-       } else impossible("do_takeoff: taking off %lx", taking_off);
+       } else impossible("do_takeoff: taking off %lx", context.takeoff.what);
 
        return(otmp);
 }
 
-static const char *disrobing = "";
-
 STATIC_PTR
 int
 take_off()
@@ -1843,89 +1835,91 @@ take_off()
        register int i;
        register struct obj *otmp;
 
-       if (taking_off) {
-           if (todelay > 0) {
-               todelay--;
+       if (context.takeoff.what) {
+           if (context.takeoff.delay > 0) {
+               context.takeoff.delay--;
                return(1);      /* still busy */
            } else {
                if ((otmp = do_takeoff())) off_msg(otmp);
            }
-           takeoff_mask &= ~taking_off;
-           taking_off = 0L;
+           context.takeoff.mask &= ~context.takeoff.what;
+           context.takeoff.what = 0L;
        }
 
        for(i = 0; takeoff_order[i]; i++)
-           if(takeoff_mask & takeoff_order[i]) {
-               taking_off = takeoff_order[i];
+           if(context.takeoff.mask & takeoff_order[i]) {
+               context.takeoff.what = takeoff_order[i];
                break;
            }
 
        otmp = (struct obj *) 0;
-       todelay = 0;
+       context.takeoff.delay = 0;
 
-       if (taking_off == 0L) {
-         You("finish %s.", disrobing);
+       if (context.takeoff.what == 0L) {
+         You("finish %s.", context.takeoff.disrobing);
          return 0;
-       } else if (taking_off == W_WEP) {
-         todelay = 1;
-       } else if (taking_off == W_SWAPWEP) {
-         todelay = 1;
-       } else if (taking_off == W_QUIVER) {
-         todelay = 1;
-       } else if (taking_off == WORN_ARMOR) {
+       } else if (context.takeoff.what == W_WEP) {
+         context.takeoff.delay = 1;
+       } else if (context.takeoff.what == W_SWAPWEP) {
+         context.takeoff.delay = 1;
+       } else if (context.takeoff.what == W_QUIVER) {
+         context.takeoff.delay = 1;
+       } else if (context.takeoff.what == WORN_ARMOR) {
          otmp = uarm;
          /* If a cloak is being worn, add the time to take it off and put
           * it back on again.  Kludge alert! since that time is 0 for all
           * known cloaks, add 1 so that it actually matters...
           */
-         if (uarmc) todelay += 2 * objects[uarmc->otyp].oc_delay + 1;
-       } else if (taking_off == WORN_CLOAK) {
+         if (uarmc) context.takeoff.delay += 2 * objects[uarmc->otyp].oc_delay + 1;
+       } else if (context.takeoff.what == WORN_CLOAK) {
          otmp = uarmc;
-       } else if (taking_off == WORN_BOOTS) {
+       } else if (context.takeoff.what == WORN_BOOTS) {
          otmp = uarmf;
-       } else if (taking_off == WORN_GLOVES) {
+       } else if (context.takeoff.what == WORN_GLOVES) {
          otmp = uarmg;
-       } else if (taking_off == WORN_HELMET) {
+       } else if (context.takeoff.what == WORN_HELMET) {
          otmp = uarmh;
-       } else if (taking_off == WORN_SHIELD) {
+       } else if (context.takeoff.what == WORN_SHIELD) {
          otmp = uarms;
 #ifdef TOURIST
-       } else if (taking_off == WORN_SHIRT) {
+       } else if (context.takeoff.what == WORN_SHIRT) {
          otmp = uarmu;
          /* add the time to take off and put back on armor and/or cloak */
-         if (uarm)  todelay += 2 * objects[uarm->otyp].oc_delay;
-         if (uarmc) todelay += 2 * objects[uarmc->otyp].oc_delay + 1;
+         if (uarm)  context.takeoff.delay += 2 * objects[uarm->otyp].oc_delay;
+         if (uarmc) context.takeoff.delay += 2 * objects[uarmc->otyp].oc_delay + 1;
 #endif
-       } else if (taking_off == WORN_AMUL) {
-         todelay = 1;
-       } else if (taking_off == LEFT_RING) {
-         todelay = 1;
-       } else if (taking_off == RIGHT_RING) {
-         todelay = 1;
-       } else if (taking_off == WORN_BLINDF) {
-         todelay = 2;
+       } else if (context.takeoff.what == WORN_AMUL) {
+         context.takeoff.delay = 1;
+       } else if (context.takeoff.what == LEFT_RING) {
+         context.takeoff.delay = 1;
+       } else if (context.takeoff.what == RIGHT_RING) {
+         context.takeoff.delay = 1;
+       } else if (context.takeoff.what == WORN_BLINDF) {
+         context.takeoff.delay = 2;
        } else {
-         impossible("take_off: taking off %lx", taking_off);
+         impossible("take_off: taking off %lx", context.takeoff.what);
          return 0;     /* force done */
        }
 
-       if (otmp) todelay += objects[otmp->otyp].oc_delay;
+       if (otmp) context.takeoff.delay += objects[otmp->otyp].oc_delay;
 
        /* Since setting the occupation now starts the counter next move, that
          * would always produce a delay 1 too big per item unless we subtract
         * 1 here to account for it.
         */
-       if (todelay>0) todelay--;
+       if (context.takeoff.delay>0) context.takeoff.delay--;
 
-       set_occupation(take_off, disrobing, 0);
+       set_occupation(take_off,
+               (context.takeoff.disrobing[0]) ?
+               context.takeoff.disrobing : (char *)0, 0);
        return(1);              /* get busy */
 }
 
 void
 reset_remarm()
 {
-       taking_off = takeoff_mask = 0L;
-       disrobing = nul;
+       context.takeoff.what = context.takeoff.mask = 0L;
+       context.takeoff.disrobing[0] = '\0';
 }
 
 /* the 'A' command */
@@ -1934,9 +1928,9 @@ doddoremarm()
 {
     int result = 0;
 
-    if (taking_off || takeoff_mask) {
-       You("continue %s.", disrobing);
-       set_occupation(take_off, disrobing, 0);
+    if (context.takeoff.what || context.takeoff.mask) {
+       You("continue %s.", context.takeoff.disrobing);
+       set_occupation(take_off, context.takeoff.disrobing, 0);
        (void) take_off();
        return 0;
     } else if (!uwep && !uswapwep && !uquiver && !uamul && !ublindf &&
@@ -1950,13 +1944,13 @@ doddoremarm()
            (result = ggetobj("take off", select_off, 0, FALSE, (unsigned *)0)) < -1)
        result = menu_remarm(result);
 
-    if (takeoff_mask) {
+    if (context.takeoff.mask) {
        /* default activity for armor and/or accessories,
           possibly combined with weapons */
-       disrobing = "disrobing";
+       (void)strncpy(context.takeoff.disrobing, "disrobing", CONTEXTVERBSZ);
        /* specific activity when handling weapons only */
-       if (!(takeoff_mask & ~(W_WEP|W_SWAPWEP|W_QUIVER)))
-           disrobing = "disarming";
+       if (!(context.takeoff.mask & ~(W_WEP|W_SWAPWEP|W_QUIVER)))
+               (void)strncpy(context.takeoff.disrobing, "disarming", CONTEXTVERBSZ);
        (void) take_off();
     }
     /* The time to perform the command is already completely accounted for
index d0d23d2e0ae8a5b9145aba2af6156b49cbf80b11..d845318069b68004329e22ee842158a1def838b7 100644 (file)
--- a/src/eat.c
+++ b/src/eat.c
@@ -351,6 +351,8 @@ do_reset_eat()
        if (context.victual.piece) {
                context.victual.o_id = 0;
                context.victual.piece = touchfood(context.victual.piece);
+               if (context.victual.piece)
+                       context.victual.o_id = context.victual.piece->o_id;
                recalc_wt();
        }
        context.victual.fullwarn = context.victual.eating = context.victual.doreset = FALSE;
@@ -1147,7 +1149,8 @@ no_opener:
        context.tin.reqtime = tmp;
        context.tin.usedtime = 0;
        context.tin.tin = otmp;
-       if (otmp) context.tin.o_id = otmp->o_id;
+       if (context.tin.tin)
+               context.tin.o_id = context.tin.tin->o_id;
        set_occupation(opentin, "opening the tin", 0);
        return;
 }
@@ -1955,6 +1958,7 @@ doeat()           /* generic "eat" command funtion (see cmd.c) */
         * they shouldn't be able to choke now.
         */
            if (u.uhs != SATIATED) context.victual.canchoke = FALSE;
+           context.victual.o_id = 0;
            context.victual.piece = touchfood(otmp);
            if (context.victual.piece)
                context.victual.o_id = context.victual.piece->o_id;
@@ -1974,6 +1978,7 @@ doeat()           /* generic "eat" command funtion (see cmd.c) */
        /* KMH, conduct */
        u.uconduct.food++;
 
+       context.victual.o_id = 0;
        context.victual.piece = otmp = touchfood(otmp);
        if (context.victual.piece)
                context.victual.o_id = context.victual.piece->o_id;
index 0e0b608217ac349d9375757824729e57c1017364..1412013d0edb01b37b6e036d5000891cfa11b0fa 100644 (file)
@@ -235,10 +235,12 @@ boolean ghostly, frozen;
                if (otmp->bypass) otmp->bypass = 0;
                if (!ghostly) {
                    /* fix the pointers */
-                   if (context.victual.o_id == otmp->o_id)
+                   if (otmp->o_id == context.victual.o_id)
                        context.victual.piece = otmp;
-                   if (context.tin.o_id == otmp->o_id)
+                   if (otmp->o_id == context.tin.o_id)
                        context.tin.tin = otmp;
+                   if (otmp->o_id == context.spbook.o_id)
+                       context.spbook.book = otmp;
                }
                otmp2 = otmp;
        }
index 8b91cffb475e3162cae0cd65001e0191ef31c328..5a9545737737badafc98f80c3e4caf42816128a5 100644 (file)
@@ -877,17 +877,34 @@ register struct obj *otmp;
                saveobjchn(fd,otmp->cobj,mode);
            if (release_data(mode)) {
 /*             if (otmp->oclass == FOOD_CLASS) food_disappears(otmp); */
+               /*
+                * If these are on the floor, the discarding could
+                * be because of a game save, or we could just be changing levels.
+                * Always invalidate the pointer, but ensure that we have
+                * the o_id in order to restore the pointer on reload.
+                */
                if (otmp == context.victual.piece) {
                        /* Store the o_id of the victual if mismatched */
                        if (context.victual.o_id != otmp->o_id)
                            context.victual.o_id = otmp->o_id;
+                       /* invalidate the pointer; on reload it will get restored */
+                       context.victual.piece = (struct obj *)0;
                }
                if (otmp == context.tin.tin) {
                        /* Store the o_id of your tin */
                        if (context.tin.o_id != otmp->o_id)
                            context.tin.o_id = otmp->o_id;
+                       /* invalidate the pointer; on reload it will get restored */
+                       context.tin.tin = (struct obj *)0;
+               }
+/*             if (otmp->oclass == SPBOOK_CLASS) book_disappears(otmp); */
+               if (otmp == context.spbook.book) {
+                       /* Store the o_id of your spellbook */
+                       if (context.spbook.o_id != otmp->o_id)
+                           context.spbook.o_id = otmp->o_id;
+                       /* invalidate the pointer; on reload it will get restored */
+                       context.spbook.book = (struct obj *)0;
                }
-               if (otmp->oclass == SPBOOK_CLASS) book_disappears(otmp);
                otmp->where = OBJ_FREE; /* set to free so dealloc will work */
                otmp->timed = 0;        /* not timed any more */
                otmp->lamplit = 0;      /* caller handled lights */
index 4470105aa4c35c1ac2fd7bc6386d0905f593d5d3..104b0a000932290cc5bd5c7853b64d7fd83dcfd1 100644 (file)
@@ -4,9 +4,6 @@
 
 #include "hack.h"
 
-static NEARDATA schar delay;           /* moves left for this spell */
-static NEARDATA struct obj *book;      /* last/current book being xscribed */
-
 /* spellmenu arguments; 0 thru n-1 used as spl_book[] index when swapping */
 #define SPELLMENU_CAST (-2)
 #define SPELLMENU_VIEW (-1)
@@ -194,7 +191,7 @@ struct obj *spellbook;
            gone = TRUE;
        } else {
            You("find yourself reading the %s line over and over again.",
-               spellbook == book ? "next" : "first");
+               spellbook == context.spbook.book ? "next" : "first");
        }
        return gone;
 }
@@ -321,22 +318,23 @@ learn()
        boolean costly = TRUE;
 
        /* JDS: lenses give 50% faster reading; 33% smaller read time */
-       if (delay && ublindf && ublindf->otyp == LENSES && rn2(2)) delay++;
+       if (context.spbook.delay && ublindf && ublindf->otyp == LENSES && rn2(2)) context.spbook.delay++;
        if (Confusion) {                /* became confused while learning */
-           (void) confused_book(book);
-           book = 0;                   /* no longer studying */
-           nomul(delay);               /* remaining delay is uninterrupted */
-           delay = 0;
+           (void) confused_book(context.spbook.book);
+           context.spbook.book = 0;                    /* no longer studying */
+           context.spbook.o_id = 0;
+           nomul(context.spbook.delay);                /* remaining delay is uninterrupted */
+           context.spbook.delay = 0;
            return(0);
        }
-       if (delay) {    /* not if (delay++), so at end delay == 0 */
-           delay++;
+       if (context.spbook.delay) {     /* not if (context.spbook.delay++), so at end delay == 0 */
+           context.spbook.delay++;
            return(1); /* still busy */
        }
        exercise(A_WIS, TRUE);          /* you're studying. */
-       booktype = book->otyp;
+       booktype = context.spbook.book->otyp;
        if(booktype == SPE_BOOK_OF_THE_DEAD) {
-           deadbook(book);
+           deadbook(context.spbook.book);
            return(0);
        }
 
@@ -345,13 +343,13 @@ learn()
                OBJ_NAME(objects[booktype]));
        for (i = 0; i < MAXSPELL; i++)  {
                if (spellid(i) == booktype)  {
-                       if (book->spestudied > MAX_SPELL_STUDY) {
+                       if (context.spbook.book->spestudied > MAX_SPELL_STUDY) {
                            pline("This spellbook is too faint to be read any more.");
-                           book->otyp = booktype = SPE_BLANK_PAPER;
+                           context.spbook.book->otyp = booktype = SPE_BLANK_PAPER;
                        } else if (spellknow(i) <= 1000) {
                            Your("knowledge of %s is keener.", splname);
                            incrnknow(i);
-                           book->spestudied++;
+                           context.spbook.book->spestudied++;
                            exercise(A_WIS,TRUE);       /* extra study */
                        } else { /* 1000 < spellknow(i) <= MAX_SPELL_STUDY */
                            You("know %s quite well already.", splname);
@@ -365,7 +363,7 @@ learn()
                        spl_book[i].sp_id = booktype;
                        spl_book[i].sp_lev = objects[booktype].oc_level;
                        incrnknow(i);
-                       book->spestudied++;
+                       context.spbook.book->spestudied++;
                        You(i > 0 ? "add %s to your repertoire." : "learn %s.",
                            splname);
                        makeknown((int)booktype);
@@ -374,15 +372,17 @@ learn()
        }
        if (i == MAXSPELL) impossible("Too many spells memorized!");
 
-       if (book->cursed) {     /* maybe a demon cursed it */
-           if (cursed_book(book)) {
-               useup(book);
-               book = 0;
+       if (context.spbook.book->cursed) {      /* maybe a demon cursed it */
+           if (cursed_book(context.spbook.book)) {
+               useup(context.spbook.book);
+               context.spbook.book = 0;
+               context.spbook.o_id = 0;
                return 0;
            }
        }
-       if (costly) check_unpaid(book);
-       book = 0;
+       if (costly) check_unpaid(context.spbook.book);
+       context.spbook.book = 0;
+       context.spbook.o_id = 0;
        return(0);
 }
 
@@ -394,9 +394,9 @@ register struct obj *spellbook;
        register boolean confused = (Confusion != 0);
        boolean too_hard = FALSE;
 
-       if (delay && !confused && spellbook == book &&
+       if (context.spbook.delay && !confused && spellbook == context.spbook.book &&
                    /* handle the sequence: start reading, get interrupted,
-                      have book become erased somehow, resume reading it */
+                      have context.spbook.book become erased somehow, resume reading it */
                    booktype != SPE_BLANK_PAPER) {
                You("continue your efforts to memorize the spell.");
        } else {
@@ -409,20 +409,20 @@ register struct obj *spellbook;
                switch (objects[booktype].oc_level) {
                 case 1:
                 case 2:
-                       delay = -objects[booktype].oc_delay;
+                       context.spbook.delay = -objects[booktype].oc_delay;
                        break;
                 case 3:
                 case 4:
-                       delay = -(objects[booktype].oc_level - 1) *
+                       context.spbook.delay = -(objects[booktype].oc_level - 1) *
                                objects[booktype].oc_delay;
                        break;
                 case 5:
                 case 6:
-                       delay = -objects[booktype].oc_level *
+                       context.spbook.delay = -objects[booktype].oc_level *
                                objects[booktype].oc_delay;
                        break;
                 case 7:
-                       delay = -8 * objects[booktype].oc_delay;
+                       context.spbook.delay = -8 * objects[booktype].oc_delay;
                        break;
                 default:
                        impossible("Unknown spellbook level %d, book %d;",
@@ -463,8 +463,8 @@ register struct obj *spellbook;
                if (too_hard) {
                    boolean gone = cursed_book(spellbook);
 
-                   nomul(delay);                       /* study time */
-                   delay = 0;
+                   nomul(context.spbook.delay);                        /* study time */
+                   context.spbook.delay = 0;
                    if(gone || !rn2(3)) {
                        if (!gone) pline_The("spellbook crumbles to dust!");
                        if (!objects[spellbook->otyp].oc_name_known &&
@@ -478,8 +478,8 @@ register struct obj *spellbook;
                    if (!confused_book(spellbook)) {
                        spellbook->in_use = FALSE;
                    }
-                   nomul(delay);
-                   delay = 0;
+                   nomul(context.spbook.delay);
+                   context.spbook.delay = 0;
                    return(1);
                }
                spellbook->in_use = FALSE;
@@ -489,7 +489,9 @@ register struct obj *spellbook;
                    "memorize");
        }
 
-       book = spellbook;
+       context.spbook.book = spellbook;
+       if (context.spbook.book)
+               context.spbook.o_id = context.spbook.book->o_id;
        set_occupation(learn, "studying", 0);
        return(1);
 }
@@ -500,7 +502,10 @@ void
 book_disappears(obj)
 struct obj *obj;
 {
-       if (obj == book) book = (struct obj *)0;
+       if (obj == context.spbook.book) {
+               context.spbook.book = (struct obj *)0;
+               context.spbook.o_id = 0;
+       }
 }
 
 /* renaming an object usually results in it having a different address;
@@ -510,7 +515,11 @@ void
 book_substitution(old_obj, new_obj)
 struct obj *old_obj, *new_obj;
 {
-       if (old_obj == book) book = new_obj;
+       if (old_obj == context.spbook.book) {
+               context.spbook.book = new_obj;
+               if (context.spbook.book)
+                       context.spbook.o_id = context.spbook.book->o_id;
+       }
 }
 
 /* called from moveloop() */
@@ -1005,7 +1014,8 @@ losespells()
        boolean confused = (Confusion != 0);
        int  n, nzap, i;
 
-       book = 0;
+       context.spbook.book = 0;
+       context.spbook.o_id = 0;
        for (n = 0; n < MAXSPELL && spellid(n) != NO_SPELL; n++)
                continue;
        if (n) {