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