#include "header.h"
struct isave {
char type;
char id;
short arg;
};
static int cgood(int, int, int, int);
static void speldamage(int);
static void loseint(void);
static long isconfuse(void);
static int nospell(int, int);
static int fullhit(int);
static void direct(int, int, const char *, int);
static void ifblind(int, int);
static void tdirect(int);
static void omnidirect(int, int, const char *);
static int dirsub(int *, int *);
static void dirpoly(int);
static void dropsomething(int);
static int spattack(int, int, int);
static void sphboom(int, int);
static void genmonst(void);
void
createmonster(int mon)
{
int x, y, k, i;
if (mon < 1 || mon > MAXMONST + 8) {
beep();
lprintf("\ncan't createmonst(%d)\n", (long)mon);
nap(3000);
return;
}
while (mon < MAXMONST && monster[mon].genocided)
mon++;
for (k = rnd(8), i = -8; i < 0; i++, k++) {
if (k > 8)
k = 1;
x = playerx + diroffx[k];
y = playery + diroffy[k];
if (cgood(x, y, 0, 1)) {
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;
}
}
}
static int
cgood(int x, int y, int itm, int monst)
{
if ((y >= 0) && (y <= MAXY - 1) && (x >= 0) && (x <= MAXX - 1))
if (item[x][y] != OWALL)
if (itm == 0 || (item[x][y] == 0))
if (monst == 0 || (mitem[x][y] == 0))
if ((level != 1) || (x != 33) ||
(y != MAXY - 1))
return (1);
return (0);
}
void
createitem(int it, int arg)
{
int x, y, k, i;
if (it >= MAXOBJ)
return;
for (k = rnd(8), i = -8; i < 0; i++, k++) {
if (k > 8)
k = 1;
x = playerx + diroffx[k];
y = playery + diroffy[k];
if (cgood(x, y, 1, 0)) {
item[x][y] = it;
know[x][y] = 0;
iarg[x][y] = arg;
return;
}
}
}
static const char eys[] = "\nEnter your spell: ";
void
cast(void)
{
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 = getchr()) == 'D') {
seemagic(-1);
cursors();
lprcat(eys);
}
if (a == '\33')
goto over;
if ((b = getchr()) == '\33')
goto over;
if ((d = getchr()) == '\33') {
over: lprcat(aborted);
c[SPELLS]++;
return;
}
#ifdef EXTRA
c[SPELLSCAST]++;
#endif
for (lprc('\n'), j = -1, i = 0; i < SPNUM; i++)
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();
}
static void
speldamage(int x)
{
int i, j, clev;
int xl, xh, yl, yh;
char *p, *kn, *pm;
const char *cp;
if (x >= SPNUM)
return;
if (c[TIMESTOP]) {
lprcat(" It didn't seem to work");
return;
}
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) {
case 0:
if (c[PROTECTIONTIME] == 0)
c[MOREDEFENSES] += 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, '+');
return;
case 2:
if (c[DEXCOUNT] == 0)
c[DEXTERITY] += 3;
c[DEXCOUNT] += 400;
return;
case 3:
i = rnd(3) + 1;
cp = " While the %s slept, you smashed it %d times";
ws: direct(x, fullhit(i), cp, i);
return;
case 4:
c[CHARMCOUNT] += c[CHARISMA] << 1;
return;
case 5:
godirect(x, rnd(10) + 15 + clev, " The sound damages the %s", 70, '@');
return;
case 6:
i = rnd(3) + 2;
cp = " While the %s is entangled, you hit %d times";
goto ws;
case 7:
if (c[STRCOUNT] == 0)
c[STREXTRA] += 3;
c[STRCOUNT] += 150 + rnd(100);
return;
case 8:
yl = playery - 5;
yh = playery + 6;
xl = playerx - 15;
xh = playerx + 16;
vxy(&xl, &yl);
vxy(&xh, &yh);
for (i = yl; i <= yh; i++)
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;
case 10:
c[BLINDCOUNT] = 0;
return;
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:
for (j = i = 0; i < 26; i++)
if (iven[i] == OAMULET)
j += 1 + ivenarg[i];
c[INVISIBILITY] += (j << 7) + 12;
return;
case 14:
godirect(x, rnd(25 + clev) + 25 + clev, " The fireball hits the %s", 40, '*');
return;
case 15:
godirect(x, rnd(25) + 20 + clev, " Your cone of cold strikes the %s", 60, 'O');
return;
case 16:
dirpoly(x);
return;
case 17:
c[CANCELLATION] += 5 + clev;
return;
case 18:
c[HASTESELF] += 7 + clev;
return;
case 19:
omnidirect(x, 30 + rnd(10), " The %s gasps for air");
return;
case 20:
xh = min(playerx + 1, MAXX - 2);
yh = min(playery + 1, MAXY - 2);
for (i = max(playerx - 1, 1); i <= xh; i++)
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;
}
}
return;
case 21:
direct(x, 100 + clev, " The %s shrivels up", 0);
return;
case 22:
godirect(x, rnd(25) + 20 + (clev << 1), " A lightning bolt hits the %s", 1, '~');
return;
case 23:
i = min(c[HP] - 1, c[HPMAX] / 2);
direct(x, i + i, "", 0);
c[HP] -= i;
return;
case 24:
if (c[GLOBE] == 0)
c[MOREDEFENSES] += 10;
c[GLOBE] += 200;
loseint();
return;
case 25:
omnidirect(x, 32 + clev, " The %s struggles for air in your 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);
else
lprcat(" It didn't work");
return;
case 27:
c[SCAREMONST] += rnd(10) + clev;
return;
case 28:
c[HOLDMONST] += rnd(10) + clev;
return;
case 29:
c[TIMESTOP] += rnd(20) + (clev << 1);
return;
case 30:
tdirect(x);
return;
case 31:
omnidirect(x, 35 + rnd(10) + clev, " The %s cringes from the flame");
return;
case 32:
if ((rnd(23) == 5) && (wizard == 0)) {
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);
newsphere(xl, yl, i, rnd(20) + 11);
return;
case 33:
genmonst();
spelknow[33] = 0;
loseint();
return;
case 34:
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);
return;
case 35:
c[WTW] += rnd(10) + 5;
return;
case 36:
{
struct isave *save;
int sc;
sc = 0;
save = malloc(sizeof(struct isave) * MAXX * MAXY * 2);
for (j = 0; j < MAXY; j++)
for (i = 0; i < MAXX; i++) {
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) {
--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 {
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(save);
positionplayer();
return;
}
case 37:
larn_adjtime(-99999L);
spelknow[37] = 0;
loseint();
return;
default:
lprintf(" spell %d not available!", (long)x);
beep();
return;
}
}
static void
loseint(void)
{
if (--c[INTELLIGENCE] < 3)
c[INTELLIGENCE] = 3;
}
static long
isconfuse(void)
{
if (c[CONFUSE]) {
lprcat(" You can't aim your magic!");
beep();
}
return (c[CONFUSE]);
}
static int
nospell(int x, int monst)
{
int tmp;
if (x >= SPNUM || monst >= MAXMONST + 8 || monst < 0 || x < 0)
return (0);
if ((tmp = spelweird[monst - 1][x]) == 0)
return (0);
cursors();
lprc('\n');
lprintf(spelmes[tmp], monster[monst].name);
return (1);
}
static int
fullhit(int xx)
{
int i;
if (xx < 0 || xx > 20)
return (0);
if (c[LANCEDEATH])
return (10000);
i = xx * ((c[WCLASS] >> 1) + c[STRENGTH] + c[STREXTRA] - c[HARDGAME] - 12 + c[MOREDAM]);
return ((i >= 1) ? i : xx);
}
static void
direct(int spnum, int dam, const char *str, int arg)
{
int x, y;
int m;
if (spnum < 0 || spnum >= SPNUM || str == NULL)
return;
if (isconfuse())
return;
dirsub(&x, &y);
m = mitem[x][y];
if (item[x][y] == OMIRROR) {
if (spnum == 3) {
lprcat("You fall asleep! ");
beep();
fool:
arg += 2;
while (arg-- > 0) {
parse2();
nap(1000);
}
return;
} else if (spnum == 6) {
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);
}
void
godirect(int spnum, int dam, const char *str, int delay, char cshow)
{
char *p;
int x, y, m;
int dx, dy;
if (spnum < 0 || spnum >= SPNUM || str == NULL || delay < 0)
return;
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;
}
if ((x == playerx) && (y == playery)) {
cursors();
lprcat("\nYou are hit my your own magic!");
beep();
lastnum = 278;
losehp(dam);
return;
}
if (c[BLINDCOUNT] == 0) {
cursor(x + 1, y + 1);
lprc(cshow);
nap(delay);
show1cell(x, y);
}
if ((m = mitem[x][y])) {
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])
if (level < MAXLEVEL + MAXVLEVEL - 1)
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);
}
}
static void
ifblind(int x, int y)
{
const char *p;
vxy(&x, &y);
if (c[BLINDCOUNT]) {
lastnum = 279;
p = "monster";
} else {
lastnum = mitem[x][y];
p = monster[lastnum].name;
}
strcpy(lastmonst, p);
}
static void
tdirect(int spnum)
{
int x, y;
int m;
if (spnum < 0 || spnum >= SPNUM)
return;
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;
}
static void
omnidirect(int spnum, int dam, const char *str)
{
int x, y, m;
if (spnum < 0 || spnum >= SPNUM || str == NULL)
return;
for (x = playerx - 1; x < playerx + 2; x++)
for (y = playery - 1; y < playery + 2; y++) {
if ((m = mitem[x][y]) != 0) {
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 int
dirsub(int *x, int *y)
{
int i;
lprcat("\nIn What Direction? ");
for (i = 0;;)
switch (getchr()) {
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);
}
int
vxy(int *x, int *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);
}
static void
dirpoly(int spnum)
{
int x, y, m;
if (spnum < 0 || spnum >= SPNUM)
return;
if (isconfuse())
return;
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);
}
void
hitmonster(int x, int y)
{
int tmp, monst, damag = 0, flag;
if (c[TIMESTOP])
return;
vxy(&x, &y);
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)) {
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 ((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;
}
}
int
hitm(int x, int y, int amt)
{
int monst;
int hpoints, amt2;
vxy(&x, &y);
amt2 = amt;
monst = mitem[x][y];
if (c[HALFDAM])
amt >>= 1;
if (amt <= 0)
amt2 = amt = 1;
lasthx = x;
lasthy = y;
stealth[x][y] = 1;
c[HOLDMONST] = 0;
switch (monst) {
case WHITEDRAGON:
case REDDRAGON:
case GREENDRAGON:
case BRONZEDRAGON:
case PLATINUMDRAGON:
case SILVERDRAGON:
amt *= 1 + (c[SLAYING] << 1);
break;
}
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);
}
void
hitplayer(int x, int y)
{
int dam, tmp, mster, bias;
vxy(&x, &y);
lastnum = mster = mitem[x][y];
if (c[NEGATESPIRIT] || c[SPIRITPRO])
if ((mster == POLTERGEIST) || (mster == SPIRITNAGA))
return;
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);
}
static void
dropsomething(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;
}
}
void
dropgold(int amount)
{
if (amount > 250)
createitem(OMAXGOLD, amount / 100);
else
createitem(OGOLDPILE, amount);
}
void
something(int lvl)
{
int j;
int i;
if (lvl < 0 || lvl > MAXLEVEL + MAXVLEVEL)
return;
if (rnd(101) < 8)
something(lvl);
j = newobject(lvl, &i);
createitem(j, i);
}
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 };
int
newobject(int lev, int *i)
{
int tmp = 32, j;
if (level < 0 || level > MAXLEVEL + MAXVLEVEL)
return (0);
if (lev > 6)
tmp = 37;
else if (lev > 4)
tmp = 35;
j = nobjtab[tmp = rnd(tmp)];
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);
}
#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 };
static int
spattack(int x, int xx, int yy)
{
int i, j = 0, k, m;
const char *p = NULL;
if (c[CANCELLATION])
return (0);
vxy(&xx, &yy);
switch (x) {
case 1:
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]) {
if (--ivenarg[k] < rustarm[i][1])
ivenarg[k] = rustarm[i][1];
else
j = 1;
break;
}
}
if (j == 0)
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);
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;;) {
i = rund(26);
m = iven[i];
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:
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);
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);
}
void
checkloss(int x)
{
if (x > 0) {
losehp(x);
bottomhp();
}
}
long
annihilate(void)
{
int i, j;
long k;
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 (*(p = &mitem[i][j])) {
if (*p < DEMONLORD + 2) {
k += monster[(int)*p].experience;
*p = know[i][j] = 0;
} else {
lprintf("\nThe %s barely escapes being annihilated!", monster[(int)*p].name);
hitp[i][j] = (hitp[i][j] >> 1) + 1;
}
}
}
if (k > 0) {
lprcat("\nYou hear loud screams of agony!");
raiseexperience((long)k);
}
return (k);
}
long
newsphere(int x, int y, int dir, int life)
{
int m;
struct sphere *sp;
if (((sp = malloc(sizeof(struct sphere)))) == NULL)
return (c[SPHCAST]);
if (dir >= 9)
dir = 0;
if (level == 0)
vxy(&x, &y);
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) {
know[x][y] = 1;
show1cell(x, y);
cursors();
lprintf("\nThe %s dispels the sphere!", monster[m].name);
beep();
rmsphere(x, y);
return (c[SPHCAST]);
}
if (m == DISENCHANTRESS) {
cursors();
lprintf("\nThe %s causes cancellation of the sphere!", monster[m].name);
beep();
boom: sphboom(x, y);
rmsphere(x, y);
return (c[SPHCAST]);
}
if (c[CANCELLATION]) {
cursors();
lprcat("\nAs the cancellation takes effect, you hear a great earth shaking blast!");
beep();
goto boom;
}
if (item[x][y] == OANNIHILATION) {
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) {
cursors();
lprcat("\nYou have been enveloped by the zone of nothingness!\n");
beep();
rmsphere(x, y);
nap(4000);
died(258);
}
item[x][y] = OANNIHILATION;
mitem[x][y] = 0;
know[x][y] = 1;
show1cell(x, y);
sp->x = x;
sp->y = y;
sp->lev = level;
sp->dir = dir;
sp->lifetime = life;
sp->p = 0;
if (spheres == 0)
spheres = sp;
else {
sp->p = spheres;
spheres = sp;
}
return (++c[SPHCAST]);
}
long
rmsphere(int x, int y)
{
struct sphere *sp, *sp2 = NULL;
for (sp = spheres; sp; sp2 = sp, sp = sp->p)
if (level == sp->lev)
if ((x == sp->x) && (y == sp->y)) {
item[x][y] = mitem[x][y] = 0;
know[x][y] = 1;
show1cell(x, y);
--c[SPHCAST];
if (sp == spheres) {
sp2 = sp;
spheres = sp->p;
free(sp2);
} else {
sp2->p = sp->p;
free(sp);
}
break;
}
return (c[SPHCAST]);
}
static void
sphboom(int x, int y)
{
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);
}
}
}
static void
genmonst(void)
{
int i, j;
cursors();
lprcat("\nGenocide what monster? ");
for (i = 0; (!isalpha(i)) && (i != ' '); i = getchr())
;
lprc(i);
for (j = 0; j < MAXMONST; j++)
if (monstnamelist[j] == i) {
monster[j].genocided = 1;
lprintf(" There will be no more %s's", monster[j].name);
newcavelevel(level);
draws(0, MAXX, 0, MAXY);
bot_linex();
return;
}
lprcat(" You sense failure!");
}