more context (trunk only)

- reading spellbooks
- taking off
This commit is contained in:
nethack.allison
2003-10-08 03:31:06 +00:00
parent 9c24966fe2
commit 27749e572e
7 changed files with 192 additions and 146 deletions

View 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;

View 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"

View 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

View File

@@ -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;

View 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;
}

View 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 */

View 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) {