1 /* File fall.c */
2 /***************************************************************************
3 * Copyright 2003 - Steven Shipway <steve@cheshire.demon.co.uk> *
4 * Put "nospam" in subject to avoid spam filter *
5 * *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
10 * *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
15 * *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA *
19 * 02111-1307, USA. *
20 ***************************************************************************/
21
22
23 #include "wand_head.h"
24
25 extern void draw_symbol();
26 extern int debug_disp;
27 extern char screen[NOOFROWS][ROWLEN+1];
28
29 int moving = 0; /* so that bombs explode only if something *hits* them */
30
31 /*****************************************************
32 * Function check *
33 ******************************************************/
34 /* check for any falling caused by something moving out of x,y along *
35 * vector dx,dy. All the others are constant and should really have *
36 * been global... */
37
check(mx,my,x,y,dx,dy,sx,sy,howdead)38 int check(mx,my,x,y,dx,dy,sx,sy,howdead)
39 int x,y,sx,sy,dx,dy, *mx, *my;
40 char howdead[25];
41 {
42 int ret=0;
43 ret+=fall(mx,my,x,y,sx,sy,howdead);
44 ret+=fall(mx,my,x-dx,y-dy,sx,sy,howdead);
45 ret+=fall(mx,my,x-dy,y-dx,sx,sy,howdead);
46 ret+=fall(mx,my,x+dy,y+dx,sx,sy,howdead);
47 ret+=fall(mx,my,x-dx-dy,y-dy-dx,sx,sy,howdead);
48 ret+=fall(mx,my,x-dx+dy,y-dy+dx,sx,sy,howdead);
49 return ret;
50 }
51
52 /*****************************************************
53 * Function fall *
54 ******************************************************/
55 /* recursive function for falling *
56 * boulders and arrows *
57 ***********************************/
fall(mx,my,x,y,sx,sy,howdead)58 int fall(mx,my,x,y,sx,sy,howdead)
59 int x,y,sx,sy, *mx, *my;
60 char howdead[25];
61 {
62 int nx = x,nxu = x,nyl = y,nyr = y,ny = y,retval = 0;
63 if ((y>(NOOFROWS-1))||(y<0)||(x<0)||(x>(ROWLEN-1)))
64 return(0);
65 if(screen[y][x] == '~') {
66 if( screen[y-1][x] == ' ' ) fall(mx,my,x,y-1,sx,sy,howdead);
67 if( screen[y+1][x] == ' ' ) fall(mx,my,x,y+1,sx,sy,howdead);
68 if( screen[y][x-1] == ' ' ) fall(mx,my,x-1,y,sx,sy,howdead);
69 if( screen[y][x+1] == ' ' ) fall(mx,my,x+1,y,sx,sy,howdead);
70 }
71 if((screen[y][x] != 'O') && (screen[y][x] != ' ') && (screen[y][x] != 'M') &&
72 (screen[y][x] !='\\') && (screen[y][x] != '/') && (screen[y][x] != '@') &&
73 (screen[y][x] != '^') && (screen[y][x] != 'B'))
74 return(0);
75 if((screen[y][x] == 'B') && (moving == 0 )) return 0;
76 if(screen[y][x] == 'O')
77 {
78 if((screen[y][x-1] == ' ') && (screen[y-1][x-1] == ' '))
79 nx--;
80 else
81 {
82 if((screen[y][x+1] == ' ') && (screen[y-1][x+1] == ' '))
83 nx++;
84 else
85 nx = -1;
86 }
87 if((screen[y][x-1] == ' ') && (screen[y+1][x-1] == ' '))
88 nxu--;
89 else
90 {
91 if((screen[y][x+1] == ' ') && (screen[y+1][x+1] == ' '))
92 nxu++;
93 else
94 nxu = -1;
95 }
96 if((screen[y-1][x] == ' ') && (screen[y-1][x+1] == ' '))
97 nyr--;
98 else
99 {
100 if((screen[y+1][x] == ' ') && (screen[y+1][x+1] == ' '))
101 nyr++;
102 else
103 nyr = -1;
104 }
105 if((screen[y-1][x] == ' ') && (screen[y-1][x-1] == ' '))
106 nyl--;
107 else
108 {
109 if((screen[y+1][x] == ' ') && (screen[y+1][x-1] == ' '))
110 nyl++;
111 else
112 nyl = -1;
113 }
114 }
115 if(screen[y][x] == '\\')
116 {
117 if(screen[y-1][++nx] != ' ')
118 nx = -1;
119 if(screen[y+1][--nxu] != ' ')
120 nxu = -1;
121 if(screen[--nyr][x+1] != ' ')
122 nyr = -1;
123 if(screen[++nyl][x-1] != ' ')
124 nyl = -1;
125 }
126 if(screen[y][x] == '/')
127 {
128 if(screen[y-1][--nx] != ' ')
129 nx = -1;
130 if(screen[y+1][++nxu] != ' ')
131 nxu = -1;
132 if(screen[++nyr][x+1] != ' ')
133 nyr = -1;
134 if(screen[--nyl][x-1] != ' ')
135 nyl = -1;
136 }
137 if((screen[y][nx] != ' ') && (screen[y][nx] != 'M') && (screen[y][nx] != 'B'))
138 nx = -1;
139 if((screen[y-1][x] == 'O') && (nx >= 0) && (y > 0)) /* boulder falls ? */
140 {
141 moving = 1;
142 screen[y-1][x] = ' ';
143 if(screen[y][nx] == '@')
144 {
145 strcpy(howdead,"a falling boulder");
146 retval=1;
147 }
148 if(screen[y][nx] == 'M')
149 {
150 *mx = *my = -2;
151 screen[y][nx] = ' ';
152 }
153 if(screen[y][nx] == 'B')
154 {
155 retval = bang(nx,y,mx,my,sx,sy,howdead);
156 return retval;
157 }
158 screen[y][nx] = 'O';
159 if(!debug_disp)
160 {
161 if((y<(sy+5)) && (y>(sy-3)) && (x>(sx-6)) && (x<(sx+6)))
162 draw_symbol((x-sx+5)*3,(y-sy+2)*2,' ');
163 if((y<(sy+4)) && (y>(sy-4)) && (nx>(sx-6)) && (nx<(sx+6)))
164 draw_symbol((nx-sx+5)*3,(y-sy+3)*2,'O');
165 }
166 else
167 {
168 move(y,x+1);
169 addch(' ');;
170 move(y+1,nx+1);
171 addch('O');
172 }
173 refresh();
174 retval+=fall(mx,my,nx ,y+1,sx,sy,howdead);
175 moving = 0;
176 retval+=check(mx,my,x,y-1,0,1,sx,sy,howdead);
177 if(screen[y+1][nx] == '@')
178 {
179 strcpy(howdead,"a falling boulder");
180 return(1);
181 }
182 if(screen[y+1][nx] == 'M')
183 {
184 *mx = *my = -2;
185 screen[y+1][nx] = ' ';
186 }
187 }
188 if((screen[nyr][x] != '^')&&(screen[nyr][x] != ' ')&&(screen[nyr][x] != 'M')
189 &&(screen[nyr][x] != 'B'))
190 nyr = -1;
191 if((screen[y][x+1] == '<')&&(nyr>=0)&&(x+1<ROWLEN)) /* arrow moves ( < ) ? */
192 {
193 moving = 1;
194 screen[y][x+1] = ' ';
195 if(screen[nyr][x] == '@')
196 {
197 strcpy(howdead,"a speeding arrow");
198 retval = 1;
199 }
200 if(screen[nyr][x] == 'M')
201 {
202 *mx = *my = -2;
203 screen[nyr][x] = ' ';
204 }
205 if(screen[nyr][x] == 'B')
206 {
207 retval = bang(x,nyr,mx,my,sx,sy,howdead);
208 return retval;
209 }
210 screen[nyr][x] = '<';
211 if(!debug_disp)
212 {
213 if((y<(sy+4)) && (y>(sy-4)) && (x<(sx+5)) && (x>(sx-7)))
214 draw_symbol((x-sx+6)*3,(y-sy+3)*2,' ');
215 if((nyr<(sy+4)) && (nyr>(sy-4)) && (x<(sx+6)) && (x>(sx-6)))
216 draw_symbol((x-sx+5)*3,(nyr-sy+3)*2,'<');
217 }
218 else
219 {
220 move(y+1,x+2);
221 addch(' ');
222 move(nyr+1,x+1);
223 addch('<');
224 }
225 refresh();
226 retval+=fall(mx,my,x-1,nyr,sx,sy,howdead);
227 moving = 0;
228 retval+=check(mx,my,x+1,y,-1,0,sx,sy,howdead);
229 if(screen[nyr][x-1] == '@')
230 {
231 strcpy(howdead,"a speeding arrow");
232 return(1);
233 }
234 if(screen[nyr][x-1] == 'M')
235 {
236 *mx = *my = -2;
237 screen[nyr][x-1] = ' ';
238 }
239 }
240 if((screen[nyl][x] != ' ')&&(screen[nyl][x] != '^')&&(screen[nyl][x] != 'M')
241 &&( screen[nyl][x] != 'B'))
242 nyl = -1;
243 if((screen[y][x-1] == '>')&&(nyl>=0)&&(x>0)) /* arrow moves ( > ) ? */
244 {
245 moving = 1;
246 screen[y][x-1] = ' ';
247 if(screen[nyl][x] == '@')
248 {
249 strcpy(howdead,"a speeding arrow");
250 retval = 1;
251 }
252 if(screen[nyl][x] == 'M')
253 {
254 *mx = *my = -2;
255 screen[nyl][x] = ' ';
256 }
257 if(screen[nyr][x] == 'B')
258 {
259 retval = bang(x,nyr,mx,my,sx,sy,howdead);
260 return retval;
261 }
262 screen[nyl][x] = '>';
263 if(!debug_disp)
264 {
265 if((y<(sy+4)) && (y>(sy-4)) && (x<(sx+7)) && (x>(sx-5)))
266 draw_symbol((x-sx+4)*3,(y-sy+3)*2,' ');
267 if((nyl<(sy+4)) && (nyl>(sy-4)) && (x<(sx+6)) && (x>(sx-6)))
268 draw_symbol((x-sx+5)*3,(nyl-sy+3)*2,'>');
269 }
270 else
271 {
272 move(y+1,x);
273 addch(' ');
274 move(nyl+1,x+1);
275 addch('>');
276 }
277 refresh();
278 retval+=fall(mx,my,x+1,nyl,sx,sy,howdead);
279 moving = 0;
280 retval+=check(mx,my,x-1,y,1,0,sx,sy,howdead);
281 if(screen[nyl][x+1] == '@')
282 {
283 strcpy(howdead,"a speeding arrow");
284 return(1);
285 }
286 if(screen[nyl][x+1] == 'M')
287 {
288 *mx = *my = -2;
289 screen[nyl][x+1] = ' ';
290 }
291 }
292
293 if(screen[y][nxu] != ' ')
294 nxu = -1;
295
296 if((screen[y+1][x] == '^') && (nxu >= 0) && (y < NOOFROWS) &&
297 (screen[y][x] != '^')&&(screen[y][x] != 'B')) /* balloon rises? */
298 {
299 screen[y+1][x] = ' ';
300 screen[y][nxu] = '^';
301 if(!debug_disp)
302 {
303 if((y<(sy+3)) && (y>(sy-5)) && (x>(sx-6)) && (x<(sx+6)))
304 draw_symbol((x-sx+5)*3,(y-sy+4)*2,' ');
305 if((y<(sy+4)) && (y>(sy-4)) && (nxu>(sx-6)) && (nxu<(sx+6)))
306 draw_symbol((nxu-sx+5)*3,(y-sy+3)*2,'^');
307 }
308 else
309 {
310 move(y+2,x+1);
311 addch(' ');
312 move(y+1,nxu+1);
313 addch('^');
314 }
315 refresh();
316 retval+=fall(mx,my,nxu ,y-1,sx,sy,howdead);
317 retval+=check(mx,my,x,y+1,0,-1,sx,sy,howdead);
318 }
319
320 nx = x; ny = y;
321
322 if(screen[y][x] == ' ') { /* thingy moves? */
323 if((y>1)&&(screen[y-1][x]=='~')&&(screen[y-2][x]=='O'))
324 /* boulder pushes */
325 ny--;
326 else {
327 if((x>1)&&(screen[y][x-1]=='~')&&(screen[y][x-2]=='>'))
328 /* arrow pushes */
329 nx--;
330 else {
331 if((x<(ROWLEN-1))&&(screen[y][x+1]=='~')&&(screen[y][x+2]=='<'))
332 /* arrow pushes */
333 nx++;
334 else {
335 if((y<(NOOFROWS-1))&&(screen[y+1][x]=='~')&&(screen[y+2][x]=='^'))
336 /* balloon pushes */
337 ny++;
338 }}}
339
340 if(( x != nx )||( y != ny )) {
341 screen[y][x] = '~';
342 screen[ny][nx] = screen[2*ny-y][2*nx-x];
343 screen[2*ny-y][2*nx-x] = ' ';
344 if(!debug_disp) {
345 if(((2*ny-y)<(sy+4)) && ((2*ny-y)>(sy-4))
346 && ((2*nx-x)>(sx-6)) && ((2*nx-x)<(sx+6)))
347 draw_symbol((2*nx-x-sx+5)*3,(2*ny-y-sy+3)*2,' ');
348 if((y<(sy+4)) && (y>(sy-4)) && (x>(sx-6)) && (x<(sx+6)))
349 draw_symbol((x-sx+5)*3,(y-sy+3)*2,'~');
350 if((ny<(sy+4)) && (ny>(sy-4)) && (nx>(sx-6)) && (nx<(sx+6)))
351 draw_symbol((nx-sx+5)*3,(ny-sy+3)*2,screen[ny][nx]);
352 } else {
353 move(ny*2-y+1,nx*2-x+1);
354 addch(' ');
355 move(ny+1,nx+1);
356 addch(screen[ny][nx]);
357 move(y+1,x+1);
358 addch('~');
359 }
360 refresh();
361 retval+=fall(mx,my,2*x-nx,2*y-ny,sx,sy,howdead);
362 retval+=check(mx,my,2*nx-x,2*ny-y,nx-x,ny-y,sx,sy,howdead);
363 }
364 }
365
366 if(retval>0)
367 return(1);
368 return(0);
369 }
370
371 /**********************************************
372 * function bang *
373 ***********************************************/
bang(x,y,mx,my,sx,sy,howdead)374 int bang(x,y,mx,my,sx,sy,howdead) /* explosion centre x,y */
375 int x,y,sx,sy,*mx,*my;
376 char *howdead;
377 {
378 int retval = 0;
379 int ba,bb; /* abbrevs for 'bang index a' and 'bang index b' :-) */
380 int gottim = 0;
381 screen[y][x] = ' ';
382 /* fill with bangs */
383 for(ba = -1; ba < 2; ba++ )
384 for(bb = -1; bb < 2; bb++ ) {
385 if(screen[y+ba][x+bb] == '#') continue; /* rock indestructable */
386 if(screen[y+ba][x+bb] == '@') gottim = 1;
387 if(screen[y+ba][x+bb] == 'M') *mx = *my = -2; /* kill monster */
388 if(screen[y+ba][x+bb] == 'B')
389 gottim += bang(x+bb,y+ba,mx,my,sx,sy,howdead);
390 screen[y+ba][x+bb] = ' ';
391 if(!debug_disp) {
392 if(((y+ba)<(sy+4)) && ((y+ba)>(sy-4)) && ((x+bb)>(sx-6))
393 && ((x+bb)<(sx+6)) && (y+ba >= 0 ) && (x +bb >= 0) &&
394 ((x+bb)<ROWLEN) && ((y+ba)<NOOFROWS) )
395 draw_symbol((x+bb-sx+5)*3,(y+ba-sy+3)*2,'%');
396 } else {
397 if( ((x+bb)>-1) && ((y+ba)>-1) &&
398 ((x+bb)<ROWLEN) && ((y+ba)<NOOFROWS) ) {
399 move(y+ba+1,x+bb+1);
400 addch('%');
401 }
402 }
403 }
404 refresh();
405 if(gottim) {
406 strcpy(howdead,"an exploding bomb");
407 return 1;
408 }
409 /* erase it all */
410 for(ba = -1; ba < 2; ba++ )
411 for(bb = -1; bb < 2; bb++ ) {
412 if(screen[y+ba][x+bb] == '#') continue;
413 if(!debug_disp) {
414 if(((y+ba)<(sy+4)) && ((y+ba)>(sy-4)) && ((x+bb)>(sx-6))
415 && ((x+bb)<(sx+6)) && (y+ba > -1) && (x+bb > -1) &&
416 ((x+bb)<ROWLEN) && ((y+ba)<NOOFROWS) )
417 draw_symbol((x+bb-sx+5)*3,(y+ba-sy+3)*2,' ');
418 } else {
419 if( ((x+bb)>-1) && ((y+ba)>-1) &&
420 ((x+bb)<ROWLEN) && ((y+ba)<NOOFROWS) ) {
421 move(y+ba+1,x+bb+1);
422 addch(' ');
423 }
424 }
425 }
426
427 /* make all the necessary falling */
428 retval = check(mx,my,x-1,y-1,1,0,sx,sy,howdead);
429 retval += check(mx,my,x-1,y+1,0,-1,sx,sy,howdead);
430 retval += check(mx,my,x+1,y-1,0,1,sx,sy,howdead);
431 retval += check(mx,my,x+1,y+1,-1,0,sx,sy,howdead);
432 return retval;
433 }
434