From: nethack.allison Date: Wed, 8 Oct 2003 03:31:06 +0000 (+0000) Subject: more context (trunk only) X-Git-Tag: MOVE2GIT~1727 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=27749e572e927515720992051e688ea0b6567785;p=nethack more context (trunk only) - reading spellbooks - taking off --- diff --git a/include/context.h b/include/context.h index f9abb107a..2a233fa85 100644 --- a/include/context.h +++ b/include/context.h @@ -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; diff --git a/include/patchlevel.h b/include/patchlevel.h index 53f883f08..a73f62c17 100644 --- a/include/patchlevel.h +++ b/include/patchlevel.h @@ -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" diff --git a/src/do_wear.c b/src/do_wear.c index ef54c3410..b412dc7e6 100644 --- a/src/do_wear.c +++ b/src/do_wear.c @@ -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 diff --git a/src/eat.c b/src/eat.c index d0d23d2e0..d84531806 100644 --- 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; diff --git a/src/restore.c b/src/restore.c index 0e0b60821..1412013d0 100644 --- a/src/restore.c +++ b/src/restore.c @@ -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; } diff --git a/src/save.c b/src/save.c index 8b91cffb4..5a9545737 100644 --- a/src/save.c +++ b/src/save.c @@ -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 */ diff --git a/src/spell.c b/src/spell.c index 4470105aa..104b0a000 100644 --- a/src/spell.c +++ b/src/spell.c @@ -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) {