chiark / gitweb /
a9e87b7e266e2c85174fbdcb11bacaca3898f926
[xor] / cell.c
1 /* -*-c-*-
2  *
3  * $Id: cell.c,v 1.1 2003/12/12 10:55:30 mdw Exp $
4  *
5  * Cell attributes and behaviour
6  *
7  * (c) 2003 Straylight/Edgeware
8  */
9
10 /*----- Licensing notice --------------------------------------------------* 
11  *
12  * This file is part of XOR.
13  *
14  * XOR is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  * 
19  * XOR is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  * 
24  * You should have received a copy of the GNU General Public License
25  * along with XOR; if not, write to the Free Software Foundation,
26  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27  */
28
29 /*----- Revision history --------------------------------------------------* 
30  *
31  * $Log: cell.c,v $
32  * Revision 1.1  2003/12/12 10:55:30  mdw
33  * Initial checkin.  Not there yet.
34  *
35  */
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #include "xor.h"
40
41 /*----- Global variables --------------------------------------------------*/
42
43 const cellinfo *cellmap[UCHAR_MAX];
44
45 /*----- Object behaviour --------------------------------------------------*/
46
47 /* --- Player --- */
48
49 static void player_hit(game_state *g, int x, int y, int hx, int hy)
50 {
51   game_die(g, x, y);
52 }
53
54 /* --- Bombs --- */
55
56 static void hbomb_hit(game_state *g, int x, int y, int hx, int hy)
57 {
58   point pt[4];
59   int n = 0;
60
61   pt[n].x = x; pt[n].y = y; n++;
62   pt[n].x = x; pt[n].y = y + 1; n++;
63   pt[n].x = x; pt[n].y = y - 1; n++;
64   if (hx != x) { pt[n].x = hx; pt[n].y = hy; n++; }
65   game_explode(g, pt, n);
66 }
67
68 static void vbomb_hit(game_state *g, int x, int y, int hx, int hy)
69 {
70   point pt[4];
71   int n = 0;
72
73   pt[n].x = x; pt[n].y = y; n++;
74   pt[n].x = x - 1; pt[n].y = y; n++;
75   pt[n].x = x + 1; pt[n].y = y; n++;
76   if (hy != y) { pt[n].x = hx; pt[n].y = hy; n++; }
77   game_explode(g, pt, n);
78 }
79
80 /* --- Exit --- */
81
82 static int exit_nudge(game_state *g, int x, int y, int dx, int dy)
83 {
84   if (g->l->m == g->l->mtot) {
85     g->f |= GF_QUIT | GF_WIN;
86     return (1);
87   }
88   return (0);
89 }
90
91 /* --- Masks --- */
92
93 static int mask_nudge(game_state *g, int x, int y, int dx, int dy)
94 {
95   undo_mask(g);
96   g->l->m++;
97   return (1);
98 }
99
100 static int switch_nudge(game_state *g, int x, int y, int dx, int dy)
101 {
102   undo_mask(g);
103   undo_levelf(g);
104   g->l->f ^= LF_DARK;
105   g->l->m++;
106   return (1);
107 }
108
109 /* --- Map segments --- */
110
111 static int map_nudge(game_state *g, int x, int y, int dx, int dy)
112 {
113   undo_levelf(g);
114   g->l->f |= LF_NWMAP << (CELL(g->l, x, y) - C_NWMAP);
115   return (1);
116 }
117
118 /* --- Chickens and fish --- */
119
120 static int chicken_nudge(game_state *g, int x, int y, int dx, int dy)
121 {
122   if (dx) return (0);
123   if (!(cellmap[CELL(g->l, x, y + dy) & CF_CELLMASK]->f & CF_VPASS))
124     return (0);
125   game_moveobj(g, x, y, x, y + dy);
126   return (1);
127 }
128
129 static int fish_nudge(game_state *g, int x, int y, int dx, int dy)
130 {
131   if (dy) return (0);
132   if (!(cellmap[CELL(g->l, x + dx, y) & CF_CELLMASK]->f & CF_HPASS))
133     return (0);
134   game_moveobj(g, x, y, x + dx, y);
135   return (1);
136 }
137
138 static int chicken_moveh(game_state *g, int x, int y)
139 {
140   level *l = g->l;
141   int c;
142
143   c = CELL(l, x - 1, y) & CF_CELLMASK;
144   if (!(cellmap[c]->f & CF_HPASS))
145     return (0);
146   game_moveobj(g, x, y, x - 1, y);
147   x--;
148   c = CELL(l, x - 1, y);
149   if (!(c & CF_INFLIGHT) && cellmap[c & CF_CELLMASK]->hit)
150     cellmap[c & CF_CELLMASK]->hit(g, x - 1, y, x, y);
151   if (cellmap[CELL(l, x - 1, y) & CF_CELLMASK]->f & CF_HPASS)
152     CELLSETFL(l, x, y, CF_INFLIGHT);
153   else
154     CELLCLRFL(l, x, y, CF_INFLIGHT);
155   return (1);
156 }
157
158 static int fish_movev(game_state *g, int x, int y)
159 {
160   level *l = g->l;
161   int c;
162
163   c = CELL(l, x, y + 1) & CF_CELLMASK;
164   if (!(cellmap[c]->f & CF_VPASS))
165     return (0);
166   game_moveobj(g, x, y, x, y + 1);
167   y++;
168   c = CELL(l, x, y + 1);
169   if (!(c & CF_INFLIGHT) && cellmap[c & CF_CELLMASK]->hit)
170     cellmap[c & CF_CELLMASK]->hit(g, x, y + 1, x, y);
171   if (cellmap[CELL(l, x, y + 1) & CF_CELLMASK]->f & CF_VPASS)
172     CELLSETFL(l, x, y, CF_INFLIGHT);
173   else
174     CELLCLRFL(l, x, y, CF_INFLIGHT);
175   return (1);
176 }
177
178 /* --- Dollies --- */
179
180 static int dolly_nudge(game_state *g, int x, int y, int dx, int dy)
181 {
182   if (CELL(g->l, x + dx, y + dy) != C_EMPTY)
183     return (0);
184   game_moveobj(g, x, y, x + dx, y + dy);
185   x += dx; y += dy;
186   if (CELL(g->l, x + dx, y + dy) == C_EMPTY) {
187     if (dx < 0) CELLSETFL(g->l, x, y, CF_DOLLYLEFT | CF_INFLIGHT);
188     else if (dx > 0) CELLSETFL(g->l, x, y, CF_DOLLYRIGHT | CF_INFLIGHT);
189     else if (dy < 0) CELLSETFL(g->l, x, y, CF_DOLLYUP | CF_INFLIGHT);
190     else if (dy > 0) CELLSETFL(g->l, x, y, CF_DOLLYDOWN | CF_INFLIGHT);
191   }
192   return (1);
193 }
194
195 static int dolly_moveh(game_state *g, int x, int y)
196 {
197   int c = CELL(g->l, x, y);
198   int dx;
199
200   if (!(c & CF_INFLIGHT)) return (0);
201   switch (c & CF_DOLLYMASK) {
202     case CF_DOLLYLEFT: dx = -1; break;
203     case CF_DOLLYRIGHT: dx = +1; break;
204     default: return (0);
205   }
206   game_moveobj(g, x, y, x + dx, y);
207   x += dx;
208   if (CELL(g->l, x + dx, y) != C_EMPTY)
209     CELLCLRFL(g->l, x, y, CF_DOLLYMASK | CF_INFLIGHT);
210   return (1);
211 }
212
213 static int dolly_movev(game_state *g, int x, int y)
214 {
215   int c = CELL(g->l, x, y);
216   int dy;
217
218   if (!(c & CF_INFLIGHT)) return (0);
219   switch (c & CF_DOLLYMASK) {
220     case CF_DOLLYUP: dy = -1; break;
221     case CF_DOLLYDOWN: dy = +1; break;
222     default: return (0);
223   }
224   game_moveobj(g, x, y, x, y + dy);
225   y += dy;
226   if (CELL(g->l, x, y + dy) != C_EMPTY)
227     CELLCLRFL(g->l, x, y, CF_DOLLYMASK | CF_INFLIGHT);
228   return (1);
229 }
230
231 /*----- The object table --------------------------------------------------*/
232
233 static cellinfo celltab[] = {
234
235   { /* cell type */     C_PLAYER,
236     /* flags */         CF_PLAYER,
237     /* hit */           player_hit,
238     /* nudge */         0,
239     /* horiz move */    0,
240     /* vert move */     0,
241   },
242
243   { /* cell type */     C_SPARE,
244     /* flags */         CF_PLAYER,
245     /* hit */           player_hit,
246     /* nudge */         0,
247     /* horiz move */    0,
248     /* vert move */     0,
249   },
250
251   { /* cell type */     C_WALL,
252     /* flags */         CF_HIDE | CF_MAP,
253     /* hit */           0,
254     /* nudge */         0,
255     /* horiz move */    0,
256     /* vert move */     0,
257   },
258
259   { /* cell type */     C_EXIT,
260     /* flags */         CF_MAP,
261     /* hit */           0,
262     /* nudge */         exit_nudge,
263     /* horiz move */    0,
264     /* vert move */     0,
265   },
266
267   { /* cell type */     C_EMPTY,
268     /* flags */         CF_HPASS | CF_VPASS,
269     /* hit */           0,
270     /* nudge */         0,
271     /* horiz move */    0,
272     /* vert move */     0,
273   },
274
275   { /* cell type */     C_MASK,
276     /* flags */         CF_MASK | CF_MAP,
277     /* hit */           0,
278     /* nudge */         mask_nudge,
279     /* horiz move */    0,
280     /* vert move */     0,
281   },
282
283   { /* cell type */     C_NWMAP,
284     /* flags */         0,
285     /* hit */           0,
286     /* nudge */         map_nudge,
287     /* horiz move */    0,
288     /* vert move */     0,
289   },
290
291   { /* cell type */     C_NEMAP,
292     /* flags */         0,
293     /* hit */           0,
294     /* nudge */         map_nudge,
295     /* horiz move */    0,
296     /* vert move */     0,
297   },
298
299   { /* cell type */     C_SWMAP,
300     /* flags */         0,
301     /* hit */           0,
302     /* nudge */         map_nudge,
303     /* horiz move */    0,
304     /* vert move */     0,
305   },
306
307   { /* cell type */     C_SEMAP,
308     /* flags */         0,
309     /* hit */           0,
310     /* nudge */         map_nudge,
311     /* horiz move */    0,
312     /* vert move */     0,
313   },
314
315   { /* cell type */     C_DOT,
316     /* flags */         CF_HPASS,
317     /* hit */           0,
318     /* nudge */         0,
319     /* horiz move */    0,
320     /* vert move */     0,
321   },
322
323   { /* cell type */     C_WAVE,
324     /* flags */         CF_VPASS,
325     /* hit */           0,
326     /* nudge */         0,
327     /* horiz move */    0,
328     /* vert move */     0,
329   },
330
331   { /* cell type */     C_CHICKEN,
332     /* flags */         0,
333     /* hit */           0,
334     /* nudge */         chicken_nudge,
335     /* horiz move */    chicken_moveh,
336     /* vert move */     0,
337   },
338
339   { /* cell type */     C_FISH,
340     /* flags */         0,
341     /* hit */           0,
342     /* nudge */         fish_nudge,
343     /* horiz move */    0,
344     /* vert move */     fish_movev,
345   },
346
347   { /* cell type */     C_HBOMB,
348     /* flags */         0,
349     /* hit */           hbomb_hit,
350     /* nudge */         chicken_nudge,
351     /* horiz move */    chicken_moveh,
352     /* vert move */     0,
353   },
354
355   { /* cell type */     C_VBOMB,
356     /* flags */         0,
357     /* hit */           vbomb_hit,
358     /* nudge */         fish_nudge,
359     /* horiz move */    0,
360     /* vert move */     fish_movev,
361   },
362
363   { /* cell type */     C_DOLLY,
364     /* flags */         0,
365     /* hit */           0,
366     /* nudge */         dolly_nudge,
367     /* horiz move */    dolly_moveh,
368     /* vert move */     dolly_movev,
369   },
370
371   { /* cell type */     C_SWITCH,
372     /* flags */         CF_MASK | CF_MAP,
373     /* hit */           0,
374     /* nudge */         switch_nudge,
375     /* horiz move */    0,
376     /* vert move */     0,
377   },
378
379   { /* cell type */     C_BMUS,
380     /* flags */         0,
381     /* hit */           0,
382     /* nudge */         0,
383     /* horiz move */    0,
384     /* vert move */     0,
385   },
386
387   { /* cell type */     0,
388     /* flags */         0,
389     /* hit */           0,
390     /* nudge */         0,
391     /* horiz move */    0,
392     /* vert move */     0,
393   }
394 };
395
396 void cellinfo_init(void)
397 {
398   int i;
399
400   for (i = 0; celltab[i].c; i++) cellmap[celltab[i].c] = &celltab[i];
401 }
402
403 /*----- That's all, folks -------------------------------------------------*/