1 /* omega copyright (c) 1987,1988,1989 by Laurence Raphael Brothers */
2 /* mmove.c */
3 /* monster move functions */
4 
5 #include "glob.h"
6 
7 
8 /* like m_normal_move, but can open doors */
m_smart_move(m)9 void m_smart_move(m)
10 struct monster *m;
11 {
12   m_simple_move(m);
13 }
14 
15 /* not very smart, but not altogether stupid movement */
m_normal_move(m)16 void m_normal_move(m)
17 struct monster *m;
18 {
19   m_simple_move(m);
20 }
21 
22 
23 /* used by both m_normal_move and m_smart_move */
m_simple_move(m)24 void m_simple_move(m)
25 struct monster *m;
26 {
27   int dx = sign(Player.x - m->x);
28   int dy = sign(Player.y - m->y);
29 
30   erase_monster(m);
31   if (m->hp < Monsters[m->id].hp/4) {
32     dx = - dx;
33     dy = - dy;
34     m->movef = M_MOVE_SCAREDY;
35     if (m->uniqueness == COMMON) {
36       strcpy(Str2,"The ");
37       strcat(Str2,m->monstring);
38     }
39     else strcpy(Str2,m->monstring);
40     if (m->possessions != NULL) {
41       strcat(Str2," drops its treasure and flees!");
42       m_dropstuff(m);
43     }
44     else strcat(Str2," flees!");
45     mprint(Str2);
46     m->speed = min(2,m->speed-1);
47   }
48   if ((! m_statusp(m,HOSTILE) && !m_statusp(m, NEEDY)) ||
49       (Player.status[INVISIBLE] > 0)) m_random_move(m);
50   else {
51     if (m_unblocked(m,m->x+dx,m->y+dy))
52       movemonster(m,m->x+dx,m->y+dy);
53     else if (dx == 0) {
54       if (m_unblocked(m,m->x+1,m->y+dy))
55 	movemonster(m,m->x+1,m->y+dy);
56       else if (m_unblocked(m,m->x-1,m->y+dy))
57 	movemonster(m,m->x-1,m->y+dy);
58     }
59 
60     else if (dy == 0) {
61       if (m_unblocked(m,m->x+dx,m->y+1))
62 	movemonster(m,m->x+dx,m->y+1);
63       else if (m_unblocked(m,m->x+dx,m->y-1))
64 	movemonster(m,m->x+dx,m->y-1);
65     }
66 
67     else {
68       if (m_unblocked(m,m->x+dx,m->y))
69 	movemonster(m,m->x+dx,m->y);
70       else if (m_unblocked(m,m->x,m->y+dy))
71 	movemonster(m,m->x,m->y+dy);
72     }
73   }
74 }
75 
76 
77 
78 
m_move_animal(m)79 void m_move_animal(m)
80 struct monster *m;
81 {
82   if (m_statusp(m,HOSTILE))
83     m_normal_move(m);
84   else m_scaredy_move(m);
85 }
86 
87 
88 
89 
90 /* same as simple move except run in opposite direction */
m_scaredy_move(m)91 void m_scaredy_move(m)
92 struct monster *m;
93 {
94   int dx = -sign(Player.x - m->x);
95   int dy = -sign(Player.y - m->y);
96   erase_monster(m);
97   if (Player.status[INVISIBLE]) m_random_move(m);
98   else {
99     if (m_unblocked(m,m->x+dx,m->y+dy))
100       movemonster(m,m->x+dx,m->y+dy);
101     else if (dx == 0) {
102       if (m_unblocked(m,m->x+1,m->y+dy))
103 	movemonster(m,m->x+1,m->y+dy);
104       else if (m_unblocked(m,m->x-1,m->y+dy))
105 	movemonster(m,m->x-1,m->y+dy);
106     }
107 
108     else if (dy == 0) {
109       if (m_unblocked(m,m->x+dx,m->y+1))
110 	movemonster(m,m->x+dx,m->y+1);
111       else if (m_unblocked(m,m->x+dx,m->y-1))
112 	movemonster(m,m->x+dx,m->y-1);
113     }
114 
115     else {
116       if (m_unblocked(m,m->x+dx,m->y))
117 	movemonster(m,m->x+dx,m->y);
118       else if (m_unblocked(m,m->x,m->y+dy))
119 	movemonster(m,m->x,m->y+dy);
120     }
121   }
122 }
123 
124 
125 
126 
127 
128 
129 /* for spirits (and earth creatures) who can ignore blockages because
130    either they are noncorporeal or they can move through stone */
m_spirit_move(m)131 void m_spirit_move(m)
132 struct monster *m;
133 {
134   int dx = sign(Player.x - m->x);
135   int dy = sign(Player.y - m->y);
136   erase_monster(m);
137   if (m->hp < Monsters[m->id].hp/6) {
138     dx = -dx;
139     dy = -dy;
140   }
141 
142   if (Player.status[INVISIBLE] > 0 || !m_unblocked(m, m->x+dx, m->y+dy))
143     m_random_move(m);
144   else
145     movemonster(m,m->x+dx,m->y+dy);
146 }
147 
148 
149 
150 /* fluttery dumb movement */
m_flutter_move(m)151 void m_flutter_move(m)
152 struct monster *m;
153 {
154   int trange,range = distance(m->x,m->y,Player.x,Player.y);
155   int i,tx,ty,nx=m->x,ny=m->y;
156   erase_monster(m);
157   if (Player.status[INVISIBLE] > 0) m_random_move(m);
158   else {
159     for (i=0;i<8;i++) {
160       tx = m->x+Dirs[0][i];
161       ty = m->y+Dirs[1][i];
162       trange = distance(tx,ty,Player.x,Player.y);
163       if (m->hp < Monsters[m->id].hp/6) {
164 	if ((trange > range) && m_unblocked(m,tx,ty)) {
165 	  range = trange;
166 	  nx = tx;
167 	  ny = ty;
168 	}
169       }
170       else if ((trange <= range) && m_unblocked(m,tx,ty)) {
171 	range = trange;
172 	nx = tx;
173 	ny = ty;
174       }
175     }
176     movemonster(m,nx,ny);
177   }
178 }
179 
180 
m_follow_move(m)181 void m_follow_move(m)
182 struct monster *m;
183 {
184   if (! m_statusp(m,HOSTILE))
185     m_normal_move(m);
186   else m_scaredy_move(m);
187 }
188 
189 
190 
191 /* allows monsters to fall into pools, revealed traps, etc */
m_confused_move(m)192 void m_confused_move(m)
193 struct monster *m;
194 {
195   int i,nx,ny,done=FALSE;
196   erase_monster(m);
197   for (i=0;((i<8)&&(! done));i++) {
198     nx = m->x+random_range(3)-1;
199     ny = m->y+random_range(3)-1;
200     if (unblocked(nx,ny) &&
201 	((nx != Player.x) ||
202 	 (ny != Player.y))) {
203       done = TRUE;
204       movemonster(m,nx,ny);
205     }
206   }
207 }
208 
m_random_move(m)209 void m_random_move(m)
210 struct monster *m;
211 {
212   int i,nx,ny,done=FALSE;
213   erase_monster(m);
214   for (i=0;((i<8)&&(! done));i++) {
215     nx = m->x+random_range(3)-1;
216     ny = m->y+random_range(3)-1;
217     if (m_unblocked(m,nx,ny) &&
218 	((nx != Player.x) ||
219 	 (ny != Player.y))) {
220       done = TRUE;
221       movemonster(m,nx,ny);
222     }
223   }
224 }
225 
226 
227 /* monster removed from play */
m_vanish(m)228 void m_vanish(m)
229 struct monster *m;
230 {
231   if (m->uniqueness == COMMON) {
232     strcpy(Str2,"The ");
233     strcat(Str2,m->monstring);
234   }
235   else strcpy(Str2,m->monstring);
236   strcat(Str2," vanishes in the twinkling of an eye!");
237   mprint(Str2);
238   Level->site[m->x][m->y].creature = NULL;
239   erase_monster(m);
240   m->hp = -1; /* signals "death" -- no credit to player, though */
241 }
242 
243 /* monster still in play */
m_teleport(m)244 void m_teleport(m)
245 struct monster *m;
246 {
247   erase_monster(m);
248   if (m_statusp(m,AWAKE)) {
249     Level->site[m->x][m->y].creature = NULL;
250     putspot(m->x,m->y,getspot(m->x,m->y,FALSE));
251     findspace(&(m->x),&(m->y),-1);
252     Level->site[m->x][m->y].creature = m;
253   }
254 }
255 
m_move_leash(m)256 void m_move_leash(m)
257 struct monster *m;
258 {
259   m_simple_move(m);
260   if (m->aux1 == 0) {
261     m->aux1 = m->x;
262     m->aux2 = m->y;
263   }
264   else if (distance(m->x,m->y,m->aux1,m->aux2) > 5) {
265     if (Level->site[m->aux1][m->aux2].creature != NULL) {
266       if (los_p(Player.x,Player.y,m->aux1,m->aux2)) {
267 	/* some other monster is where the chain starts */
268 	if (Level->site[m->aux1][m->aux2].creature->uniqueness == COMMON) {
269 	  strcpy(Str1, "The ");
270 	  strcat(Str1, Level->site[m->aux1][m->aux2].creature->monstring);
271 	}
272 	else
273 	  strcpy(Str1, Level->site[m->aux1][m->aux2].creature->monstring);
274 	strcat(Str1, " releases the dog's chain!");
275 	mprint(Str1);
276       }
277       m->movef = M_MOVE_NORMAL;
278       /* otherwise, we'd lose either the dog or the other monster. */
279     }
280     else if (los_p(Player.x,Player.y,m->x,m->y)) {
281       mprint("You see the dog jerked back by its chain!");
282       plotspot(m->x, m->y, FALSE);
283     }
284     else mprint("You hear a strangled sort of yelp!");
285     Level->site[m->x][m->y].creature = NULL;
286     m->x = m->aux1;
287     m->y = m->aux2;
288     Level->site[m->x][m->y].creature = m;
289   }
290 }
291