7 * (c) 2003 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of XOR.
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.
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.
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.
36 /*----- Header files ------------------------------------------------------*/
47 #include <mLib/alloc.h>
48 #include <mLib/darray.h>
49 #include <mLib/dstr.h>
53 /*----- Data structures ---------------------------------------------------*/
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 */
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 */
70 #define LF_MAP "1234D" /* Map bits to characters */
72 /* --- Cells and their meanings --- */
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 */
95 /* --- Celll flags --- */
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 */
105 /* --- Macros for accessing the map data --- */
107 #define CELLREF(l, x, y) \
108 ((l)->d[(x) + (y) * (l)->w])
110 #define CELLOK(l, x, y) \
111 ((x) >= 0 && (x) < (l)->w && (y) >= 0 && (y) < (l)->h)
113 #define CELLSET(l, x, y, c) \
114 (CELLOK((l), (x), (y)) ? \
115 CELLREF((l), (x), (y)) = (c), (void)0 : \
118 #define CELL(l, x, y) \
119 (CELLOK((l), (x), (y)) ? \
120 CELLREF((l), (x), (y)) : \
123 #define CELLSETFL(l, x, y, f) \
124 (CELLOK((l), (x), (y)) ? \
125 CELLREF((l), (x), (y)) |= (f), (void)0 : \
128 #define CELLCLRFL(l, x, y, f) \
129 (CELLOK((l), (x), (y)) ? \
130 CELLREF((l), (x), (y)) &= ~(f), (void)0 : \
133 /* --- UI information --- *
135 * This is private to the UI layer.
138 typedef struct ui_state ui_state
;
140 /* --- Player structure --- */
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 */
149 #define PF_DEAD 1u /* Player has been killed */
151 /* --- Undo structures --- */
153 typedef struct undo_action
{
154 struct undo_action
*next
; /* Next action in chian */
155 int type
; /* What kind of thing happened */
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 */
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 */
175 typedef struct undo_move
{
176 struct undo_move
*next
;
180 /* --- Game state --- */
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 */
192 /* --- The cell attributes table --- */
194 typedef struct cellinfo
{
195 int c
; /* Cell type */
196 unsigned f
; /* Various flags */
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)@. */
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. */
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. */
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 */
220 /* --- Other structures --- */
222 typedef struct point
{ int x
, y
; } point
;
224 /*----- Global variables --------------------------------------------------*/
226 extern const cellinfo
*cellmap
[];
228 /*----- Cell attributes ---------------------------------------------------*/
230 extern void cellinfo_init(void);
232 /*----- Level management --------------------------------------------------*/
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*/
);
243 /*----- User interface ----------------------------------------------------*/
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);
258 /*----- Undo management ---------------------------------------------------*/
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*/
);
273 /*----- Game engine -------------------------------------------------------*/
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*/
);
285 /*----- That's all, folks -------------------------------------------------*/