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