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