#include "header.h"
static void movemt(int, int);
static void mmove(int, int, int, int);
static void movsphere(void);
static short w1[9], w1x[9], w1y[9];
static int tmp1, tmp2, tmp3, tmp4, distance;
void
movemonst(void)
{
int i, j;
if (c[TIMESTOP])
return;
if (c[HASTESELF])
if ((c[HASTESELF] & 1) == 0)
return;
if (spheres)
movsphere();
if (c[HOLDMONST])
return;
if (c[AGGRAVATE]) {
tmp1 = playery - 5;
tmp2 = playery + 6;
tmp3 = playerx - 10;
tmp4 = playerx + 11;
distance = 40;
} else {
tmp1 = playery - 3;
tmp2 = playery + 4;
tmp3 = playerx - 5;
tmp4 = playerx + 6;
distance = 17;
}
if (level == 0) {
if (tmp1 < 0)
tmp1 = 0;
if (tmp2 > MAXY)
tmp2 = MAXY;
if (tmp3 < 0)
tmp3 = 0;
if (tmp4 > MAXX)
tmp4 = MAXX;
} else {
if (tmp1 < 1)
tmp1 = 1;
if (tmp2 > MAXY - 1)
tmp2 = MAXY - 1;
if (tmp3 < 1)
tmp3 = 1;
if (tmp4 > MAXX - 1)
tmp4 = MAXX - 1;
}
for (j = tmp1; j < tmp2; j++)
for (i = tmp3; i < tmp4; i++)
moved[i][j] = 0;
moved[lasthx][lasthy] = 0;
if (c[AGGRAVATE] || !c[STEALTH]) {
for (j = tmp1; j < tmp2; j++)
for (i = tmp3; i < tmp4; i++)
if (mitem[i][j])
if (moved[i][j] == 0)
movemt(i, j);
} else {
for (j = tmp1; j < tmp2; j++)
for (i = tmp3; i < tmp4; i++)
if (mitem[i][j])
if (moved[i][j] == 0)
if (stealth[i][j])
movemt(i, j);
}
if (mitem[lasthx][lasthy]) {
if (moved[lasthx][lasthy] == 0) {
movemt(lasthx, lasthy);
lasthx = w1x[0];
lasthy = w1y[0];
}
}
}
static int tmpitem, xl, xh, yl, yh;
static void
movemt(int i, int j)
{
int k, m, z, tmp, xtmp, ytmp, monst;
switch (monst = mitem[i][j]) {
case TROGLODYTE:
case HOBGOBLIN:
case METAMORPH:
case XVART:
case INVISIBLESTALKER:
case ICELIZARD:
if ((gtime & 1) == 1)
return;
}
if (c[SCAREMONST]) {
if ((xl = i + rnd(3) - 2) < 0)
xl = 0;
if (xl >= MAXX)
xl = MAXX - 1;
if ((yl = j + rnd(3) - 2) < 0)
yl = 0;
if (yl >= MAXY)
yl = MAXY - 1;
if ((tmp = item[xl][yl]) != OWALL)
if (mitem[xl][yl] == 0)
if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR))
if (tmp != OCLOSEDDOOR)
mmove(i, j, xl, yl);
return;
}
if (monster[monst].intelligence > 10 - c[HARDGAME]) {
xl = tmp3 - 2;
yl = tmp1 - 2;
xh = tmp4 + 2;
yh = tmp2 + 2;
vxy(&xl, &yl);
vxy(&xh, &yh);
for (k = yl; k < yh; k++)
for (m = xl; m < xh; m++) {
switch (item[m][k]) {
case OWALL:
case OPIT:
case OTRAPARROW:
case ODARTRAP:
case OCLOSEDDOOR:
case OTRAPDOOR:
case OTELEPORTER:
smm: screen[m][k] = 127;
break;
case OMIRROR:
if (mitem[m][k] == VAMPIRE)
goto smm;
default:
screen[m][k] = 0;
break;
}
}
screen[playerx][playery] = 1;
xl = tmp3 - 1;
yl = tmp1 - 1;
xh = tmp4 + 1;
yh = tmp2 + 1;
vxy(&xl, &yl);
vxy(&xh, &yh);
for (tmp = 1; tmp < distance; tmp++)
for (k = yl; k < yh; k++)
for (m = xl; m < xh; m++)
if (screen[m][k] == tmp)
for (z = 1; z < 9; z++) {
if (screen[xtmp = m + diroffx[z]][ytmp = k + diroffy[z]] == 0)
screen[xtmp][ytmp] = tmp + 1;
if (xtmp == i && ytmp == j)
goto out;
}
out: if (tmp < distance)
for (z = 1; z < 9; z++)
if (screen[xl = i + diroffx[z]][yl = j + diroffy[z]] == tmp)
if (!mitem[xl][yl]) {
mmove(i, j, w1x[0] = xl, w1y[0] = yl);
return;
}
}
xl = i - 1;
yl = j - 1;
xh = i + 2;
yh = j + 2;
if (i < playerx)
xl++;
else if (i > playerx)
--xh;
if (j < playery)
yl++;
else if (j > playery)
--yh;
for (k = 0; k < 9; k++)
w1[k] = 10000;
for (k = xl; k < xh; k++)
for (m = yl; m < yh; m++) {
tmp = k - i + 4 + 3 * (m - j);
tmpitem = item[k][m];
if (tmpitem != OWALL || (k == playerx && m == playery))
if (mitem[k][m] == 0)
if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR))
if (tmpitem != OCLOSEDDOOR) {
w1[tmp] = (playerx - k) * (playerx - k) + (playery - m) * (playery - m);
w1x[tmp] = k;
w1y[tmp] = m;
}
}
tmp = 0;
for (k = 1; k < 9; k++)
if (w1[tmp] > w1[k])
tmp = k;
if (w1[tmp] < 10000)
if ((i != w1x[tmp]) || (j != w1y[tmp]))
mmove(i, j, w1x[tmp], w1y[tmp]);
}
static void
mmove(int aa, int bb, int cc, int dd)
{
int tmp, i, flag;
const char *who = NULL, *p;
flag = 0;
if ((cc == playerx) && (dd == playery)) {
hitplayer(aa, bb);
moved[aa][bb] = 1;
return;
}
i = item[cc][dd];
if ((i == OPIT) || (i == OTRAPDOOR))
switch (mitem[aa][bb]) {
case SPIRITNAGA:
case PLATINUMDRAGON:
case WRAITH:
case VAMPIRE:
case SILVERDRAGON:
case POLTERGEIST:
case DEMONLORD:
case DEMONLORD + 1:
case DEMONLORD + 2:
case DEMONLORD + 3:
case DEMONLORD + 4:
case DEMONLORD + 5:
case DEMONLORD + 6:
case DEMONPRINCE:
break;
default:
mitem[aa][bb] = 0;
}
tmp = mitem[cc][dd] = mitem[aa][bb];
if (i == OANNIHILATION) {
if (tmp >= DEMONLORD + 3) {
cursors();
lprintf("\nThe %s dispels the sphere!", monster[tmp].name);
rmsphere(cc, dd);
} else
i = tmp = mitem[cc][dd] = 0;
}
stealth[cc][dd] = 1;
if ((hitp[cc][dd] = hitp[aa][bb]) < 0)
hitp[cc][dd] = 1;
mitem[aa][bb] = 0;
moved[cc][dd] = 1;
if (tmp == LEPRECHAUN)
switch (i) {
case OGOLDPILE:
case OMAXGOLD:
case OKGOLD:
case ODGOLD:
case ODIAMOND:
case ORUBY:
case OEMERALD:
case OSAPPHIRE:
item[cc][dd] = 0;
}
if (tmp == TROLL)
if ((gtime & 1) == 0)
if (monster[tmp].hitpoints > hitp[cc][dd])
hitp[cc][dd]++;
if (i == OTRAPARROW) {
who = "An arrow";
if ((hitp[cc][dd] -= rnd(10) + level) <= 0) {
mitem[cc][dd] = 0;
flag = 2;
} else
flag = 1;
}
if (i == ODARTRAP) {
who = "A dart";
if ((hitp[cc][dd] -= rnd(6)) <= 0) {
mitem[cc][dd] = 0;
flag = 2;
} else
flag = 1;
}
if (i == OTELEPORTER) {
flag = 3;
fillmonst(mitem[cc][dd]);
mitem[cc][dd] = 0;
}
if (c[BLINDCOUNT])
return;
if (know[cc][dd] & 1) {
p = NULL;
if (flag)
cursors();
switch (flag) {
case 1:
p = "\n%s hits the %s";
break;
case 2:
p = "\n%s hits and kills the %s";
break;
case 3:
p = "\nThe %s%s gets teleported";
who = "";
break;
}
if (p) {
lprintf(p, who, monster[tmp].name);
beep();
}
}
if (know[aa][bb] & 1)
show1cell(aa, bb);
if (know[cc][dd] & 1)
show1cell(cc, dd);
}
#define SPHMAX 20
static void
movsphere(void)
{
int x, y, dir, len;
struct sphere *sp, *sp2;
struct sphere sph[SPHMAX];
for (sp = NULL, x = 0, sp2 = spheres; sp2; sp2 = sp2->p)
if (sp2->lev == level) {
sph[x] = *sp2;
sph[x++].p = 0;
if (x > 1)
sph[x - 2].p = &sph[x - 1];
}
if (x)
sp = sph;
else
return;
for (sp = sph; sp; sp = sp->p) {
x = sp->x;
y = sp->y;
if (item[x][y] != OANNIHILATION)
continue;
if (--(sp->lifetime) < 0) {
rmsphere(x, y);
continue;
}
switch (rnd((int)max(7, c[INTELLIGENCE] >> 1))) {
case 1:
case 2:
sp->dir = rnd(8);
default:
dir = sp->dir;
len = sp->lifetime;
rmsphere(x, y);
newsphere(x + diroffx[dir], y + diroffy[dir], dir, len);
}
}
}