-+-+-+-+-+-+-+-+ START OF PART 54 -+-+-+-+-+-+-+-+ XIf you're building Moria on a VAX/VMS system, you'll need a C compiler Xthat understands the 'defined()' macro. X X`09Notes on VMS files: X X`09getch.c - single character terminal input and related routines. X X`09uexit.c`09- shell for the exit() call, to prevent -NOMSG messages X`09`09from appearing when exiting the Moria program. X X`09makefile. - for use if you have a Make utility. I use Todd X`09`09Aven's VMSMAKE (with the unix options) X X`09moria.opt - the options file for linking Moria. (You do a X`09`09'link moria/opt' command to link the program) X X`09descrip.mms - builds moria if you have the mms utility. (You do a X`09`09'mms/description=descrip.mms' to build it.) X X`09debug.mms - builds moria to run under debug if you have the mms X`09`09utility. (You do a 'mms/description=debug.mms' to build X`09`09the debugger version.) X X`09make.com - for those without make or mms, does all the compiles X`09`09and the final link of the program. X X scores.fdl - file intended for use with CONVERT/FDL; the score X file needs to be created empty, then converted using X scores.fdl. This is because moria expects it to be X stream/LF format. X XIn the config.h file, the files that moria uses are defined to be Xon the logical device 'moria:'. This will need to be defined before Xyou can run Moria. $ CALL UNPACK README.;1 957290561 $ create 'f' X/* source/recall.c: print out monster memory info`09`09`09-CJS- X X Copyright (c) 1989-92 James E. Wilson, Christopher J. Stuart X X This software may be copied and distributed for educational, research, an Vd X not for profit purposes provided that this copyright and statement are X included in all such copies. */ X X#ifdef __TURBOC__ X#include`09 X#endif /* __TURBOC__ */ X`20 X#include "config.h" X#include "constant.h" X#include "types.h" X#include "externs.h" X X#if defined(LINT_ARGS) Xstatic void roff(char *); X#else Xstatic void roff(); X#endif X Xstatic char *desc_atype`5B`5D = `7B X "do something undefined", X "attack", X "weaken", X "confuse", X "terrify", X "shoot flames", X "shoot acid", X "freeze", X "shoot lightning", X "corrode", X "blind", X "paralyse", X "steal money", X "steal things", X "poison", X "reduce dexterity", X "reduce constitution", X "drain intelligence", X "drain wisdom", X "lower experience", X "call for help", X "disenchant", X "eat your food", X "absorb light", X "absorb charges" `7D; Xstatic char *desc_amethod`5B`5D = `7B X "make an undefined advance", X "hit", X "bite", X "claw", X "sting", X "touch", X "kick", X "gaze", X "breathe", X "spit", X "wail", X "embrace", X "crawl on you", X "release spores", X "beg", X "slime you", X "crush", X "trample", X "drool", X "insult" `7D; Xstatic char *desc_howmuch`5B`5D = `7B X " not at all", X " a bit", X "", X " quite", X " very", X " most", X " highly", X " extremely" `7D; X Xstatic char *desc_move`5B`5D = `7B X "move invisibly", X "open doors", X "pass through walls", X "kill weaker creatures", X "pick up objects", X "breed explosively" `7D; Xstatic char *desc_spell`5B`5D = `7B X "teleport short distances", X "teleport long distances", X "teleport its prey", X "cause light wounds", X "cause serious wounds", X "paralyse its prey", X "induce blindness", X "confuse", X "terrify", X "summon a monster", X "summon the undead", X "slow its prey", X "drain mana", X "unknown 1", X "unknown 2" `7D; Xstatic char *desc_breath`5B`5D = `7B X "lightning", X "poison gases", X "acid", X "frost", X "fire" `7D; Xstatic char *desc_weakness`5B`5D = `7B X "frost", X "fire", X "poison", X "acid", X "bright light", X "rock remover" `7D; X Xstatic vtype roffbuf;`09`09/* Line buffer. */ Xstatic char *roffp;`09`09/* Pointer into line buffer. */ Xstatic int roffpline;`09`09/* Place to print line now being loaded. */ X X#define plural(c, ss, sp)`09((c) == 1 ? ss : sp) X X/* Number of kills needed for information. */ X X/* the higher the level of the monster, the fewer the kills you need */ X#define knowarmor(l,d)`09`09((d) > 304 / (4 + (l))) X/* the higher the level of the monster, the fewer the attacks you need, X the more damage an attack does, the more attacks you need */ X#define knowdamage(l,a,d)`09((4 + (l))*(a) > 80 * (d)) X X/* Do we know anything about this monster? */ Xint bool_roff_recall(mon_num) Xint mon_num; X`7B X register recall_type *mp; X register int i; X X if (wizard) X return TRUE; X mp = &c_recall`5Bmon_num`5D; X if (mp->r_cmove `7C`7C mp->r_cdefense `7C`7C mp->r_kills `7C`7C mp->r_spel Vls X `7C`7C mp->r_deaths) X return TRUE; X for (i = 0; i < 4; i++) X if (mp->r_attacks`5Bi`5D) X return TRUE; X return FALSE; X`7D X X/* Print out what we have discovered about this monster. */ Xint roff_recall(mon_num) Xint mon_num; X`7B X char *p, *q; X int8u *pu; X vtype temp; X register recall_type *mp; X register creature_type *cp; X register int i, k; X register int32u j; X int32 templong; X int mspeed; X int32u rcmove, rspells; X int16u rcdefense; X recall_type save_mem; X#ifdef ATARIST_MWC X int32u holder; X int32u holder2; X#endif X X mp = &c_recall`5Bmon_num`5D; X cp = &c_list`5Bmon_num`5D; X if (wizard) X `7B X save_mem = *mp; X mp->r_kills = MAX_SHORT; X mp->r_wake = mp->r_ignore = MAX_UCHAR; X#ifdef ATARIST_MWC X j = (((cp->cmove & (holder = CM_4D2_OBJ)) != 0) * 8) + X`09(((cp->cmove & (holder = CM_2D2_OBJ)) != 0) * 4) + X`09 (((cp->cmove & (holder = CM_1D2_OBJ)) != 0) * 2) + X`09 ((cp->cmove & (holder = CM_90_RANDOM)) != 0) + X`09 ((cp->cmove & (holder = CM_60_RANDOM)) != 0); X holder = CM_TREASURE; X mp->r_cmove = (cp->cmove & `7Eholder) `7C (j << CM_TR_SHIFT); X#else X j = (((cp->cmove & CM_4D2_OBJ) != 0) * 8) + X`09(((cp->cmove & CM_2D2_OBJ) != 0) * 4) + X`09 (((cp->cmove & CM_1D2_OBJ) != 0) * 2) + X`09 ((cp->cmove & CM_90_RANDOM) != 0) + X`09 ((cp->cmove & CM_60_RANDOM) != 0); X mp->r_cmove = (cp->cmove & `7ECM_TREASURE) `7C (j << CM_TR_SHIFT); X#endif X mp->r_cdefense = cp->cdefense; X mp->r_spells = cp->spells `7C CS_FREQ; X j = 0; X pu = cp->damage; X while (*pu != 0 && j < 4) X`09`7B X`09 /* Turbo C needs a 16 bit int for the array index. */ X`09 mp->r_attacks`5B(int)j`5D = MAX_UCHAR; X`09 j++; X`09 pu++; X`09`7D X /* A little hack to enable the display of info for Quylthulgs. */ X if (mp->r_cmove & CM_ONLY_MAGIC) X`09mp->r_attacks`5B0`5D = MAX_UCHAR; X `7D X roffpline = 0; X roffp = roffbuf; X#ifdef ATARIST_MWC X holder = `7ECS_FREQ; X rspells = mp->r_spells & cp->spells & holder; X /* the CM_WIN property is always known, set it if a win monster */ X holder = CM_WIN; X rcmove = mp->r_cmove `7C (holder & cp->cmove); X#else X rspells = mp->r_spells & cp->spells & `7ECS_FREQ; X /* the CM_WIN property is always known, set it if a win monster */ X rcmove = mp->r_cmove `7C (CM_WIN & cp->cmove); X#endif X rcdefense = mp->r_cdefense & cp->cdefense; X (void) sprintf(temp, "The %s:\n", cp->name); X roff(temp); X /* Conflict history. */ X if(mp->r_deaths) X `7B X (void) sprintf(temp, X`09`09 "%d of the contributors to your monster memory %s", X`09`09 mp->r_deaths, plural(mp->r_deaths, "has", "have") ); X roff(temp); X roff(" been killed by this creature, and "); X if (mp->r_kills == 0) X`09roff("it is not ever known to have been defeated."); X else X`09`7B X`09 (void) sprintf(temp, X`09`09`09 "at least %d of the beasts %s been exterminated.", X`09`09`09 mp->r_kills, plural(mp->r_kills, "has", "have") ); X`09 roff(temp); X`09`7D X `7D X else if (mp->r_kills) X `7B X (void) sprintf(temp, "At least %d of these creatures %s", X`09`09 mp->r_kills, plural(mp->r_kills, "has", "have") ); X roff(temp); X roff(" been killed by contributors to your monster memory."); X `7D X else X roff("No known battles to the death are recalled."); X /* Immediately obvious. */ X k = FALSE; X if (cp->level == 0) X `7B X roff(" It lives in the town"); X k = TRUE; X `7D X else if (mp->r_kills) X `7B X /* The Balrog is a level 100 monster, but appears at 50 feet. */ X i = cp->level; X if (i > WIN_MON_APPEAR) X`09i = WIN_MON_APPEAR; X (void) sprintf(temp, " It is normally found at depths of %d feet", X`09`09 i * 50); X roff(temp); X k = TRUE; X `7D X /* the c_list speed value is 10 greater, so that it can be a int8u */ X mspeed = cp->speed - 10; X if (rcmove & CM_ALL_MV_FLAGS) X `7B X if (k) X`09roff(", and"); X else X`09`7B X`09 roff(" It"); X`09 k = TRUE; X`09`7D X roff(" moves"); X if (rcmove & CM_RANDOM_MOVE) X`09`7B X`09 /* Turbo C needs a 16 bit int for the array index. */ X`09 roff(desc_howmuch`5B(int)((rcmove & CM_RANDOM_MOVE) >> 3)`5D); X`09 roff(" erratically"); X`09`7D X if (mspeed == 1) X`09roff(" at normal speed"); X else X`09`7B X`09 if (rcmove & CM_RANDOM_MOVE) X`09 roff(", and"); X`09 if (mspeed <= 0) X`09 `7B X`09 if (mspeed == -1) X`09`09roff(" very"); X`09 else if (mspeed < -1) X`09`09roff(" incredibly"); X`09 roff(" slowly"); X`09 `7D X`09 else X`09 `7B X`09 if (mspeed == 3) X`09`09roff(" very"); X`09 else if (mspeed > 3) X`09`09roff(" unbelievably"); X`09 roff(" quickly"); X`09 `7D X`09`7D X `7D X if (rcmove & CM_ATTACK_ONLY) X `7B X if(k) X`09roff(", but"); X else X`09`7B X`09 roff(" It"); X`09 k = TRUE; X`09`7D X roff(" does not deign to chase intruders"); X `7D X if (rcmove & CM_ONLY_MAGIC) X `7B X if (k) X`09roff (", but"); X else X`09`7B X`09 roff (" It"); X`09 k = TRUE; X`09`7D X roff (" always moves and attacks by using magic"); X `7D X if(k) X roff("."); X /* Kill it once to know experience, and quality (evil, undead, monsterous) V. X The quality of being a dragon is obvious. */ X if (mp->r_kills) X `7B X roff(" A kill of this"); X if (cp->cdefense & CD_ANIMAL) X`09roff(" natural"); X if (cp->cdefense & CD_EVIL) X`09roff(" evil"); X if (cp->cdefense & CD_UNDEAD) X`09roff(" undead"); X X /* calculate the integer exp part, can be larger than 64K when first X`09 level character looks at Balrog info, so must store in long */ X templong = (long)cp->mexp * cp->level / py.misc.lev; X /* calculate the fractional exp part scaled by 100, X`09 must use long arithmetic to avoid overflow */ X j = (((long)cp->mexp * cp->level % py.misc.lev) * (long)1000 / X`09 py.misc.lev+5) / 10; X X (void) sprintf(temp, " creature is worth %ld.%02ld point%s", templong, X`09`09 j, (templong == 1 && j == 0 ? "" : "s")); X roff(temp); X X if (py.misc.lev / 10 == 1) p = "th"; X else X`09`7B X`09 i = py.misc.lev % 10; X`09 if (i == 1)`09`09p = "st"; X`09 else if (i == 2)`09p = "nd"; X`09 else if (i == 3) p = "rd"; X`09 else`09`09`09p = "th"; X`09`7D X i = py.misc.lev; X if (i == 8 `7C`7C i == 11 `7C`7C i == 18) q = "n"; X else`09`09`09`09q = ""; X (void) sprintf(temp, " for a%s %d%s level character.", q, i, p); X roff(temp); X `7D X /* Spells known, if have been used against us. */ X k = TRUE; X j = rspells; X#ifdef ATARIST_MWC X holder = CS_BREATHE; X holder2 = CS_BR_LIGHT; X for (i = 0; j & holder; i++) X#else X for (i = 0; j & CS_BREATHE; i++) X#endif X `7B X#ifdef ATARIST_MWC X if (j & (holder2 << i)) X#else X if (j & (CS_BR_LIGHT << i)) X#endif X`09`7B X#ifdef ATARIST_MWC X`09 j &= `7E(holder2 << i); X#else X`09 j &= `7E(CS_BR_LIGHT << i); X#endif X`09 if (k) X`09 `7B X`09 roff(" It can breathe "); X`09 k = FALSE; X`09 `7D X#ifdef ATARIST_MWC X`09 else if (j & holder) X#else X`09 else if (j & CS_BREATHE) X#endif X`09 roff(", "); X`09 else X`09 roff(" and "); X`09 roff(desc_breath`5Bi`5D); X`09`7D X `7D X k = TRUE; X#ifdef ATARIST_MWC X holder = CS_SPELLS; X for (i = 0; j & holder; i++) X#else X for (i = 0; j & CS_SPELLS; i++) X#endif X `7B X if (j & (CS_TEL_SHORT << i)) X`09`7B X`09 j &= `7E(CS_TEL_SHORT << i); X`09 if (k) X`09 `7B X#ifdef ATARIST_MWC X`09 holder2 = CS_BREATHE; X`09 if (rspells & holder2) X#else X`09 if (rspells & CS_BREATHE) X#endif X`09`09roff(", and is also"); X`09 else X`09`09roff(" It is"); X`09 roff(" magical, casting spells which "); X`09 k = FALSE; X`09 `7D X#ifdef ATARIST_MWC X`09 else if (j & holder) X#else X`09 else if (j & CS_SPELLS) X#endif X`09 roff(", "); X`09 else X`09 roff(" or "); X`09 roff(desc_spell`5Bi`5D); X`09`7D X `7D X#ifdef ATARIST_MWC X holder = CS_BREATHE`7CCS_SPELLS; X if (rspells & holder) X#else X if (rspells & (CS_BREATHE`7CCS_SPELLS)) X#endif X `7B X if ((mp->r_spells & CS_FREQ) > 5) X`09`7B`09/* Could offset by level */ X`09 (void) sprintf(temp, "; 1 time in %ld", cp->spells & CS_FREQ); X`09 roff(temp); X`09`7D X roff("."); X `7D X /* Do we know how hard they are to kill? Armor class, hit die. */ X if (knowarmor(cp->level, mp->r_kills)) X `7B X (void) sprintf(temp, " It has an armor rating of %d", cp->ac); X roff(temp); X (void) sprintf(temp, " and a%s life rating of %dd%d.", X`09`09 ((cp->cdefense & CD_MAX_HP) ? " maximized" : ""), X`09`09 cp->hd`5B0`5D, cp->hd`5B1`5D); X roff(temp); X `7D X /* Do we know how clever they are? Special abilities. */ X k = TRUE; X j = rcmove; X#ifdef ATARIST_MWC X holder = CM_SPECIAL; X holder2 = CM_INVISIBLE; X for (i = 0; j & holder; i++) X#else X for (i = 0; j & CM_SPECIAL; i++) X#endif X `7B X#ifdef ATARIST_MWC X if (j & (holder2 << i)) X#else X if (j & (CM_INVISIBLE << i)) X#endif X`09`7B X#ifdef ATARIST_MWC X`09 j &= `7E(holder2 << i); X#else X`09 j &= `7E(CM_INVISIBLE << i); X#endif X`09 if (k) X`09 `7B X`09 roff(" It can "); X`09 k = FALSE; X`09 `7D X#ifdef ATARIST_MWC +-+-+-+-+-+-+-+- END OF PART 54 +-+-+-+-+-+-+-+-