chiark / gitweb /
infra: Clean up project setup
[xor] / cell.c
1 /* -*-c-*-
2  *
3  * $Id$
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 /*----- Header files ------------------------------------------------------*/
30
31 #include "xor.h"
32
33 /*----- Global variables --------------------------------------------------*/
34
35 const cellinfo *cellmap[UCHAR_MAX];
36
37 /*----- Object behaviour --------------------------------------------------*/
38
39 /* --- Player --- */
40
41 static void player_hit(game_state *g, int x, int y, int hx, int hy)
42 {
43   game_die(g, x, y);
44 }
45
46 /* --- Bombs --- */
47
48 static void hbomb_hit(game_state *g, int x, int y, int hx, int hy)
49 {
50   point pt[4];
51   int n = 0;
52
53   pt[n].x = x; pt[n].y = y; n++;
54   pt[n].x = x; pt[n].y = y + 1; n++;
55   pt[n].x = x; pt[n].y = y - 1; n++;
56   if (hx != x) { pt[n].x = hx; pt[n].y = hy; n++; }
57   game_explode(g, pt, n);
58 }
59
60 static void vbomb_hit(game_state *g, int x, int y, int hx, int hy)
61 {
62   point pt[4];
63   int n = 0;
64
65   pt[n].x = x; pt[n].y = y; n++;
66   pt[n].x = x - 1; pt[n].y = y; n++;
67   pt[n].x = x + 1; pt[n].y = y; n++;
68   if (hy != y) { pt[n].x = hx; pt[n].y = hy; n++; }
69   game_explode(g, pt, n);
70 }
71
72 /* --- Exit --- */
73
74 static int exit_nudge(game_state *g, int x, int y, int dx, int dy)
75 {
76   if (g->l->m == g->l->mtot) {
77     g->f |= GF_QUIT | GF_WIN;
78     return (1);
79   }
80   return (0);
81 }
82
83 /* --- Masks --- */
84
85 static int mask_nudge(game_state *g, int x, int y, int dx, int dy)
86 {
87   undo_mask(g);
88   g->l->m++;
89   return (1);
90 }
91
92 static int switch_nudge(game_state *g, int x, int y, int dx, int dy)
93 {
94   undo_mask(g);
95   undo_levelf(g);
96   g->l->f ^= LF_DARK;
97   g->l->m++;
98   return (1);
99 }
100
101 /* --- Map segments --- */
102
103 static int map_nudge(game_state *g, int x, int y, int dx, int dy)
104 {
105   undo_levelf(g);
106   g->l->f |= LF_NWMAP << (CELL(g->l, x, y) - C_NWMAP);
107   return (1);
108 }
109
110 /* --- Chickens and fish --- */
111
112 static int chicken_nudge(game_state *g, int x, int y, int dx, int dy)
113 {
114   if (dx) return (0);
115   if (!(cellmap[CELL(g->l, x, y + dy) & CF_CELLMASK]->f & CF_VPASS))
116     return (0);
117   game_moveobj(g, x, y, x, y + dy);
118   return (1);
119 }
120
121 static int fish_nudge(game_state *g, int x, int y, int dx, int dy)
122 {
123   if (dy) return (0);
124   if (!(cellmap[CELL(g->l, x + dx, y) & CF_CELLMASK]->f & CF_HPASS))
125     return (0);
126   game_moveobj(g, x, y, x + dx, y);
127   return (1);
128 }
129
130 static int chicken_moveh(game_state *g, int x, int y)
131 {
132   level *l = g->l;
133   int c;
134
135   c = CELL(l, x - 1, y) & CF_CELLMASK;
136   if (!(cellmap[c]->f & CF_HPASS))
137     return (0);
138   game_moveobj(g, x, y, x - 1, y);
139   x--;
140   c = CELL(l, x - 1, y);
141   if (!(c & CF_INFLIGHT) && cellmap[c & CF_CELLMASK]->hit)
142     cellmap[c & CF_CELLMASK]->hit(g, x - 1, y, x, y);
143   if (cellmap[CELL(l, x - 1, y) & CF_CELLMASK]->f & CF_HPASS)
144     CELLSETFL(l, x, y, CF_INFLIGHT);
145   else
146     CELLCLRFL(l, x, y, CF_INFLIGHT);
147   return (1);
148 }
149
150 static int fish_movev(game_state *g, int x, int y)
151 {
152   level *l = g->l;
153   int c;
154
155   c = CELL(l, x, y + 1) & CF_CELLMASK;
156   if (!(cellmap[c]->f & CF_VPASS))
157     return (0);
158   game_moveobj(g, x, y, x, y + 1);
159   y++;
160   c = CELL(l, x, y + 1);
161   if (!(c & CF_INFLIGHT) && cellmap[c & CF_CELLMASK]->hit)
162     cellmap[c & CF_CELLMASK]->hit(g, x, y + 1, x, y);
163   if (cellmap[CELL(l, x, y + 1) & CF_CELLMASK]->f & CF_VPASS)
164     CELLSETFL(l, x, y, CF_INFLIGHT);
165   else
166     CELLCLRFL(l, x, y, CF_INFLIGHT);
167   return (1);
168 }
169
170 /* --- Dollies --- */
171
172 static int dolly_nudge(game_state *g, int x, int y, int dx, int dy)
173 {
174   if (CELL(g->l, x + dx, y + dy) != C_EMPTY)
175     return (0);
176   game_moveobj(g, x, y, x + dx, y + dy);
177   x += dx; y += dy;
178   if (CELL(g->l, x + dx, y + dy) == C_EMPTY) {
179     if (dx < 0) CELLSETFL(g->l, x, y, CF_DOLLYLEFT | CF_INFLIGHT);
180     else if (dx > 0) CELLSETFL(g->l, x, y, CF_DOLLYRIGHT | CF_INFLIGHT);
181     else if (dy < 0) CELLSETFL(g->l, x, y, CF_DOLLYUP | CF_INFLIGHT);
182     else if (dy > 0) CELLSETFL(g->l, x, y, CF_DOLLYDOWN | CF_INFLIGHT);
183   }
184   return (1);
185 }
186
187 static int dolly_moveh(game_state *g, int x, int y)
188 {
189   int c = CELL(g->l, x, y);
190   int dx;
191
192   if (!(c & CF_INFLIGHT)) return (0);
193   switch (c & CF_DOLLYMASK) {
194     case CF_DOLLYLEFT: dx = -1; break;
195     case CF_DOLLYRIGHT: dx = +1; break;
196     default: return (0);
197   }
198   game_moveobj(g, x, y, x + dx, y);
199   x += dx;
200   if (CELL(g->l, x + dx, y) != C_EMPTY)
201     CELLCLRFL(g->l, x, y, CF_DOLLYMASK | CF_INFLIGHT);
202   return (1);
203 }
204
205 static int dolly_movev(game_state *g, int x, int y)
206 {
207   int c = CELL(g->l, x, y);
208   int dy;
209
210   if (!(c & CF_INFLIGHT)) return (0);
211   switch (c & CF_DOLLYMASK) {
212     case CF_DOLLYUP: dy = -1; break;
213     case CF_DOLLYDOWN: dy = +1; break;
214     default: return (0);
215   }
216   game_moveobj(g, x, y, x, y + dy);
217   y += dy;
218   if (CELL(g->l, x, y + dy) != C_EMPTY)
219     CELLCLRFL(g->l, x, y, CF_DOLLYMASK | CF_INFLIGHT);
220   return (1);
221 }
222
223 /*----- The object table --------------------------------------------------*/
224
225 static cellinfo celltab[] = {
226
227   { /* cell type */     C_PLAYER,
228     /* flags */         CF_PLAYER,
229     /* hit */           player_hit,
230     /* nudge */         0,
231     /* horiz move */    0,
232     /* vert move */     0,
233   },
234
235   { /* cell type */     C_SPARE,
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_WALL,
244     /* flags */         CF_HIDE | CF_MAP,
245     /* hit */           0,
246     /* nudge */         0,
247     /* horiz move */    0,
248     /* vert move */     0,
249   },
250
251   { /* cell type */     C_EXIT,
252     /* flags */         CF_MAP,
253     /* hit */           0,
254     /* nudge */         exit_nudge,
255     /* horiz move */    0,
256     /* vert move */     0,
257   },
258
259   { /* cell type */     C_EMPTY,
260     /* flags */         CF_HPASS | CF_VPASS,
261     /* hit */           0,
262     /* nudge */         0,
263     /* horiz move */    0,
264     /* vert move */     0,
265   },
266
267   { /* cell type */     C_MASK,
268     /* flags */         CF_MASK | CF_MAP,
269     /* hit */           0,
270     /* nudge */         mask_nudge,
271     /* horiz move */    0,
272     /* vert move */     0,
273   },
274
275   { /* cell type */     C_NWMAP,
276     /* flags */         0,
277     /* hit */           0,
278     /* nudge */         map_nudge,
279     /* horiz move */    0,
280     /* vert move */     0,
281   },
282
283   { /* cell type */     C_NEMAP,
284     /* flags */         0,
285     /* hit */           0,
286     /* nudge */         map_nudge,
287     /* horiz move */    0,
288     /* vert move */     0,
289   },
290
291   { /* cell type */     C_SWMAP,
292     /* flags */         0,
293     /* hit */           0,
294     /* nudge */         map_nudge,
295     /* horiz move */    0,
296     /* vert move */     0,
297   },
298
299   { /* cell type */     C_SEMAP,
300     /* flags */         0,
301     /* hit */           0,
302     /* nudge */         map_nudge,
303     /* horiz move */    0,
304     /* vert move */     0,
305   },
306
307   { /* cell type */     C_DOT,
308     /* flags */         CF_HPASS,
309     /* hit */           0,
310     /* nudge */         0,
311     /* horiz move */    0,
312     /* vert move */     0,
313   },
314
315   { /* cell type */     C_WAVE,
316     /* flags */         CF_VPASS,
317     /* hit */           0,
318     /* nudge */         0,
319     /* horiz move */    0,
320     /* vert move */     0,
321   },
322
323   { /* cell type */     C_CHICKEN,
324     /* flags */         0,
325     /* hit */           0,
326     /* nudge */         chicken_nudge,
327     /* horiz move */    chicken_moveh,
328     /* vert move */     0,
329   },
330
331   { /* cell type */     C_FISH,
332     /* flags */         0,
333     /* hit */           0,
334     /* nudge */         fish_nudge,
335     /* horiz move */    0,
336     /* vert move */     fish_movev,
337   },
338
339   { /* cell type */     C_HBOMB,
340     /* flags */         0,
341     /* hit */           hbomb_hit,
342     /* nudge */         chicken_nudge,
343     /* horiz move */    chicken_moveh,
344     /* vert move */     0,
345   },
346
347   { /* cell type */     C_VBOMB,
348     /* flags */         0,
349     /* hit */           vbomb_hit,
350     /* nudge */         fish_nudge,
351     /* horiz move */    0,
352     /* vert move */     fish_movev,
353   },
354
355   { /* cell type */     C_DOLLY,
356     /* flags */         0,
357     /* hit */           0,
358     /* nudge */         dolly_nudge,
359     /* horiz move */    dolly_moveh,
360     /* vert move */     dolly_movev,
361   },
362
363   { /* cell type */     C_SWITCH,
364     /* flags */         CF_MASK | CF_MAP,
365     /* hit */           0,
366     /* nudge */         switch_nudge,
367     /* horiz move */    0,
368     /* vert move */     0,
369   },
370
371   { /* cell type */     C_BMUS,
372     /* flags */         0,
373     /* hit */           0,
374     /* nudge */         0,
375     /* horiz move */    0,
376     /* vert move */     0,
377   },
378
379   { /* cell type */     0,
380     /* flags */         0,
381     /* hit */           0,
382     /* nudge */         0,
383     /* horiz move */    0,
384     /* vert move */     0,
385   }
386 };
387
388 void cellinfo_init(void)
389 {
390   int i;
391
392   for (i = 0; celltab[i].c; i++) cellmap[celltab[i].c] = &celltab[i];
393 }
394
395 /*----- That's all, folks -------------------------------------------------*/