|
|
1.1 root 1: /*
2: * movem.c (move monster) Larn is copyrighted 1986 by Noah Morgan.
3: *
4: * Here are the functions in this file:
5: *
6: * movemonst() Routine to move the monsters toward the player
7: * movemt(x,y) Function to move a monster at (x,y) -- must determine where
8: * mmove(x,y,xd,yd) Function to actually perform the monster movement
9: * movsphere() Function to look for and move spheres of annihilation
10: */
11: #include "header.h"
12:
13: /*
14: * movemonst() Routine to move the monsters toward the player
15: *
16: * This routine has the responsibility to determine which monsters are to
17: * move, and call movemt() to do the move.
18: * Returns no value.
19: */
20: static short w1[9],w1x[9],w1y[9];
21: static int tmp1,tmp2,tmp3,tmp4,distance;
22: movemonst()
23: {
24: register int i,j;
25: if (c[TIMESTOP]) return; /* no action if time is stopped */
26: if (c[HASTESELF]) if ((c[HASTESELF]&1)==0) return;
27: if (spheres) movsphere(); /* move the spheres of annihilation if any */
28: if (c[HOLDMONST]) return; /* no action if monsters are held */
29:
30: if (c[AGGRAVATE]) /* determine window of monsters to move */
31: {
32: tmp1=playery-5; tmp2=playery+6; tmp3=playerx-10; tmp4=playerx+11;
33: distance=40; /* depth of intelligent monster movement */
34: }
35: else
36: {
37: tmp1=playery-3; tmp2=playery+4; tmp3=playerx-5; tmp4=playerx+6;
38: distance=17; /* depth of intelligent monster movement */
39: }
40:
41: if (level == 0) /* if on outside level monsters can move in perimeter */
42: {
43: if (tmp1 < 0) tmp1=0; if (tmp2 > MAXY) tmp2=MAXY;
44: if (tmp3 < 0) tmp3=0; if (tmp4 > MAXX) tmp4=MAXX;
45: }
46: else /* if in a dungeon monsters can't be on the perimeter (wall there) */
47: {
48: if (tmp1 < 1) tmp1=1; if (tmp2 > MAXY-1) tmp2=MAXY-1;
49: if (tmp3 < 1) tmp3=1; if (tmp4 > MAXX-1) tmp4=MAXX-1;
50: }
51:
52: for (j=tmp1; j<tmp2; j++) /* now reset monster moved flags */
53: for (i=tmp3; i<tmp4; i++)
54: moved[i][j] = 0;
55: moved[lasthx][lasthy]=0;
56:
57: if (c[AGGRAVATE] || !c[STEALTH]) /* who gets moved? split for efficiency */
58: {
59: for (j=tmp1; j<tmp2; j++) /* look thru all locations in window */
60: for (i=tmp3; i<tmp4; i++)
61: if (mitem[i][j]) /* if there is a monster to move */
62: if (moved[i][j]==0) /* if it has not already been moved */
63: movemt(i,j); /* go and move the monster */
64: }
65: else /* not aggravated and not stealth */
66: {
67: for (j=tmp1; j<tmp2; j++) /* look thru all locations in window */
68: for (i=tmp3; i<tmp4; i++)
69: if (mitem[i][j]) /* if there is a monster to move */
70: if (moved[i][j]==0) /* if it has not already been moved */
71: if (stealth[i][j]) /* if it is asleep due to stealth */
72: movemt(i,j); /* go and move the monster */
73: }
74:
75: if (mitem[lasthx][lasthy]) /* now move monster last hit by player if not already moved */
76: {
77: if (moved[lasthx][lasthy]==0) /* if it has not already been moved */
78: {
79: movemt(lasthx,lasthy);
80: lasthx = w1x[0]; lasthy = w1y[0];
81: }
82: }
83: }
84:
85: /*
86: * movemt(x,y) Function to move a monster at (x,y) -- must determine where
87: * int x,y;
88: *
89: * This routine is responsible for determining where one monster at (x,y) will
90: * move to. Enter with the monsters coordinates in (x,y).
91: * Returns no value.
92: */
93: static int tmpitem,xl,xh,yl,yh;
94: movemt(i,j)
95: int i,j;
96: {
97: register int k,m,z,tmp,xtmp,ytmp,monst;
98: switch(monst=mitem[i][j]) /* for half speed monsters */
99: {
100: case TROGLODYTE: case HOBGOBLIN: case METAMORPH: case XVART:
101: case INVISIBLESTALKER: case ICELIZARD: if ((gtime & 1) == 1) return;
102: };
103:
104: if (c[SCAREMONST]) /* choose destination randomly if scared */
105: {
106: if ((xl = i+rnd(3)-2) < 0) xl=0; if (xl >= MAXX) xl=MAXX-1;
107: if ((yl = j+rnd(3)-2) < 0) yl=0; if (yl >= MAXY) yl=MAXY-1;
108: if ((tmp=item[xl][yl]) != OWALL)
109: if (mitem[xl][yl] == 0)
110: if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR))
111: if (tmp != OCLOSEDDOOR) mmove(i,j,xl,yl);
112: return;
113: }
114:
115: if (monster[monst].intelligence > 10-c[HARDGAME]) /* if smart monster */
116: /* intelligent movement here -- first setup screen array */
117: {
118: xl=tmp3-2; yl=tmp1-2; xh=tmp4+2; yh=tmp2+2;
119: vxy(&xl,&yl); vxy(&xh,&yh);
120: for (k=yl; k<yh; k++)
121: for (m=xl; m<xh; m++)
122: {
123: switch(item[m][k])
124: {
125: case OWALL: case OPIT: case OTRAPARROW: case ODARTRAP:
126: case OCLOSEDDOOR: case OTRAPDOOR: case OTELEPORTER:
127: smm: screen[m][k]=127; break;
128: case OMIRROR: if (mitem[m][k]==VAMPIRE) goto smm;
129: default: screen[m][k]= 0; break;
130: };
131: }
132: screen[playerx][playery]=1;
133:
134: /* now perform proximity ripple from playerx,playery to monster */
135: xl=tmp3-1; yl=tmp1-1; xh=tmp4+1; yh=tmp2+1;
136: vxy(&xl,&yl); vxy(&xh,&yh);
137: for (tmp=1; tmp<distance; tmp++) /* only up to 20 squares away */
138: for (k=yl; k<yh; k++)
139: for (m=xl; m<xh; m++)
140: if (screen[m][k]==tmp) /* if find proximity n advance it */
141: for (z=1; z<9; z++) /* go around in a circle */
142: {
143: if (screen[xtmp=m+diroffx[z]][ytmp=k+diroffy[z]]==0)
144: screen[xtmp][ytmp]=tmp+1;
145: if (xtmp==i && ytmp==j) goto out;
146: }
147:
148: out: if (tmp<distance) /* did find connectivity */
149: /* now select lowest value around playerx,playery */
150: for (z=1; z<9; z++) /* go around in a circle */
151: if (screen[xl=i+diroffx[z]][yl=j+diroffy[z]]==tmp)
152: if (!mitem[xl][yl]) { mmove(i,j,w1x[0]=xl,w1y[0]=yl); return; }
153: }
154:
155: /* dumb monsters move here */
156: xl=i-1; yl=j-1; xh=i+2; yh=j+2;
157: if (i<playerx) xl++; else if (i>playerx) --xh;
158: if (j<playery) yl++; else if (j>playery) --yh;
159: for (k=0; k<9; k++) w1[k] = 10000;
160:
161: for (k=xl; k<xh; k++)
162: for (m=yl; m<yh; m++) /* for each square compute distance to player */
163: {
164: tmp = k-i+4+3*(m-j);
165: tmpitem = item[k][m];
166: if (tmpitem!=OWALL || (k==playerx && m==playery))
167: if (mitem[k][m]==0)
168: if ((mitem[i][j] != VAMPIRE) || (tmpitem != OMIRROR))
169: if (tmpitem!=OCLOSEDDOOR)
170: {
171: w1[tmp] = (playerx-k)*(playerx-k)+(playery-m)*(playery-m);
172: w1x[tmp] = k; w1y[tmp] = m;
173: }
174: }
175:
176: tmp = 0;
177: for (k=1; k<9; k++) if (w1[tmp] > w1[k]) tmp=k;
178:
179: if (w1[tmp] < 10000)
180: if ((i!=w1x[tmp]) || (j!=w1y[tmp]))
181: mmove(i,j,w1x[tmp],w1y[tmp]);
182: }
183:
184: /*
185: * mmove(x,y,xd,yd) Function to actually perform the monster movement
186: * int x,y,xd,yd;
187: *
188: * Enter with the from coordinates in (x,y) and the destination coordinates
189: * in (xd,yd).
190: */
191: mmove(aa,bb,cc,dd)
192: int aa,bb,cc,dd;
193: {
194: register int tmp,i,flag;
195: char *who,*p;
196: flag=0; /* set to 1 if monster hit by arrow trap */
197: if ((cc==playerx) && (dd==playery))
198: {
199: hitplayer(aa,bb); moved[aa][bb] = 1; return;
200: }
201: i=item[cc][dd];
202: if ((i==OPIT) || (i==OTRAPDOOR))
203: switch(mitem[aa][bb])
204: {
205: case SPIRITNAGA: case PLATINUMDRAGON: case WRAITH:
206: case VAMPIRE: case SILVERDRAGON: case POLTERGEIST:
207: case DEMONLORD: case DEMONLORD+1: case DEMONLORD+2:
208: case DEMONLORD+3: case DEMONLORD+4: case DEMONLORD+5:
209: case DEMONLORD+6: case DEMONPRINCE: break;
210:
211: default: mitem[aa][bb]=0; /* fell in a pit or trapdoor */
212: };
213: tmp = mitem[cc][dd] = mitem[aa][bb];
214: if (i==OANNIHILATION)
215: {
216: if (tmp>=DEMONLORD+3) /* demons dispel spheres */
217: {
218: cursors();
219: lprintf("\nThe %s dispels the sphere!",monster[tmp].name);
220: rmsphere(cc,dd); /* delete the sphere */
221: }
222: else i=tmp=mitem[cc][dd]=0;
223: }
224: stealth[cc][dd]=1;
225: if ((hitp[cc][dd] = hitp[aa][bb]) < 0) hitp[cc][dd]=1;
226: mitem[aa][bb] = 0; moved[cc][dd] = 1;
227: if (tmp == LEPRECHAUN)
228: switch(i)
229: {
230: case OGOLDPILE: case OMAXGOLD: case OKGOLD: case ODGOLD:
231: case ODIAMOND: case ORUBY: case OEMERALD: case OSAPPHIRE:
232: item[cc][dd] = 0; /* leprechaun takes gold */
233: };
234:
235: if (tmp == TROLL) /* if a troll regenerate him */
236: if ((gtime & 1) == 0)
237: if (monster[tmp].hitpoints > hitp[cc][dd]) hitp[cc][dd]++;
238:
239: if (i==OTRAPARROW) /* arrow hits monster */
240: { who = "An arrow"; if ((hitp[cc][dd] -= rnd(10)+level) <= 0)
241: { mitem[cc][dd]=0; flag=2; } else flag=1; }
242: if (i==ODARTRAP) /* dart hits monster */
243: { who = "A dart"; if ((hitp[cc][dd] -= rnd(6)) <= 0)
244: { mitem[cc][dd]=0; flag=2; } else flag=1; }
245: if (i==OTELEPORTER) /* monster hits teleport trap */
246: { flag=3; fillmonst(mitem[cc][dd]); mitem[cc][dd]=0; }
247: if (c[BLINDCOUNT]) return; /* if blind don't show where monsters are */
248: if (know[cc][dd] & 1)
249: {
250: p=0;
251: if (flag) cursors();
252: switch(flag)
253: {
254: case 1: p="\n%s hits the %s"; break;
255: case 2: p="\n%s hits and kills the %s"; break;
256: case 3: p="\nThe %s%s gets teleported"; who=""; break;
257: };
258: if (p) { lprintf(p,who,monster[tmp].name); beep(); }
259: }
260: /* if (yrepcount>1) { know[aa][bb] &= 2; know[cc][dd] &= 2; return; } */
261: if (know[aa][bb] & 1) show1cell(aa,bb);
262: if (know[cc][dd] & 1) show1cell(cc,dd);
263: }
264:
265: /*
266: * movsphere() Function to look for and move spheres of annihilation
267: *
268: * This function works on the sphere linked list, first duplicating the list
269: * (the act of moving changes the list), then processing each sphere in order
270: * to move it. They eat anything in their way, including stairs, volcanic
271: * shafts, potions, etc, except for upper level demons, who can dispel
272: * spheres.
273: * No value is returned.
274: */
275: #define SPHMAX 20 /* maximum number of spheres movsphere can handle */
276: movsphere()
277: {
278: register int x,y,dir,len;
279: register struct sphere *sp,*sp2;
280: struct sphere sph[SPHMAX];
281:
282: /* first duplicate sphere list */
283: for (sp=0,x=0,sp2=spheres; sp2; sp2=sp2->p) /* look through sphere list */
284: if (sp2->lev == level) /* only if this level */
285: {
286: sph[x] = *sp2; sph[x++].p = 0; /* copy the struct */
287: if (x>1) sph[x-2].p = &sph[x-1]; /* link pointers */
288: }
289: if (x) sp= sph; /* if any spheres, point to them */
290: else return; /* no spheres */
291:
292: for (sp=sph; sp; sp=sp->p) /* look through sphere list */
293: {
294: x = sp->x; y = sp->y;
295: if (item[x][y]!=OANNIHILATION) continue; /* not really there */
296: if (--(sp->lifetime) < 0) /* has sphere run out of gas? */
297: {
298: rmsphere(x,y); /* delete sphere */
299: continue;
300: }
301: switch(rnd((int)max(7,c[INTELLIGENCE]>>1))) /* time to move the sphere */
302: {
303: case 1:
304: case 2: /* change direction to a random one */
305: sp->dir = rnd(8);
306: default: /* move in normal direction */
307: dir = sp->dir; len = sp->lifetime;
308: rmsphere(x,y);
309: newsphere(x+diroffx[dir],y+diroffy[dir],dir,len);
310: };
311: }
312: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.