Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!caip!clyde!cbatt!cbosgd!ucbvax!ucdavis!deneb!u566393908ea From: u566393908ea@ucdavis.UUCP (u566393908ea) Newsgroups: net.sources.games Subject: VMS Larn 12.0 is here! (part 5 of 6) Message-ID: <498@ucdavis.UUCP> Date: Sat, 30-Aug-86 18:06:34 EDT Article-I.D.: ucdavis.498 Posted: Sat Aug 30 18:06:34 1986 Date-Received: Sun, 31-Aug-86 09:59:14 EDT Distribution: net Organization: University of California, Davis Lines: 2607 Hello all! This is a port of Larn v12.0 to VAX/VMS. Now everyone can save his/her daughter!! Just unpack using /bin/sh and read readme.txt. - Mark Nagel P.S. Thanks to Lord Kahless for letting me post this! -------------------------------cut here------------------------------------- #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create the files: # monster.c # regen.c # savelev.c # signal.c # tok.c # This archive created: Sat Aug 30 14:52:16 1986 export PATH; PATH=/bin:$PATH echo shar: extracting "'monster.c'" '(45763 characters)' if test -f 'monster.c' then echo shar: will not over-write existing file "'monster.c'" else cat << \SHAR_EOF > 'monster.c' /* * monster.c Larn is copyrighted 1986 by Noah Morgan. * *This file contains the following functions: *---------------------------------------------------------------------------- * *createmonster(monstno) Function to create a monster next to the player *int monstno; * *int cgood(x,y,itm,monst) Function to check location for emptiness *int x,y,itm,monst; * *createitem(it,arg) Routine to place an item next to the player *int it,arg; * *cast() Subroutine called by parse to cast a spell for the user * *speldamage(x) Function to perform spell functions cast by the player *int x; * *loseint() Routine to decrement your int(intelligence) if > 3 * *isconfuse() Routine to check to see if player is confused * *nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster *int x,monst; * *fullhit(xx) Function to return full damage against a monst(aka web) *int xx; * *direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir *int spnum,dam,arg; *char *str; * *godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks *int spnum,dam,delay; *char *str,cshow; * *ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt *int x,y; * *tdirect(spnum) Routine to teleport away a monster *int spnum; * *omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player *int sp,dam; *char *str; * *dirsub(x,y) Routine to ask for direction, then modify x,y for it *int *x,*y; * *vxy(x,y) Routine to verify/fix(*x,*y) for being within bounds *int *x,*y; * *dirpoly(spnum) Routine to ask for a direction and polymorph a monst *int spnum; * *hitmonster(x,y) Function to hit a monster at the designated coordinates *int x,y; * *hitm(x,y,amt) Function to just hit a monster at a given coordinates *int x,y,amt; * *hitplayer(x,y) Function for the monster to hit the player from(x,y) *int x,y; * *dropsomething(monst) Function to create an object when a monster dies *int monst; * *dropgold(amount) Function to drop some gold around player *int amount; * *something(level) Function to create a random item around player *int level; * *newobject(lev,i) Routine to return a randomly selected new object *int lev,*i; * *spattack(atckno,xx,yy) Function to process special attacks from monsters *int atckno,xx,yy; * *checkloss(x) Routine to subtract hp from user and flag bottomline display *int x; * *annihilate() Routine to annihilate monsters around player, playerx,playery * *newsphere(x,y,dir,lifetime) Function to create a new sphere of annihilation *int x,y,dir,lifetime; * *rmsphere(x,y) Function to delete a sphere of annihilation from list *int x,y; * *sphboom(x,y) Function to perform the effects of a sphere detonation *int x,y; * *genmonst() Function to ask for monster and genocide from game * */ #include "header.h" struct isave { /* used for alter reality */ char type; /* 0=item, 1=monster */ char id; /* item number or monster number */ short arg; /* the type of item or hitpoints of monster */ }; /* *createmonster(monstno) Function to create a monster next to the player *int monstno; * * Enter with the monster number(1 to MAXMONST+8) * Returns no value. */ createmonster(mon) int mon; { register int x, y, k, i; if (mon < 1 || mon > MAXMONST + 8) {/* check for monster number out of bounds */ beep(); lprintf("\ncan't createmonst(%d)\n",(long) mon); nap(3000); return; } while (monster[mon].genocided && mon < MAXMONST) mon++; /* genocided? */ for (k = rnd(8), i = -8; i < 0; i++, k++) {/* choose direction, then try all */ if (k > 8) k = 1; /* wraparound the diroff arrays */ x = playerx + diroffx[k]; y = playery + diroffy[k]; if (cgood(x, y, 0, 1)) {/* if we can create here */ mitem[x][y] = mon; hitp[x][y] = monster[mon].hitpoints; stealth[x][y] = know[x][y] = 0; switch(mon) { case ROTHE: case POLTERGEIST: case VAMPIRE: stealth[x][y] = 1; }; return; } } } /* * int cgood(x,y,itm,monst) Function to check location for emptiness * int x,y,itm,monst; * * Routine to return TRUE if a location does not have itm or monst there * returns FALSE(0) otherwise * Enter with itm or monst TRUE or FALSE if checking it * Example: if itm==TRUE check for no item at this location * if monst==TRUE check for no monster at this location * This routine will return FALSE if at a wall or the dungeon exit on level 1 */ int cgood(x, y, itm, monst) register int x, y; int itm, monst; { if ((y >= 0) && (y <= MAXY - 1) && (x >= 0) && (x <= MAXX - 1))/* within bounds? */ if (item[x][y] != OWALL)/* can't make anything on walls */ if (itm == 0 || (item[x][y] == 0))/* is it free of items? */ if (monst == 0 || (mitem[x][y] == 0))/* is it free of monsters? */ if ((level != 1) || (x != 33) || (y != MAXY - 1))/* not exit to level 1 */ return(1); return(0); } /* * createitem(it,arg) Routine to place an item next to the player * int it,arg; * * Enter with the item number and its argument(iven[], ivenarg[]) * Returns no value, thus we don't know about createitem() failures. */ createitem(it, arg) int it, arg; { register int x, y, k, i; if (it >= MAXOBJ) return; /* no such object */ for (k = rnd(8), i = -8; i < 0; i++, k++) {/* choose direction, then try all */ if (k > 8) k = 1; /* wraparound the diroff arrays */ x = playerx + diroffx[k]; y = playery + diroffy[k]; if (cgood(x, y, 1, 0)) {/* if we can create here */ item[x][y] = it; know[x][y] = 0; iarg[x][y] = arg; return; } } } /* * cast() Subroutine called by parse to cast a spell for the user * * No arguments and no return value. */ static char eys[] = "\nEnter your spell: "; cast() { register int i,j,a,b,d; cursors(); if (c[SPELLS] <= 0) { lprcat("\nYou don't have any spells!"); return; } lprcat(eys); --c[SPELLS]; while ((a = readchar()) == 'D') { seemagic(-1); cursors(); lprcat(eys); } if (a == '\33') goto over; /* to escape casting a spell */ if ((b = readchar()) == '\33') goto over; /* to escape casting a spell */ if ((d = readchar()) == '\33') { over: lprcat(aborted); c[SPELLS]++; return; } /* to escape casting a spell */ #ifdef EXTRA c[SPELLSCAST]++; #endif for (lprc('\n'), j = -1, i = 0; i < SPNUM; i++)/* seq search for his spell, hash? */ if ((spelcode[i][0] == a) && (spelcode[i][1] == b) && (spelcode[i][2] == d)) if (spelknow[i]) { speldamage(i); j = 1; i = SPNUM; } if (j == -1) lprcat(" Nothing Happened "); bottomline(); } /* * speldamage(x) Function to perform spell functions cast by the player * int x; * * Enter with the spell number, returns no value. * Please insure that there are 2 spaces before all messages here */ speldamage(x) int x; { register int i, j, clev; int xl, xh, yl, yh; register char *p, *kn, *pm; if (x >= SPNUM) return; /* no such spell */ if (c[TIMESTOP]) { lprcat(" It didn't seem to work"); return; } /* not if time stopped */ clev = c[LEVEL]; if ((rnd(23) == 7) || (rnd(18) > c[INTELLIGENCE])) { lprcat(" It didn't work!"); return; } if (clev * 3 + 2 < x) { lprcat(" Nothing happens. You seem inexperienced at this"); return; } switch(x) { /* ----- LEVEL 1 SPELLS ----- */ case 0: if (c[PROTECTIONTIME] == 0) c[MOREDEFENSES] += 2;/* protection field +2 */ c[PROTECTIONTIME] += 250; return; case 1: i = rnd(((clev + 1) << 1)) + clev + 3; godirect(x, i,(clev >= 2) ? " Your missiles hit the %s" : " Your missile hit the %s", 100, '+'); /* magic missile */ return; case 2: if (c[DEXCOUNT] == 0) c[DEXTERITY] += 3;/* dexterity */ c[DEXCOUNT] += 400; return; case 3: i = rnd(3) + 1; p = " While the %s slept, you smashed it %d times"; ws: direct(x, fullhit(i), p, i);/* sleep */ return; case 4: /* charm monster */ c[CHARMCOUNT] += c[CHARISMA] << 1; return; case 5: godirect(x, rnd(10) + 15 + clev, " The sound damages the %s", 70, '@');/* sonic spear */ return; /* ----- LEVEL 2 SPELLS ----- */ case 6: i = rnd(3) + 2; p = " While the %s is entangled, you hit %d times"; goto ws; /* web */ case 7: if (c[STRCOUNT] == 0) c[STREXTRA] += 3;/* strength */ c[STRCOUNT] += 150 + rnd(100); return; case 8: yl = playery - 5; /* enlightenment */ yh = playery + 6; xl = playerx - 15; xh = playerx + 16; vxy(&xl, &yl); vxy(&xh, &yh); /* check bounds */ for (i = yl; i <= yh; i++)/* enlightenment */ for (j = xl; j <= xh; j++) know[j][i] = 1; draws(xl, xh + 1, yl, yh + 1); return; case 9: raisehp(20 +(clev << 1)); return; /* healing */ case 10: c[BLINDCOUNT] = 0; return; /* cure blindness */ case 11: createmonster(makemonst(level + 1) + 8); return; case 12: if (rnd(11) + 7 <= c[WISDOM]) direct(x, rnd(20) + 20 + clev, " The %s believed!", 0); else lprcat(" It didn't believe the illusions!"); return; case 13: /* if he has the amulet of invisibility then add more time */ for (j = i = 0; i < 26; i++) if (iven[i] == OAMULET) j += 1 + ivenarg[i]; c[INVISIBILITY] +=(j << 7) + 12; return; /* ----- LEVEL 3 SPELLS ----- */ case 14: godirect(x, rnd(25 + clev) + 25 + clev, " The fireball hits the %s", 40, '*'); return; /* fireball */ case 15: godirect(x, rnd(25) + 20 + clev, " Your cone of cold strikes the %s", 60, 'O');/* cold */ return; case 16: dirpoly(x); return; /* polymorph */ case 17: c[CANCELLATION] += 5 + clev; return; /* cancellation */ case 18: c[HASTESELF] += 7 + clev; return; /* haste self */ case 19: omnidirect(x, 30 + rnd(10), " The %s gasps for air");/* cloud kill */ return; case 20: xh = min(playerx + 1, MAXX - 2); yh = min(playery + 1, MAXY - 2); for (i = max(playerx - 1, 1); i <= xh; i++)/* vaporize rock */ for (j = max(playery - 1, 1); j <= yh; j++) { kn = &know[i][j]; pm = &mitem[i][j]; switch(*(p = &item[i][j])) { case OWALL: if (level < MAXLEVEL + MAXVLEVEL - 1) *p = *kn = 0; break; case OSTATUE: if (c[HARDGAME] < 3) { *p = OBOOK; iarg[i][j] = level; *kn = 0; } break; case OTHRONE: *pm = GNOMEKING; *kn = 0; *p = OTHRONE2; hitp[i][j] = monster[GNOMEKING].hitpoints; break; case OALTAR: *pm = DEMONPRINCE; *kn = 0; hitp[i][j] = monster[DEMONPRINCE].hitpoints; break; }; switch(*pm) { case XORN: ifblind(i, j); hitm(i, j, 200); break;/* Xorn takes damage from vpr */ } } return; /* ----- LEVEL 4 SPELLS ----- */ case 21: direct(x, 100 + clev, " The %s shrivels up", 0);/* dehydration */ return; case 22: godirect(x, rnd(25) + 20 +(clev << 1), " A lightning bolt hits the %s", 1, '~');/* lightning */ return; case 23: i = min(c[HP] - 1, c[HPMAX] / 2);/* drain life */ direct(x, i + i, "", 0); c[HP] -= i; return; case 24: if (c[GLOBE] == 0) c[MOREDEFENSES] += 10; c[GLOBE] += 200; loseint(); /* globe of invulnerability */ return; case 25: omnidirect(x, 32 + clev, " The %s struggles for air in your flood!");/* flood */ return; case 26: if (rnd(151) == 63) { beep(); lprcat("\nYour heart stopped!\n"); nap(4000); died(270); return; } if (c[WISDOM] > rnd(10) + 10) direct(x, 2000, " The %s's heart stopped", 0);/* finger of death */ else lprcat(" It didn't work"); return; /* ----- LEVEL 5 SPELLS ----- */ case 27: c[SCAREMONST] += rnd(10) + clev; return; /* scare monster */ case 28: c[HOLDMONST] += rnd(10) + clev; return; /* hold monster */ case 29: c[TIMESTOP] += rnd(20) +(clev << 1); return; /* time stop */ case 30: tdirect(x); return; /* teleport away */ case 31: omnidirect(x, 35 + rnd(10) + clev, " The %s cringes from the flame");/* magic fire */ return; /* ----- LEVEL 6 SPELLS ----- */ case 32: if ((rnd(23) == 5) && (wizard == 0)) {/* sphere of annihilation */ beep(); lprcat("\nYou have been enveloped by the zone of nothingness!\n"); nap(4000); died(258); return; } xl = playerx; yl = playery; loseint(); i = dirsub(&xl, &yl);/* get direction of sphere */ newsphere(xl, yl, i, rnd(20) + 11);/* make a sphere */ return; case 33: genmonst(); spelknow[33] = 0; /* genocide */ loseint(); return; case 34: /* summon demon */ if (rnd(100) > 30) { direct(x, 150, " The demon strikes at the %s", 0); return; } if (rnd(100) > 15) { lprcat(" Nothing seems to have happened"); return; } lprcat(" The demon turned on you and vanished!"); beep(); i = rnd(40) + 30; lastnum = 277; losehp(i); /* must say killed by a demon */ return; case 35: /* walk through walls */ c[WTW] += rnd(10) + 5; return; case 36: /* alter reality */ { struct isave *save;/* pointer to item save structure */ int sc; sc = 0; /* # items saved */ save =(struct isave *) malloc(sizeof(struct isave) * MAXX * MAXY * 2); for (j = 0; j < MAXY; j++) for (i = 0; i < MAXX; i++) {/* save all items and monsters */ xl = item[i][j]; if (xl && xl != OWALL && xl != OANNIHILATION) { save[sc].type = 0; save[sc].id = item[i][j]; save[sc++].arg = iarg[i][j]; } if (mitem[i][j]) { save[sc].type = 1; save[sc].id = mitem[i][j]; save[sc++].arg = hitp[i][j]; } item[i][j] = OWALL; mitem[i][j] = 0; if (wizard) know[i][j] = 1; else know[i][j] = 0; } eat(1, 1); if (level == 1) item[33][MAXY - 1] = 0; for (j = rnd(MAXY - 2), i = 1; i < MAXX - 1; i++) item[i][j] = 0; while (sc > 0) {/* put objects back in level */ --sc; if (save[sc].type == 0) { int trys; for (trys = 100, i = j = 1; --trys > 0 && item[i][j]; i = rnd(MAXX - 1), j = rnd(MAXY - 1)); if (trys) { item[i][j] = save[sc].id; iarg[i][j] = save[sc].arg; } } else { /* put monsters back in */ int trys; for (trys = 100, i = j = 1; --trys > 0 && (item[i][j] == OWALL || mitem[i][j]); i = rnd(MAXX - 1), j = rnd(MAXY - 1)); if (trys) { mitem[i][j] = save[sc].id; hitp[i][j] = save[sc].arg; } } } loseint(); draws(0, MAXX, 0, MAXY); if (wizard == 0) spelknow[36] = 0; free((char *) save); positionplayer(); return; } case 37: /* permanence */ adjtime(-99999L); spelknow[37] = 0; /* forget */ loseint(); return; default: lprintf(" spell %d not available!",(long) x); beep(); return; }; } /* * loseint() Routine to subtract 1 from your int(intelligence) if > 3 * * No arguments and no return value */ loseint() { if (--c[INTELLIGENCE] < 3) c[INTELLIGENCE] = 3; } /* * isconfuse() Routine to check to see if player is confused * * This routine prints out a message saying "You can't aim your magic!" * returns 0 if not confused, non-zero(time remaining confused) if confused */ isconfuse() { if (c[CONFUSE]) { lprcat(" You can't aim your magic!"); beep(); } return(c[CONFUSE]); } /* * nospell(x,monst) Routine to return 1 if a spell doesn't affect a monster * int x,monst; * * Subroutine to return 1 if the spell can't affect the monster * otherwise returns 0 * Enter with the spell number in x, and the monster number in monst. */ nospell(x, monst) int x, monst; { register int tmp; if (x >= SPNUM || monst >= MAXMONST + 8 || monst < 0 || x < 0) return(0); /* bad spell or monst */ if ((tmp = spelweird[monst - 1][x]) == 0) return(0); cursors(); lprc('\n'); lprintf(spelmes[tmp], monster[monst].name); return(1); } /* * fullhit(xx) Function to return full damage against a monster(aka web) * int xx; * * Function to return hp damage to monster due to a number of full hits * Enter with the number of full hits being done */ fullhit(xx) int xx; { register int i; if (xx < 0 || xx > 20) return(0); /* fullhits are out of range */ if (c[LANCEDEATH]) return(10000); /* lance of death */ i = xx *((c[WCLASS] >> 1) + c[STRENGTH] + c[STREXTRA] - c[HARDGAME] - 12 + c[MOREDAM]); return((i >= 1) ? i : xx); } /* * direct(spnum,dam,str,arg) Routine to direct spell damage 1 square in 1 dir * int spnum,dam,arg; * char *str; * * Routine to ask for a direction to a spell and then hit the monster * Enter with the spell number in spnum, the damage to be done in dam, * lprintf format string in str, and lprintf's argument in arg. * Returns no value. */ direct(spnum, dam, str, arg) int spnum, dam, arg; char *str; { int x, y; register int m; if (spnum < 0 || spnum >= SPNUM || str == 0) return; /* bad arguments */ if (isconfuse()) return; dirsub(&x, &y); m = mitem[x][y]; if (item[x][y] == OMIRROR) { if (spnum == 3) { /* sleep */ lprcat("You fall asleep! "); beep(); fool: arg += 2; while (arg-- > 0) { parse2(); nap(1000); } return; } else if (spnum == 6) { /* web */ lprcat("You get stuck in your own web! "); beep(); goto fool; } else { lastnum = 278; lprintf(str, "spell caster(thats you)",(long) arg); beep(); losehp(dam); return; } } if (m == 0) { lprcat(" There wasn't anything there!"); return; } ifblind(x, y); if (nospell(spnum, m)) { lasthx = x; lasthy = y; return; } lprintf(str, lastmonst,(long) arg); hitm(x, y, dam); } /* * godirect(spnum,dam,str,delay,cshow) Function to perform missile attacks * int spnum,dam,delay; * char *str,cshow; * * Function to hit in a direction from a missile weapon and have it keep * on going in that direction until its power is exhausted * Enter with the spell number in spnum, the power of the weapon in hp, * lprintf format string in str, the # of milliseconds to delay between * locations in delay, and the character to represent the weapon in cshow. * Returns no value. */ godirect(spnum, dam, str, delay, cshow) int spnum, dam, delay; char *str, cshow; { register char *p; register int x, y, m; int dx, dy; if (spnum < 0 || spnum >= SPNUM || str == 0 || delay < 0) return; /* bad args */ if (isconfuse()) return; dirsub(&dx, &dy); x = dx; y = dy; dx = x - playerx; dy = y - playery; x = playerx; y = playery; while (dam > 0) { x += dx; y += dy; if ((x > MAXX - 1) || (y > MAXY - 1) || (x < 0) || (y < 0)) { dam = 0; break; /* out of bounds */ } if ((x == playerx) && (y == playery)) {/* if energy hits player */ cursors(); lprcat("\nYou are hit my your own magic!"); beep(); lastnum = 278; losehp(dam); return; } if (c[BLINDCOUNT] == 0) {/* if not blind show effect */ cursor(x + 1, y + 1); lprc(cshow); nap(delay); show1cell(x, y); } if ((m = mitem[x][y])) {/* is there a monster there? */ ifblind(x, y); if (nospell(spnum, m)) { lasthx = x; lasthy = y; return; } cursors(); lprc('\n'); lprintf(str, lastmonst); dam -= hitm(x, y, dam); show1cell(x, y); nap(1000); x -= dx; y -= dy; } else switch(*(p = &item[x][y])) { case OWALL: cursors(); lprc('\n'); lprintf(str, "wall"); if (dam >= 50 + c[HARDGAME])/* enough damage? */ if (level < MAXLEVEL + MAXVLEVEL - 1)/* not on V3 */ if ((x < MAXX - 1) && (y < MAXY - 1) && (x) && (y)) { lprcat(" The wall crumbles"); god3: *p = 0; god: know[x][y] = 0; show1cell(x, y); } god2: dam = 0; break; case OCLOSEDDOOR: cursors(); lprc('\n'); lprintf(str, "door"); if (dam >= 40) { lprcat(" The door is blasted apart"); goto god3; } goto god2; case OSTATUE: cursors(); lprc('\n'); lprintf(str, "statue"); if (c[HARDGAME] < 3) if (dam > 44) { lprcat(" The statue crumbles"); *p = OBOOK; iarg[x][y] = level; goto god; } goto god2; case OTHRONE: cursors(); lprc('\n'); lprintf(str, "throne"); if (dam > 39) { mitem[x][y] = GNOMEKING; hitp[x][y] = monster[GNOMEKING].hitpoints; *p = OTHRONE2; goto god; } goto god2; case OMIRROR: dx *= -1; dy *= -1; break; }; dam -= 3 +(c[HARDGAME] >> 1); } } /* * ifblind(x,y) Routine to put "monster" or the monster name into lastmosnt * int x,y; * * Subroutine to copy the word "monster" into lastmonst if the player is blind * Enter with the coordinates(x,y) of the monster * Returns no value. */ ifblind(x, y) int x, y; { char *p; vxy(&x, &y); /* verify correct x,y coordinates */ if (c[BLINDCOUNT]) { lastnum = 279; p = "monster"; } else { lastnum = mitem[x][y]; p = monster[lastnum].name; } strcpy(lastmonst, p); } /* * tdirect(spnum) Routine to teleport away a monster * int spnum; * * Routine to ask for a direction to a spell and then teleport away monster * Enter with the spell number that wants to teleport away * Returns no value. */ tdirect(spnum) int spnum; { int x, y; register int m; if (spnum < 0 || spnum >= SPNUM) return; /* bad args */ if (isconfuse()) return; dirsub(&x, &y); if ((m = mitem[x][y]) == 0) { lprcat(" There wasn't anything there!"); return; } ifblind(x, y); if (nospell(spnum, m)) { lasthx = x; lasthy = y; return; } fillmonst(m); mitem[x][y] = know[x][y] = 0; } /* * omnidirect(sp,dam,str) Routine to damage all monsters 1 square from player * int sp,dam; * char *str; * * Routine to cast a spell and then hit the monster in all directions * Enter with the spell number in sp, the damage done to wach square in dam, * and the lprintf string to identify the spell in str. * Returns no value. */ omnidirect(spnum, dam, str) int spnum, dam; char *str; { register int x, y, m; if (spnum < 0 || spnum >= SPNUM || str == 0) return; /* bad args */ for (x = playerx - 1; x < playerx + 2; x++) for (y = playery - 1; y < playery + 2; y++) { if (m = mitem[x][y]) if (nospell(spnum, m) == 0) { ifblind(x, y); cursors(); lprc('\n'); lprintf(str, lastmonst); hitm(x, y, dam); nap(800); } else { lasthx = x; lasthy = y; } } } /* * static dirsub(x,y) Routine to ask for direction, then modify x,y for it * int *x,*y; * * Function to ask for a direction and modify an x,y for that direction * Enter with the origination coordinates in(x,y). * Returns index into diroffx[](0-8). */ static dirsub(x, y) int *x, *y; { register int i; lprcat("\nIn What Direction? "); for (i = 0;;) switch(readchar()) { case 'b': i++; case 'n': i++; case 'y': i++; case 'u': i++; case 'h': i++; case 'k': i++; case 'l': i++; case 'j': i++; goto out; }; out: *x = playerx + diroffx[i]; *y = playery + diroffy[i]; vxy(x, y); return(i); } /* * vxy(x,y) Routine to verify/fix coordinates for being within bounds * int *x,*y; * * Function to verify x & y are within the bounds for a level * If *x or *y is not within the absolute bounds for a level, fix them so that * they are on the level. * Returns TRUE if it was out of bounds, and the *x & *y in the calling * routine are affected. */ vxy(x, y) int *x, *y; { int flag = 0; if (*x < 0) { *x = 0; flag++; } if (*y < 0) { *y = 0; flag++; } if (*x >= MAXX) { *x = MAXX - 1; flag++; } if (*y >= MAXY) { *y = MAXY - 1; flag++; } return(flag); } /* * dirpoly(spnum) Routine to ask for a direction and polymorph a monst * int spnum; * * Subroutine to polymorph a monster and ask for the direction its in * Enter with the spell number in spmun. * Returns no value. */ dirpoly(spnum) int spnum; { int x, y, m; if (spnum < 0 || spnum >= SPNUM) return; /* bad args */ if (isconfuse()) return; /* if he is confused, he can't aim his magic */ dirsub(&x, &y); if (mitem[x][y] == 0) { lprcat(" There wasn't anything there!"); return; } ifblind(x, y); if (nospell(spnum, mitem[x][y])) { lasthx = x; lasthy = y; return; } while (monster[m = mitem[x][y] = rnd(MAXMONST + 7)].genocided); hitp[x][y] = monster[m].hitpoints; show1cell(x, y); /* show the new monster */ } /* * hitmonster(x,y) Function to hit a monster at the designated coordinates * int x,y; * * This routine is used for a bash & slash type attack on a monster * Enter with the coordinates of the monster in(x,y). * Returns no value. */ hitmonster(x, y) int x, y; { register int tmp, monst, damag, flag; if (c[TIMESTOP]) return; /* not if time stopped */ vxy(&x, &y); /* verify coordinates are within range */ if ((monst = mitem[x][y]) == 0) return; hit3flag = 1; ifblind(x, y); tmp = monster[monst].armorclass + c[LEVEL] + c[DEXTERITY] + c[WCLASS] / 4 - 12; cursors(); if ((rnd(20) < tmp - c[HARDGAME]) || (rnd(71) < 5)) {/* need at least random chance to hit */ lprcat("\nYou hit"); flag = 1; damag = fullhit(1); if (damag < 9999) damag = rnd(damag) + 1; } else { lprcat("\nYou missed"); flag = 0; } lprcat(" the "); lprcat(lastmonst); if (flag) /* if the monster was hit */ if ((monst == RUSTMONSTER) || (monst == DISENCHANTRESS) || (monst == CUBE)) if (c[WIELD] > 0) if (ivenarg[c[WIELD]] > -10) { lprintf("\nYour weapon is dulled by the %s", lastmonst); beep(); --ivenarg[c[WIELD]]; } if (flag) hitm(x, y, damag); if (monst == VAMPIRE) if (hitp[x][y] < 25) { mitem[x][y] = BAT; know[x][y] = 0; } } /* * hitm(x,y,amt) Function to just hit a monster at a given coordinates * int x,y,amt; * * Returns the number of hitpoints the monster absorbed * This routine is used to specifically damage a monster at a location(x,y) * Called by hitmonster(x,y) */ hitm(x, y, amt) int x, y; register amt; { register int monst; int hpoints, amt2; vxy(&x, &y); /* verify coordinates are within range */ amt2 = amt; /* save initial damage so we can return it */ monst = mitem[x][y]; if (c[HALFDAM]) amt >>= 1; /* if half damage curse adjust damage points */ if (amt <= 0) amt2 = amt = 1; lasthx = x; lasthy = y; stealth[x][y] = 1; /* make sure hitting monst breaks stealth condition */ c[HOLDMONST] = 0; /* hit a monster breaks hold monster spell */ switch(monst) { /* if a dragon and orb(s) of dragon slaying */ case WHITEDRAGON: case REDDRAGON: case GREENDRAGON: case BRONZEDRAGON: case PLATINUMDRAGON: case SILVERDRAGON: amt *= 1 +(c[SLAYING] << 1); break; } /* invincible monster fix is here */ if (hitp[x][y] > monster[monst].hitpoints) hitp[x][y] = monster[monst].hitpoints; if ((hpoints = hitp[x][y]) <= amt) { #ifdef EXTRA c[MONSTKILLED]++; #endif lprintf("\nThe %s died!", lastmonst); raiseexperience((long) monster[monst].experience); amt = monster[monst].gold; if (amt > 0) dropgold(rnd(amt) + amt); dropsomething(monst); disappear(x, y); bottomline(); return(hpoints); } hitp[x][y] = hpoints - amt; return(amt2); } /* * hitplayer(x,y) Function for the monster to hit the player from(x,y) * int x,y; * * Function for the monster to hit the player with monster at location x,y * Returns nothing of value. */ hitplayer(x, y) int x, y; { register int dam, tmp, mster, bias; vxy(&x, &y); /* verify coordinates are within range */ lastnum = mster = mitem[x][y]; /* spirit naga's and poltergeist's do nothing if scarab of negate spirit */ if (c[NEGATESPIRIT] || c[SPIRITPRO]) if ((mster == POLTERGEIST) || (mster == SPIRITNAGA)) return; /* if undead and cube of undead control */ if (c[CUBEofUNDEAD] || c[UNDEADPRO]) if ((mster == VAMPIRE) || (mster == WRAITH) || (mster == ZOMBIE)) return; if ((know[x][y] & 1) == 0) { know[x][y] = 1; show1cell(x, y); } bias =(c[HARDGAME]) + 1; hitflag = hit2flag = hit3flag = 1; yrepcount = 0; cursors(); ifblind(x, y); if (c[INVISIBILITY]) if (rnd(33) < 20) { lprintf("\nThe %s misses wildly", lastmonst); return; } if (c[CHARMCOUNT]) if (rnd(30) + 5 * monster[mster].level - c[CHARISMA] < 30) { lprintf("\nThe %s is awestruck at your magnificence!", lastmonst); return; } if (mster == BAT) dam = 1; else { dam = monster[mster].damage; dam += rnd((int)((dam < 1) ? 1 : dam)) + monster[mster].level; } tmp = 0; if (monster[mster].attack > 0) if (((dam + bias + 8) > c[AC]) || (rnd((int)((c[AC] > 0) ? c[AC] : 1)) == 1)) { if (spattack(monster[mster].attack, x, y)) { flushall(); return; } tmp = 1; bias -= 2; cursors(); } if (((dam + bias) > c[AC]) || (rnd((int)((c[AC] > 0) ? c[AC] : 1)) == 1)) { lprintf("\n The %s hit you ", lastmonst); tmp = 1; if ((dam -= c[AC]) < 0) dam = 0; if (dam > 0) { losehp(dam); bottomhp(); flushall(); } } if (tmp == 0) lprintf("\n The %s missed ", lastmonst); } /* * dropsomething(monst) Function to create an object when a monster dies * int monst; * * Function to create an object near the player when certain monsters are killed * Enter with the monster number * Returns nothing of value. */ dropsomething(monst) int monst; { switch(monst) { case ORC: case NYMPH: case ELF: case TROGLODYTE: case TROLL: case ROTHE: case VIOLETFUNGI: case PLATINUMDRAGON: case GNOMEKING: case REDDRAGON: something(level); return; case LEPRECHAUN: if (rnd(101) >= 75) creategem(); if (rnd(5) == 1) dropsomething(LEPRECHAUN); return; } } /* * dropgold(amount) Function to drop some gold around player * int amount; * * Enter with the number of gold pieces to drop * Returns nothing of value. */ dropgold(amount) register int amount; { if (amount > 250) createitem(OMAXGOLD, amount / 100); else createitem(OGOLDPILE, amount); } /* * something(level) Function to create a random item around player * int level; * * Function to create an item from a designed probability around player * Enter with the cave level on which something is to be dropped * Returns nothing of value. */ something(level) int level; { register int j; int i; if (level < 0 || level > MAXLEVEL + MAXVLEVEL) return; /* correct level? */ if (rnd(101) < 8) something(level); /* possibly more than one item */ j = newobject(level, &i); createitem(j, i); } /* * newobject(lev,i) Routine to return a randomly selected new object * int lev,*i; * * Routine to return a randomly selected object to be created * Returns the object number created, and sets *i for its argument * Enter with the cave level and a pointer to the items arg */ static char nobjtab[] = { 0, OSCROLL, OSCROLL, OSCROLL, OSCROLL, OPOTION, OPOTION, OPOTION, OPOTION, OGOLDPILE, OGOLDPILE, OGOLDPILE, OGOLDPILE, OBOOK, OBOOK, OBOOK, OBOOK, ODAGGER, ODAGGER, ODAGGER, OLEATHER, OLEATHER, OLEATHER, OREGENRING, OPROTRING, OENERGYRING, ODEXRING, OSTRRING, OSPEAR, OBELT, ORING, OSTUDLEATHER, OSHIELD, OFLAIL, OCHAIN, O2SWORD, OPLATE, OLONGSWORD }; newobject(lev, i) register int lev, *i; { register int tmp = 32, j; if (level < 0 || level > MAXLEVEL + MAXVLEVEL) return(0); /* correct level? */ if (lev > 6) tmp = 37; else if (lev > 4) tmp = 35; j = nobjtab[tmp = rnd(tmp)];/* the object type */ switch(tmp) { case 1: case 2: case 3: case 4: *i = newscroll(); break; case 5: case 6: case 7: case 8: *i = newpotion(); break; case 9: case 10: case 11: case 12: *i = rnd((lev + 1) * 10) + lev * 10 + 10; break; case 13: case 14: case 15: case 16: *i = lev; break; case 17: case 18: case 19: if (!(*i = newdagger())) return(0); break; case 20: case 21: case 22: if (!(*i = newleather())) return(0); break; case 23: case 32: case 35: *i = rund(lev / 3 + 1); break; case 24: case 26: *i = rnd(lev / 4 + 1); break; case 25: *i = rund(lev / 4 + 1); break; case 27: *i = rnd(lev / 2 + 1); break; case 30: case 33: *i = rund(lev / 2 + 1); break; case 28: *i = rund(lev / 3 + 1); if (*i == 0) return(0); break; case 29: case 31: *i = rund(lev / 2 + 1); if (*i == 0) return(0); break; case 34: *i = newchain(); break; case 36: *i = newplate(); break; case 37: *i = newsword(); break; } return(j); } /* * spattack(atckno,xx,yy) Function to process special attacks from monsters * int atckno,xx,yy; * * Enter with the special attack number, and the coordinates(xx,yy) * of the monster that is special attacking * Returns 1 if must do a show1cell(xx,yy) upon return, 0 otherwise * * atckno monster effect * --------------------------------------------------- * 0 none * 1 rust monster eat armor * 2 hell hound breathe light fire * 3 dragon breathe fire * 4 giant centipede weakening sing * 5 white dragon cold breath * 6 wraith drain level * 7 waterlord water gusher * 8 leprechaun steal gold * 9 disenchantress disenchant weapon or armor * 10 ice lizard hits with barbed tail * 11 umber hulk confusion * 12 spirit naga cast spells taken from special attacks * 13 platinum dragon psionics * 14 nymph steal objects * 15 bugbear bite * 16 osequip bite * * char rustarm[ARMORTYPES][2]; * special array for maximum rust damage to armor from rustmonster * format is: { armor type , minimum attribute */ #define ARMORTYPES 6 static char rustarm[ARMORTYPES][2] = { OSTUDLEATHER, -2, ORING, -4, OCHAIN, -5, OSPLINT, -6, OPLATE, -8, OPLATEARMOR, -9 }; static char spsel[] = { 1, 2, 3, 5, 6, 8, 9, 11, 13, 14 }; spattack(x, xx, yy) int x, xx, yy; { register int i, j = 0, k, m; register char *p = 0; if (c[CANCELLATION]) return(0); vxy(&xx, &yy); /* verify x & y coordinates */ switch(x) { case 1: /* rust your armor, j=1 when rusting has occurred */ m = k = c[WEAR]; if ((i = c[SHIELD]) != -1) if (--ivenarg[i] < -1) ivenarg[i] = -1; else j = 1; if ((j == 0) && (k != -1)) { m = iven[k]; for (i = 0; i < ARMORTYPES; i++) if (m == rustarm[i][0]) {/* find his armor in table */ if (--ivenarg[k] < rustarm[i][1]) ivenarg[k] = rustarm[i][1]; else j = 1; break; } } if (j == 0) /* if rusting did not occur */ switch(m) { case OLEATHER: p = "\nThe %s hit you -- Your lucky you have leather on"; break; case OSSPLATE: p = "\nThe %s hit you -- Your fortunate to have stainless steel armor!"; break; } else { beep(); p = "\nThe %s hit you -- your armor feels weaker"; } break; case 2: i = rnd(15) + 8 - c[AC]; spout: p = "\nThe %s breathes fire at you!"; if (c[FIRERESISTANCE]) p = "\nThe %s's flame doesn't phase you!"; else spout2: if (p) { lprintf(p, lastmonst); beep(); } checkloss(i); return(0); case 3: i = rnd(20) + 25 - c[AC]; goto spout; case 4: if (c[STRENGTH] > 3) { p = "\nThe %s stung you! You feel weaker"; beep(); --c[STRENGTH]; } else p = "\nThe %s stung you!"; break; case 5: p = "\nThe %s blasts you with his cold breath"; i = rnd(15) + 18 - c[AC]; goto spout2; case 6: lprintf("\nThe %s drains you of your life energy!", lastmonst); loselevel(); beep(); return(0); case 7: p = "\nThe %s got you with a gusher!"; i = rnd(15) + 25 - c[AC]; goto spout2; case 8: if (c[NOTHEFT]) return(0); /* he has a device of no theft */ if (c[GOLD]) { p = "\nThe %s hit you -- Your purse feels lighter"; if (c[GOLD] > 32767) c[GOLD] >>= 1; else c[GOLD] -= rnd((int)(1 +(c[GOLD] >> 1))); if (c[GOLD] < 0) c[GOLD] = 0; } else p = "\nThe %s couldn't find any gold to steal"; lprintf(p, lastmonst); disappear(xx, yy); beep(); bottomgold(); return(1); case 9: for (j = 50;;) { /* disenchant */ i = rund(26); m = iven[i]; /* randomly select item */ if (m > 0 && ivenarg[i] > 0 && m != OSCROLL && m != OPOTION) { if ((ivenarg[i] -= 3) < 0) ivenarg[i] = 0; lprintf("\nThe %s hits you -- you feel a sense of loss", lastmonst); srcount = 0; beep(); show3(i); bottomline(); return(0); } if (--j <= 0) { p = "\nThe %s nearly misses"; break; } break; } break; case 10: p = "\nThe %s hit you with his barbed tail"; i = rnd(25) - c[AC]; goto spout2; case 11: p = "\nThe %s has confused you"; beep(); c[CONFUSE] += 10 + rnd(10); break; case 12: /* performs any number of other special attacks */ return(spattack(spsel[rund(10)], xx, yy)); case 13: p = "\nThe %s flattens you with his psionics!"; i = rnd(15) + 30 - c[AC]; goto spout2; case 14: if (c[NOTHEFT]) return(0); /* he has device of no theft */ if (emptyhanded() == 1) { p = "\nThe %s couldn't find anything to steal"; break; } lprintf("\nThe %s picks your pocket and takes:", lastmonst); beep(); if (stealsomething() == 0) lprcat(" nothing"); disappear(xx, yy); bottomline(); return(1); case 15: i = rnd(10) + 5 - c[AC]; spout3: p = "\nThe %s bit you!"; goto spout2; case 16: i = rnd(15) + 10 - c[AC]; goto spout3; }; if (p) { lprintf(p, lastmonst); bottomline(); } return(0); } /* * checkloss(x) Routine to subtract hp from user and flag bottomline display * int x; * * Routine to subtract hitpoints from the user and flag the bottomline display * Enter with the number of hit points to lose * Note: if x > c[HP] this routine could kill the player! */ checkloss(x) int x; { if (x > 0) { losehp(x); bottomhp(); } } /* * annihilate() Routine to annihilate all monsters around player(playerx,playery) * * Gives player experience, but no dropped objects * Returns the experience gained from all monsters killed */ annihilate() { int i,j; register long k; register char *p; for (k = 0, i = playerx - 1; i <= playerx + 1; i++) for (j = playery - 1; j <= playery + 1; j++) if (!vxy(&i, &j)) /* if not out of bounds */ if (*(p = &mitem[i][j]))/* if a monster there */ if (*p < DEMONLORD + 2) { k += monster[*p].experience; *p = know[i][j] = 0; } else { lprintf("\nThe %s barely escapes being annihilated!", monster[*p].name); hitp[i][j] =(hitp[i][j] >> 1) + 1;/* lose half hit points */ } if (k > 0) { lprcat("\nYou hear loud screams of agony!"); raiseexperience((long) k); } return(k); } /* * newsphere(x,y,dir,lifetime) Function to create a new sphere of annihilation * int x,y,dir,lifetime; * * Enter with the coordinates of the sphere in x,y * the direction(0-8 diroffx format) in dir, and the lifespan of the * sphere in lifetime(in turns) * Returns the number of spheres currently in existence */ newsphere(x, y, dir, life) int x, y, dir, life; { int m; struct sphere *sp; if (((sp =(struct sphere *) malloc(sizeof(struct sphere)))) == 0) return(c[SPHCAST]);/* can't malloc, therefore failure */ if (dir >= 9) dir = 0; /* no movement if direction not found */ if (level == 0) vxy(&x, &y); /* don't go out of bounds */ else { if (x < 1) x = 1; if (x >= MAXX - 1) x = MAXX - 2; if (y < 1) y = 1; if (y >= MAXY - 1) y = MAXY - 2; } if ((m = mitem[x][y]) >= DEMONLORD + 4) {/* demons dispel spheres */ know[x][y] = 1; show1cell(x, y); /* show the demon(ha ha) */ cursors(); lprintf("\nThe %s dispels the sphere!", monster[m].name); beep(); rmsphere(x, y); /* remove any spheres that are here */ return(c[SPHCAST]); } if (m == DISENCHANTRESS) { /* disenchantress cancels spheres */ cursors(); lprintf("\nThe %s causes cancellation of the sphere!", monster[m].name); beep(); boom: sphboom(x, y); /* blow up stuff around sphere */ rmsphere(x, y); /* remove any spheres that are here */ return(c[SPHCAST]); } if (c[CANCELLATION]) { /* cancellation cancels spheres */ cursors(); lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!"); beep(); goto boom; } if (item[x][y] == OANNIHILATION) {/* collision of spheres detonates spheres */ cursors(); lprcat("\nTwo spheres of annihilation collide! You hear a great earth shaking blast!"); beep(); rmsphere(x, y); goto boom; } if (playerx == x && playery == y) {/* collision of sphere and player! */ cursors(); lprcat("\nYou have been enveloped by the zone of nothingness!\n"); beep(); rmsphere(x, y); /* remove any spheres that are here */ nap(4000); died(258); } item[x][y] = OANNIHILATION; mitem[x][y] = 0; know[x][y] = 1; show1cell(x, y); /* show the new sphere */ sp -> x = x; sp -> y = y; sp -> lev = level; sp -> dir = dir; sp -> lifetime = life; sp -> p = 0; if (spheres == 0) spheres = sp; /* if first node in the sphere list */ else { /* add sphere to beginning of linked list */ sp -> p = spheres; spheres = sp; } return(++c[SPHCAST]); /* one more sphere in the world */ } /* * rmsphere(x,y) Function to delete a sphere of annihilation from list * int x,y; * * Enter with the coordinates of the sphere(on current level) * Returns the number of spheres currently in existence */ rmsphere(x, y) int x,y; { register struct sphere *sp,*sp2 = 0; for (sp = spheres; sp; sp2 = sp, sp = sp -> p) if (level == sp -> lev) /* is sphere on this level? */ if ((x == sp -> x) && (y == sp -> y)) {/* locate sphere at this location */ item[x][y] = mitem[x][y] = 0; know[x][y] = 1; show1cell(x, y);/* show the now missing sphere */ --c[SPHCAST]; if (sp == spheres) { sp2 = sp; spheres = sp -> p; free((char *) sp2); } else { sp2 -> p = sp -> p; free((char *) sp); } break; } return(c[SPHCAST]); /* return number of spheres in the world */ } /* * sphboom(x,y) Function to perform the effects of a sphere detonation * int x,y; * * Enter with the coordinates of the blast, Returns no value */ sphboom(x, y) int x, y; { register int i, j; if (c[HOLDMONST]) c[HOLDMONST] = 1; if (c[CANCELLATION]) c[CANCELLATION] = 1; for (j = max(1, x - 2); j < min(x + 3, MAXX - 1); j++) for (i = max(1, y - 2); i < min(y + 3, MAXY - 1); i++) { item[j][i] = mitem[j][i] = 0; show1cell(j, i); if (playerx == j && playery == i) { cursors(); beep(); lprcat("\nYou were too close to the sphere!"); nap(3000); died(283); /* player killed in explosion */ } } } /* * genmonst() Function to ask for monster and genocide from game * * This is done by setting a flag in the monster[] structure */ genmonst() { register int i,j; cursors(); lprcat("\nGenocide what monster? "); for (i = 0;(!isalpha(i)) && (i != ' '); i = readchar()); lprc(i); for (j = 0; j < MAXMONST; j++)/* search for the monster type */ if (monstnamelist[j] == i) {/* have we found it? */ monster[j].genocided = 1;/* genocided from game */ lprintf(" There will be no more %s's", monster[j].name); /* now wipe out monsters on this level */ newcavelevel(level); draws(0, MAXX, 0, MAXY); bot_linex(); return; } lprcat(" You sense failure!"); } SHAR_EOF if test 45763 -ne "`wc -c < 'monster.c'`" then echo shar: error transmitting "'monster.c'" '(should have been 45763 characters)' fi fi # end of overwriting check echo shar: extracting "'regen.c'" '(3839 characters)' if test -f 'regen.c' then echo shar: will not over-write existing file "'regen.c'" else cat << \SHAR_EOF > 'regen.c' /* regen.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" /* ******* REGEN() ******* regen() subroutine to regenerate player hp and spells */ regen () { register int i, flag; register long *d; d = c; #ifdef EXTRA d[MOVESMADE]++; #endif if (d[TIMESTOP]) { if (--d[TIMESTOP] <= 0) bottomline (); return; } /* for stop time spell */ flag = 0; if (d[STRENGTH] < 3) { d[STRENGTH] = 3; flag = 1; } if ((d[HASTESELF] == 0) || ((d[HASTESELF] & 1) == 0)) gtime++; if (d[HP] != d[HPMAX]) if (d[REGENCOUNTER]-- <= 0) {/* regenerate hit points */ d[REGENCOUNTER] = 22 + (d[HARDGAME] << 1) - d[LEVEL]; if ((d[HP] += d[REGEN]) > d[HPMAX]) d[HP] = d[HPMAX]; bottomhp (); } if (d[SPELLS] < d[SPELLMAX])/* regenerate spells */ if (d[ECOUNTER]-- <= 0) { d[ECOUNTER] = 100 + 4 * (d[HARDGAME] - d[LEVEL] - d[ENERGY]); d[SPELLS]++; bottomspell (); } if (d[HERO]) if (--d[HERO] <= 0) { for (i = 0; i < 6; i++) d[i] -= 10; flag = 1; } if (d[ALTPRO]) if (--d[ALTPRO] <= 0) { d[MOREDEFENSES] -= 3; flag = 1; } if (d[PROTECTIONTIME]) if (--d[PROTECTIONTIME] <= 0) { d[MOREDEFENSES] -= 2; flag = 1; } if (d[DEXCOUNT]) if (--d[DEXCOUNT] <= 0) { d[DEXTERITY] -= 3; flag = 1; } if (d[STRCOUNT]) if (--d[STRCOUNT] <= 0) { d[STREXTRA] -= 3; flag = 1; } if (d[BLINDCOUNT]) if (--d[BLINDCOUNT] <= 0) { cursors (); lprcat ("\nThe blindness lifts "); beep (); } if (d[CONFUSE]) if (--d[CONFUSE] <= 0) { cursors (); lprcat ("\nYou regain your senses"); beep (); } if (d[GIANTSTR]) if (--d[GIANTSTR] <= 0) { d[STREXTRA] -= 20; flag = 1; } if (d[CHARMCOUNT]) if ((--d[CHARMCOUNT]) <= 0) flag = 1; if (d[INVISIBILITY]) if ((--d[INVISIBILITY]) <= 0) flag = 1; if (d[CANCELLATION]) if ((--d[CANCELLATION]) <= 0) flag = 1; if (d[WTW]) if ((--d[WTW]) <= 0) flag = 1; if (d[HASTESELF]) if ((--d[HASTESELF]) <= 0) flag = 1; if (d[AGGRAVATE]) --d[AGGRAVATE]; if (d[SCAREMONST]) if ((--d[SCAREMONST]) <= 0) flag = 1; if (d[STEALTH]) if ((--d[STEALTH]) <= 0) flag = 1; if (d[AWARENESS]) --d[AWARENESS]; if (d[HOLDMONST]) if ((--d[HOLDMONST]) <= 0) flag = 1; if (d[HASTEMONST]) --d[HASTEMONST]; if (d[FIRERESISTANCE]) if ((--d[FIRERESISTANCE]) <= 0) flag = 1; if (d[GLOBE]) if (--d[GLOBE] <= 0) { d[MOREDEFENSES] -= 10; flag = 1; } if (d[SPIRITPRO]) if (--d[SPIRITPRO] <= 0) flag = 1; if (d[UNDEADPRO]) if (--d[UNDEADPRO] <= 0) flag = 1; if (d[HALFDAM]) if (--d[HALFDAM] <= 0) { cursors (); lprcat ("\nYou now feel better "); beep (); } if (d[SEEINVISIBLE]) if (--d[SEEINVISIBLE] <= 0) { monstnamelist[INVISIBLESTALKER] = ' '; cursors (); lprcat ("\nYou feel your vision return to normal"); beep (); } if (d[ITCHING]) { if (d[ITCHING] > 1) if ((d[WEAR] != -1) || (d[SHIELD] != -1)) if (rnd (100) < 50) { d[WEAR] = d[SHIELD] = -1; cursors (); lprcat ("\nThe hysteria of itching forces you to remove your armor!"); beep (); recalc (); bottomline (); } if (--d[ITCHING] <= 0) { cursors (); lprcat ("\nYou now feel the irritation subside!"); beep (); } } if (d[CLUMSINESS]) { if (d[WIELD] != -1) if (d[CLUMSINESS] > 1) if (item[playerx][playery] == 0)/* only if nothing there */ if (rnd (100) < 33)/* drop your weapon due to clumsiness */ drop_object ((int) d[WIELD]); if (--d[CLUMSINESS] <= 0) { cursors (); lprcat ("\nYou now feel less awkward!"); beep (); } } if (flag) bottomline (); } SHAR_EOF if test 3839 -ne "`wc -c < 'regen.c'`" then echo shar: error transmitting "'regen.c'" '(should have been 3839 characters)' fi fi # end of overwriting check echo shar: extracting "'savelev.c'" '(852 characters)' if test -f 'savelev.c' then echo shar: will not over-write existing file "'savelev.c'" else cat << \SHAR_EOF > 'savelev.c' /* savelev.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" /* * routine to save the present level into storage */ savelevel () { register int x,y,t; t = level * (MAXX*MAXY); for (x = 0; x < MAXX; x++) { t += MAXY; for (y = 0; y < MAXY; y++) { cell[t+y].item = item[x][y]; cell[t+y].iarg = iarg[x][y]; cell[t+y].know = know[x][y]; cell[t+y].mitem = mitem[x][y]; cell[t+y].hitp = hitp[x][y]; } } } /* * routine to restore a level from storage */ getlevel () { register int x,y,t; t = level * (MAXX*MAXY); for (x = 0; x < MAXX; x++) { t += MAXY; for (y = 0; y < MAXY; y++) { item[x][y] = cell[t+y].item; iarg[x][y] = cell[t+y].iarg; know[x][y] = cell[t+y].know; mitem[x][y] = cell[t+y].mitem; hitp[x][y] = cell[t+y].hitp; } } } SHAR_EOF if test 852 -ne "`wc -c < 'savelev.c'`" then echo shar: error transmitting "'savelev.c'" '(should have been 852 characters)' fi fi # end of overwriting check echo shar: extracting "'signal.c'" '(2848 characters)' if test -f 'signal.c' then echo shar: will not over-write existing file "'signal.c'" else cat << \SHAR_EOF > 'signal.c' #include #include "header.h" /* "Larn is copyrighted 1986 by Noah Morgan.\n" */ #define BIT(a)(1<<((a)-1)) /* text to be displayed if ^C during intro screen */ static s2choose() { cursor(1, 24); lprcat("Press "); setbold(); lprcat("return"); resetbold(); lprcat(" to continue: "); lflush(); } /* what to do for a ^C */ static cntlc() { if (nosignal) return; /* don't do anything if inhibited */ signal(SIGQUIT, SIG_IGN); signal(SIGINT, SIG_IGN); quit(); if (predostuff == 1) s2choose(); else showplayer(); lflush(); signal(SIGQUIT, cntlc); signal(SIGINT, cntlc); } /* * subroutine to save the game if a hangup signal */ static sgam() { savegame(savefilename); wizard = 1; died(-257); /* hangup signal */ } /* * subroutine to issue the needed signal traps - called from main() */ static sigill() { sigpanic(SIGILL); } static sigtrap() { sigpanic(SIGTRAP); } static sigiot() { sigpanic(SIGIOT); } static sigemt() { sigpanic(SIGEMT); } static sigfpe() { sigpanic(SIGFPE); } static sigbus() { sigpanic(SIGBUS); } static sigsegv() { sigpanic(SIGSEGV); } static sigsys() { sigpanic(SIGSYS); } static sigpipe() { sigpanic(SIGPIPE); } static sigterm() { sigpanic(SIGTERM); } sigsetup() { signal(SIGQUIT, cntlc); signal(SIGINT, cntlc); signal(SIGKILL, SIG_IGN); signal(SIGHUP, sgam); signal(SIGILL, sigill); signal(SIGTRAP, sigtrap); signal(SIGIOT, sigiot); signal(SIGEMT, sigemt); signal(SIGFPE, sigfpe); signal(SIGBUS, sigbus); signal(SIGSEGV, sigsegv); signal(SIGSYS, sigsys); signal(SIGPIPE, sigpipe); signal(SIGTERM, sigterm); } static char *signame[NSIG] = { "", "SIGHUP", /* 1 hangup */ "SIGINT", /* 2 interrupt */ "SIGQUIT", /* 3 quit */ "SIGILL", /* 4 illegal instruction(not reset when caught) */ "SIGTRAP", /* 5 trace trap(not reset when caught) */ "SIGIOT", /* 6 IOT instruction */ "SIGEMT", /* 7 EMT instruction */ "SIGFPE", /* 8 floating point exception */ "SIGKILL", /* 9 kill(cannot be caught or ignored) */ "SIGBUS", /* 10 bus error */ "SIGSEGV", /* 11 segmentation violation */ "SIGSYS", /* 12 bad argument to system call */ "SIGPIPE", /* 13 write on a pipe with no one to read it */ "SIGALRM", /* 14 alarm clock */ "SIGTERM" /* 15 software termination signal from kill */ }; /* * routine to process a fatal error signal */ static sigpanic(sig) int sig; { char buf[128]; signal(sig, SIG_DFL); sprintf(buf, "\nLarn - Panic! Signal %d received [%s]", sig, signame[sig]); write(2, buf, strlen(buf)); sleep(2); sncbr(); savegame(savefilename); kill(getpid(), sig); /* this will terminate us */ } SHAR_EOF if test 2848 -ne "`wc -c < 'signal.c'`" then echo shar: error transmitting "'signal.c'" '(should have been 2848 characters)' fi fi # end of overwriting check echo shar: extracting "'tok.c'" '(5032 characters)' if test -f 'tok.c' then echo shar: will not over-write existing file "'tok.c'" else cat << \SHAR_EOF > 'tok.c' /* tok.c Larn is copyrighted 1986 by Noah Morgan. */ #include "header.h" static char lastok = 0; globaldef int yrepcount = 0,dayplay = 0; #define MAXUM 52 /* maximum number of user re-named monsters */ #define MAXMNAME 40 /* max length of a monster re-name */ static char usermonster[MAXUM][MAXMNAME];/* the user named monster name goes here */ static char usermpoint = 0; /* the user monster pointer */ /* lexical analyzer for larn */ yylex () { char cc; int ic; if (hit2flag) { hit2flag = 0; yrepcount = 0; return (' '); } if (yrepcount > 0) { --yrepcount; return (lastok); } else yrepcount = 0; if (yrepcount == 0) { bottomdo (); showplayer (); } /* show where the player is */ lflush (); while (1) { c[BYTESIN]++; if (ckpflag) /* check for periodic checkpointing */ if ((c[BYTESIN] % 400) == 0) { savegame (ckpfile); #ifdef TIMECHECK if (dayplay == 0) if (playable ()) { cursor (1, 19); lprcat ("\nSorry, but it is now time for work. Your game has been saved.\n"); beep (); lflush (); savegame (savefilename); wizard = nomove = 1; sleep (4); died (-257); } #endif TIMECHECK } if ((cc = KeySense(0)) == -1) return (lastok = -1); if (cc == 'Y' - 64) { /* control Y -- shell escape */ resetscroll (); clear(); /* scrolling region, home, clear, no attributes */ system(0); setscroll (); return (lastok = 'L' - 64); /* redisplay screen */ } if ((cc <= '9') && (cc >= '0')) { yrepcount = yrepcount * 10 + cc - '0'; } else { if (yrepcount > 0) --yrepcount; return (lastok = cc); } } } /* * flushall() Function to flush all type-ahead in the input buffer */ flushall () { /* if keyboard input buffer is too big, flush some of it */ while (KeySense(0) >= 0); } /* function to set the desired hardness enter with hard= -1 for default hardness, else any desired hardness */ sethard (hard) int hard; { register int j,k,i; j = c[HARDGAME]; hashewon (); if (restorflag == 0) { /* don't set c[HARDGAME] if restoring game */ if (hard >= 0) c[HARDGAME] = hard; } else c[HARDGAME] = j; /* set c[HARDGAME] to proper value if restoring game */ if (k = c[HARDGAME]) for (j = 0; j <= MAXMONST + 8; j++) { i = ((6 + k) * monster[j].hitpoints + 1) / 6; monster[j].hitpoints = (i < 0) ? 32767 : i; i = ((6 + k) * monster[j].damage + 1) / 5; monster[j].damage = (i > 127) ? 127 : i; i = (10 * monster[j].gold) / (10 + k); monster[j].gold = (i > 32767) ? 32767 : i; i = monster[j].armorclass - k; monster[j].armorclass = (i < -127) ? -127 : i; i = (7 * monster[j].experience) / (7 + k) + 1; monster[j].experience = (i <= 0) ? 1 : i; } } /* function to read and process the larn options file */ readopts () { register char *i; register int j,k; int flag = 1; /* set to 0 if he specifies a name for his character */ if (lopen (optsfile) < 0) { strcpy (logname, loginname); return; /* user name if no character name */ } i = " "; while (*i) { if ((i = (char *) lgetw ()) == 0) break; /* check for EOF */ while ((*i == ' ') || (*i == '\t')) i++; /* eat leading whitespace */ switch (*i) { case 'b': if (strcmp (i, "bold-objects") == 0) boldon = 1; break; case 'e': if (strcmp (i, "enable-checkpointing") == 0) ckpflag = 1; break; case 'i': if (strcmp (i, "inverse-objects") == 0) boldon = 0; break; case 'f': if (strcmp (i, "female") == 0) sex = 0; /* male or female */ break; case 'm': if (strcmp (i, "monster:") == 0) {/* name favorite monster */ if ((i = lgetw ()) == 0) break; if (strlen (i) >= MAXMNAME) i[MAXMNAME - 1] = 0; strcpy (usermonster[usermpoint], i); if (usermpoint >= MAXUM) break; /* defined all of em */ if (isalpha (j = usermonster[usermpoint][0])) { for (k = 1; k < MAXMONST + 8; k++)/* find monster */ if (monstnamelist[k] == j) { monster[k].name = &usermonster[usermpoint++][0]; break; } } } else if (strcmp (i, "male") == 0) sex = 1; break; case 'n': if (strcmp (i, "name:") == 0) {/* defining players name */ if ((i = lgetw ()) == 0) break; if (strlen (i) >= LOGNAMESIZE) i[LOGNAMESIZE - 1] = 0; strcpy (logname, i); flag = 0; } else if (strcmp (i, "no-introduction") == 0) nowelcome = 1; else if (strcmp (i, "no-beep") == 0) nobeep = 1; break; case 'p': if (strcmp (i, "play-day-play") == 0) dayplay = 1; break; case 's': if (strcmp (i, "savefile:") == 0) {/* defining savefilename */ if ((i = lgetw ()) == 0) break; if (strlen (i) >= SAVEFILENAMESIZE)/* avoid overflow */ i[SAVEFILENAMESIZE - 1] = 0; strcpy (savefilename, i); flag = 0; } break; }; } if (flag) strcpy (logname, loginname); } SHAR_EOF if test 5032 -ne "`wc -c < 'tok.c'`" then echo shar: error transmitting "'tok.c'" '(should have been 5032 characters)' fi fi # end of overwriting check # End of shell archive exit 0