1 /* File monsters.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 typedef struct { int d[2]; } direction;
26 
27 #ifdef        LINT_ARGS        /* M001 */
28 direction new_direction(int, int, int, int);
29 #else
30 direction new_direction();
31 #endif
32 
33 extern void draw_symbol();
34 extern int debug_disp;
35 extern int edit_mode;
36 extern char screen[NOOFROWS][ROWLEN+1];
37 
38 /* Add a spirit to the chain */
39 /* Maintain a doubly linked list to make reuse possible.
40    tail_of_list is *NOT* the last monster allocated, but
41    the last monster alloted to a screen.  start_of_list
42    is a dummy entry to ease processing. last_of_list
43    is the last entry allocated. */
44 
45 extern struct mon_rec *last_of_list, *tail_of_list;
46 extern struct mon_rec start_of_list;
47 
48 /********************************************************
49 *                 function make_monster                 *
50 *********************************************************/
make_monster(x,y)51 struct mon_rec *make_monster(x,y)
52 int x,y;
53 {
54     char *malloc();
55     #define MALLOC (struct mon_rec *)malloc(sizeof(struct mon_rec))
56     struct mon_rec *monster;
57     if(tail_of_list->next == NULL)
58     {
59         if((last_of_list = MALLOC) == NULL)
60             return NULL;
61         tail_of_list->next = last_of_list;
62         last_of_list->prev = tail_of_list;
63         last_of_list->next = NULL;
64     }
65     monster = tail_of_list = tail_of_list->next;
66     monster->x = x;
67     monster->y = y;
68     monster->mx = 1;      /* always start moving RIGHT. (fix later)  */
69     monster->my = 0;
70     monster->under = ' ';
71     return monster;
72 }
73 
74 /********************************************************************
75 *                      function direction                           *
76 *********************************************************************/
77 /* 'follow lefthand wall' algorithm for baby monsters */
78 
new_direction(x,y,bx,by)79 direction new_direction(x,y,bx,by)
80                         int x,y,bx,by;
81 {
82     direction out;
83     if(viable((x+by),(y-bx)))
84     {
85         out.d[0] = by;
86         out.d[1] = -bx;
87         return out;
88     }
89     if(viable((x+bx),(y+by)))
90     {
91         out.d[0] = bx;
92         out.d[1] = by;
93         return out;
94     }
95     if(viable((x-by),(y+bx)))
96     {
97         out.d[0] = -by;
98         out.d[1] = bx;
99         return out;
100     }
101     if(viable((x-bx),(y-by)))
102     {
103         out.d[0] = -bx;
104         out.d[1] = -by;
105         return out;
106     }
107     out.d[0] = -bx;
108     out.d[1] = -by;
109     return out;
110 }
111 
112 /***********************************************************
113 *                   function move_monsters                 *
114 ************************************************************/
move_monsters(mxp,myp,score,howdead,sx,sy,nf,bell,x,y,diamonds)115 int move_monsters(mxp, myp, score, howdead, sx, sy, nf, bell, x, y, diamonds)
116                   int *mxp, *myp, *score, sx, sy, nf, bell, x, y, diamonds;
117                   char *howdead;
118 {
119     int xdirection, ydirection, hd, vd;
120     int deadyet = 0;
121     int bx, by, nbx, nby, tmpx,tmpy;
122     direction new_disp;
123     struct mon_rec *monster,*current;
124     char buffer[25];
125 
126 /* big monster first */
127     if(*mxp == -2)                       /* has the monster been killed ? */
128     {
129         *score+=100;
130         *mxp = *myp = -1;
131         move(3,48);
132         sprintf(buffer,"%d\t %d\t",*score,nf);
133         (void) addstr(buffer);
134         draw_symbol(50,11,' ');
135         move(12,56); addstr("              ");
136         move(13,56); addstr("              ");
137         move(16,0);
138         refresh();
139     }                                     /* if monster still alive */
140 
141     if(*mxp != -1)                        /* then move that monster ! */
142     {
143         screen[*myp][*mxp] = ' ';
144         if(*mxp>x)
145             xdirection = -1;
146         else
147             xdirection = 1;
148         if(!debug_disp)
149         {
150             if((*myp<(sy+4))&&(*myp>(sy-4))&&(*mxp<(sx+6))&&(*mxp>(sx-6)))
151                 draw_symbol((*mxp-sx+5)*3,(*myp-sy+3)*2,' ');
152         }
153         else
154         {
155             move(*myp+1,*mxp+1);
156             addch(' ');
157         }
158         if((hd = (*mxp-x))<0)
159             hd = -hd;
160         if((vd = (*myp-y))<0)
161             vd = -vd;
162         if((hd>vd)&&((*mxp+xdirection)<ROWLEN)&&((screen[*myp][*mxp+xdirection] == ' ')||(screen[*myp][*mxp+xdirection] == '@')))
163             *mxp+=xdirection;
164         else
165         {
166             if(*myp>y)
167                 ydirection = -1;
168             else
169                 ydirection = 1;
170             if(((*myp+ydirection)<NOOFROWS)&& ((screen[*myp+ydirection][*mxp]
171 == ' ')||(screen[*myp+ydirection][*mxp] == '@')))
172                 *myp+=ydirection;
173             else
174                 if(((*mxp+xdirection)<ROWLEN)&&(screen[*myp][*mxp+xdirection] == ' ')||(screen[*myp][*mxp+xdirection] == '@'))
175             *mxp+=xdirection;
176         }
177         if(!debug_disp)
178         {
179             if((*myp<(sy+4))&&(*myp>(sy-4))&&(*mxp<(sx+6))&&(*mxp>(sx-6)))
180                 draw_symbol((*mxp-sx+5)*3,(*myp-sy+3)*2,'M');
181         }
182         else
183         {
184             move(*myp+1,*mxp+1);
185             addch('M');
186         }
187         if(screen[*myp][*mxp] == '@')                     /* ha! gottim! */
188         {
189             strcpy(howdead,"a hungry monster");
190             move(16,0);
191             refresh();
192             deadyet = 1;
193         }
194         screen[*myp][*mxp] = 'M';
195         move(16,0);
196         refresh();
197     }
198 
199     current = &start_of_list;                         /* baby monsters now */
200     while((current != tail_of_list)&&(!deadyet))
201     /* deal with those little monsters */
202     {
203         monster = current->next;
204         new_disp = new_direction( monster->x, monster->y, monster->mx, monster->my );
205         if(monster->under!='S')             /* if on top of another baby */
206         {
207             screen[monster->y][monster->x] = monster->under;
208             if(!debug_disp)
209             {
210                 if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
211                     draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,monster->under);
212             }
213             else
214             {
215                 move(monster->y+1,monster->x+1);
216                 addch(monster->under);
217             }
218             if(monster->under == ' ')
219                 deadyet+=check(&*mxp,&*myp,monster->x,monster->y,new_disp.d[0],new_disp.d[1],sx,sy,howdead);
220         }
221         else
222             monster->under=' ';
223         monster->mx = new_disp.d[0];
224         monster->my = new_disp.d[1];
225         monster->x += monster->mx;
226         monster->y += monster->my;
227         monster->under = screen[monster->y][monster->x];
228         screen[monster->y][monster->x] = 'S';        /* move into new space */
229         if(!debug_disp)
230         {
231             if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
232                 draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,'S');
233         }
234         else
235         {
236             move(monster->y+1,monster->x+1);
237             addch('S');
238         }
239         if(monster->under == '@')                     /* monster hit you? */
240         {
241             strcpy(howdead,"the little monsters");
242             move(16,0);
243             refresh();
244             deadyet = 1;
245             monster->under = ' ';
246         }
247         if(monster->under == '+')                    /* monster hit cage? */
248         {
249 #ifdef NOISY
250             if(bell) printf("\007");
251 #endif
252             *score +=20;
253             move(3,48);
254             sprintf(buffer,"%d\t %d\t %d ",*score,nf,diamonds);
255             (void) addstr(buffer);
256         /* remove from chain, and insert at the end (at last_of_list) */
257             if(monster == tail_of_list)
258                 tail_of_list = tail_of_list->prev;
259             else
260             {
261                 current->next = monster-> next;
262                 current->next->prev = current;
263                 monster->next = NULL;
264                 monster->prev = last_of_list;
265                 last_of_list->next = monster;
266                 last_of_list = monster;
267             }
268             screen[monster->y][monster->x] = '*';
269             if(!debug_disp)
270             {
271                 if((monster->y < (sy+4)) && (monster->y > (sy-4)) && (monster->x < (sx+6)) && (monster->x > (sx-6)))
272                     draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,'*');
273             }
274             else
275             {
276                 move(monster->y+1,monster->x+1);
277                 addch('*');
278             }
279         }
280         else
281             current = monster;
282         move(16,0);
283         refresh();
284     }
285     return deadyet;
286 }
287