fc27aa70 |
1 | /* -*-c-*- |
2 | * |
73e1eaf2 |
3 | * $Id$ |
fc27aa70 |
4 | * |
5 | * Main header for XOR |
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 | |
fc27aa70 |
29 | #ifndef XOR_H |
30 | #define XOR_H |
31 | |
32 | #ifdef __cplusplus |
33 | extern "C" { |
34 | #endif |
35 | |
36 | /*----- Header files ------------------------------------------------------*/ |
37 | |
38 | #include "config.h" |
39 | |
40 | #include <ctype.h> |
41 | #include <limits.h> |
42 | #include <stdio.h> |
43 | #include <string.h> |
44 | |
45 | #include <unistd.h> |
46 | |
47 | #include <mLib/alloc.h> |
48 | #include <mLib/darray.h> |
49 | #include <mLib/dstr.h> |
50 | #include <mLib/str.h> |
51 | #include <mLib/sub.h> |
52 | |
53 | /*----- Data structures ---------------------------------------------------*/ |
54 | |
55 | typedef struct level { |
56 | int w, h; /* Width and height, in cells */ |
57 | char *name; /* Level name */ |
58 | unsigned f; /* Various flags */ |
59 | int m, mtot; /* Masks collected, and total */ |
60 | int v, vtot; /* Moves made, and allowed */ |
61 | int *d; /* Level data, row-major order */ |
62 | } level; |
63 | |
64 | #define LF_NWMAP 1u /* North-west map collected */ |
65 | #define LF_NEMAP 2u /* North-east map collected */ |
66 | #define LF_SWMAP 4u /* South-west map collected */ |
67 | #define LF_SEMAP 8u /* South-east map collected */ |
68 | #define LF_DARK 16u /* Someone turned the lights out */ |
69 | |
70 | #define LF_MAP "1234D" /* Map bits to characters */ |
71 | |
72 | /* --- Cells and their meanings --- */ |
73 | |
74 | #define C_PLAYER '$' /* Active player */ |
75 | #define C_SPARE '%' /* Inactive player */ |
76 | #define C_WALL '#' /* Solid wall */ |
77 | #define C_EXIT '*' /* Exit door */ |
78 | #define C_EMPTY ' ' /* Empty space */ |
79 | #define C_MASK '+' /* Mask */ |
80 | #define C_NWMAP '1' /* North-west map segment */ |
81 | #define C_NEMAP '2' /* North-east map segment */ |
82 | #define C_SWMAP '3' /* South-west map segment */ |
83 | #define C_SEMAP '4' /* South-east map segment */ |
84 | #define C_UKMAP 'M' /* Unknown map segment */ |
85 | #define C_DOT '-' /* Dots -- horizontal force-field */ |
86 | #define C_WAVE '|' /* Waves -- vertical force-field */ |
87 | #define C_CHICKEN '<' /* Chicken -- moves left */ |
88 | #define C_FISH 'V' /* Fish -- moves downwards */ |
89 | #define C_HBOMB 'C' /* H-bomb -- moves like chicken */ |
90 | #define C_VBOMB 'U' /* V-bomb -- moves like fish */ |
91 | #define C_DOLLY '@' /* Dolly -- slides about */ |
92 | #define C_SWITCH '~' /* Light-switch mask */ |
93 | #define C_BMUS 'O' /* Teleport pad */ |
94 | |
95 | /* --- Celll flags --- */ |
96 | |
97 | #define CF_CELLMASK 255u /* Mask for cell type */ |
98 | #define CF_INFLIGHT 256u /* Object is currently moving */ |
99 | #define CF_DOLLYUP 0u /* Dolly moving up */ |
100 | #define CF_DOLLYDOWN 512u /* Dolly moving down */ |
101 | #define CF_DOLLYLEFT 1024u /* Dolly moving left */ |
102 | #define CF_DOLLYRIGHT 1536u /* Dolly moving right */ |
103 | #define CF_DOLLYMASK 1536u /* Mask for dolly movement */ |
104 | |
105 | /* --- Macros for accessing the map data --- */ |
106 | |
107 | #define CELLREF(l, x, y) \ |
108 | ((l)->d[(x) + (y) * (l)->w]) |
109 | |
110 | #define CELLOK(l, x, y) \ |
111 | ((x) >= 0 && (x) < (l)->w && (y) >= 0 && (y) < (l)->h) |
112 | |
113 | #define CELLSET(l, x, y, c) \ |
114 | (CELLOK((l), (x), (y)) ? \ |
115 | CELLREF((l), (x), (y)) = (c), (void)0 : \ |
116 | (void)0) |
117 | |
118 | #define CELL(l, x, y) \ |
119 | (CELLOK((l), (x), (y)) ? \ |
120 | CELLREF((l), (x), (y)) : \ |
121 | C_WALL) |
122 | |
123 | #define CELLSETFL(l, x, y, f) \ |
124 | (CELLOK((l), (x), (y)) ? \ |
125 | CELLREF((l), (x), (y)) |= (f), (void)0 : \ |
126 | (void)0) |
127 | |
128 | #define CELLCLRFL(l, x, y, f) \ |
129 | (CELLOK((l), (x), (y)) ? \ |
130 | CELLREF((l), (x), (y)) &= ~(f), (void)0 : \ |
131 | (void)0) |
132 | |
133 | /* --- UI information --- * |
134 | * |
135 | * This is private to the UI layer. |
136 | */ |
137 | |
138 | typedef struct ui_state ui_state; |
139 | |
140 | /* --- Player structure --- */ |
141 | |
142 | typedef struct game_player { |
143 | struct game_player *next, *prev; /* Link in list (forward only) */ |
144 | int x, y; /* Current position */ |
145 | unsigned f; /* Flags */ |
146 | ui_state *u; /* User interface state */ |
147 | } game_player; |
148 | |
149 | #define PF_DEAD 1u /* Player has been killed */ |
150 | |
151 | /* --- Undo structures --- */ |
152 | |
153 | typedef struct undo_action { |
154 | struct undo_action *next; /* Next action in chian */ |
155 | int type; /* What kind of thing happened */ |
156 | union { |
157 | struct { int x, y, c; } c; /* Cell change */ |
158 | game_player *p; /* Player */ |
159 | unsigned f; /* Flags to restore */ |
160 | int n; /* Counter to restore */ |
161 | } u; |
162 | } undo_action; |
163 | |
164 | enum { |
165 | A_CELL, /* Cell changed contents */ |
166 | A_DIE, /* Player died */ |
167 | A_LIVE, /* Player became alive */ |
168 | A_LEVEL, /* Level flags changed */ |
169 | A_MASK, /* Mask count changed */ |
170 | A_MOVE, /* Player moved */ |
171 | A_SWITCH, /* Switch to other player */ |
172 | A_END |
173 | }; |
174 | |
175 | typedef struct undo_move { |
176 | struct undo_move *next; |
177 | undo_action *act; |
178 | } undo_move; |
179 | |
180 | /* --- Game state --- */ |
181 | |
182 | typedef struct game_state { |
183 | struct level *l; /* Level information */ |
184 | game_player *p, *ptail; /* Player list */ |
185 | unsigned f; /* Various flags */ |
186 | undo_move *u, *r, *m; /* Undo, redo and current lists */ |
187 | } game_state; |
188 | |
189 | #define GF_QUIT 1u |
190 | #define GF_WIN 2u |
191 | |
192 | /* --- The cell attributes table --- */ |
193 | |
194 | typedef struct cellinfo { |
195 | int c; /* Cell type */ |
196 | unsigned f; /* Various flags */ |
197 | |
198 | void (*hit)(game_state *, int /*x*/, int /*y*/, int /*hx*/, int /*hy*/); |
199 | /* Object at @(x, y)@ has been struck by another object (e.g., a chicken) |
200 | which is now at @(hx, hy)@. */ |
201 | |
202 | int (*nudge)(game_state *, int /*x*/, int /*y*/, int /*dx*/, int /*dy*/); |
203 | /* Object is being nudged by player in given direction. Answer @0@ if |
204 | nothing happens (and the player cannot enter), @1@ if it's OK and the |
205 | space is vacated, or @-1@ if something strange happened. */ |
206 | |
207 | int (*moveh)(game_state *, int /*x*/, int /*y*/); |
208 | int (*movev)(game_state *, int /*x*/, int /*y*/); |
209 | /* See if object can move on its own horizontally or vertically. Return |
210 | * zero if it won't move, or nonzero otherwise. */ |
211 | } cellinfo; |
212 | |
213 | #define CF_HIDE 1u /* Invisible in the dark */ |
214 | #define CF_MASK 2u /* Must collect these */ |
215 | #define CF_HPASS 4u /* Object is passable horizontally */ |
216 | #define CF_VPASS 8u /* Object is passable vertically */ |
217 | #define CF_PLAYER 16u /* Object is a player */ |
218 | #define CF_MAP 32u /* Object shows up on map */ |
219 | |
220 | /* --- Other structures --- */ |
221 | |
222 | typedef struct point { int x, y; } point; |
223 | |
224 | /*----- Global variables --------------------------------------------------*/ |
225 | |
226 | extern const cellinfo *cellmap[]; |
227 | |
228 | /*----- Cell attributes ---------------------------------------------------*/ |
229 | |
230 | extern void cellinfo_init(void); |
231 | |
232 | /*----- Level management --------------------------------------------------*/ |
233 | |
234 | extern int lev_findnext(const level */*l*/, int /*c*/, |
235 | int */*x*/, int */*y*/); |
236 | extern int lev_findcell(const level */*l*/, int /*c*/, |
237 | int */*x*/, int */*y*/); |
238 | extern level *lev_read(FILE */*fp*/); |
239 | extern void lev_write(const level */*l*/, FILE */*fp*/); |
240 | extern void lev_free(level */*l*/); |
241 | extern level *lev_copy(const level */*l*/); |
242 | |
243 | /*----- User interface ----------------------------------------------------*/ |
244 | |
245 | extern void ui_frame(ui_state */*u*/); |
246 | extern void ui_message(ui_state */*u*/, const char */*p*/); |
247 | extern void ui_explode(ui_state */*u*/, const point */*pt*/, int /*n*/); |
248 | extern void ui_track(ui_state */*u*/, int /*x*/, int /*y*/); |
249 | extern void ui_update(ui_state */*u*/); |
250 | extern void ui_switch(ui_state */*u*/); |
251 | extern void ui_init(void); |
252 | extern void ui_update(ui_state */*u*/); |
253 | extern ui_state *ui_start(level */*l*/, int /*x*/, int /*y*/); |
254 | extern void ui_go(game_state */*g*/, ui_state */*u*/); |
255 | extern void ui_destroy(ui_state */*u*/); |
256 | extern void ui_exit(void); |
257 | |
258 | /*----- Undo management ---------------------------------------------------*/ |
259 | |
260 | extern void undo_init(game_state */*g*/); |
261 | extern void undo_begin(game_state */*g*/); |
262 | extern void undo_cell(game_state */*g*/, int /*x*/, int /*y*/, int /*c*/); |
263 | extern void undo_die(game_state */*g*/, game_player */*p*/); |
264 | extern void undo_pmove(game_state */*g*/); |
265 | extern void undo_levelf(game_state */*g*/); |
266 | extern void undo_mask(game_state */*g*/); |
267 | extern void undo_switch(game_state */*g*/); |
268 | extern void undo_commit(game_state */*g*/); |
269 | extern void undo(game_state */*g*/); |
270 | extern void redo(game_state */*g*/); |
271 | extern void undo_free(game_state */*g*/); |
272 | |
273 | /*----- Game engine -------------------------------------------------------*/ |
274 | |
275 | extern void game_explode(game_state */*g*/, const point */*pt*/, int /*n*/); |
276 | extern void game_die(game_state */*g*/, int /*x*/, int /*y*/); |
277 | extern void game_moveobj(game_state */*g*/, int /*x*/, int /*y*/, |
278 | int /*xx*/, int /*yy*/); |
279 | extern void game_switchto(game_state *g, game_player */*p*/); |
280 | extern int game_switch(game_state */*g*/); |
281 | extern void game_move(game_state */*g*/, int /*dx*/, int /*dy*/); |
282 | extern void game_go(level */*l*/); |
283 | extern void game_quit(game_state */*g*/); |
284 | |
285 | /*----- That's all, folks -------------------------------------------------*/ |
286 | |
287 | #ifdef __cplusplus |
288 | } |
289 | #endif |
290 | |
291 | #endif |