20080916
[gdash.git] / src / cave.h
blob84c37249358609fe97da5cb1a5b6573e4a8c28cc
1 /*
2 * Copyright (c) 2007, 2008 Czirkos Zoltan <cirix@fw.hu>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 #ifndef _GD_CAVE_H
17 #define _GD_CAVE_H
19 #include <glib.h>
21 /* these define the number of the cells in the png file */
22 #define NUM_OF_CELLS_X 8
23 #define NUM_OF_CELLS_Y 36
24 /* +64: placeholder for cells which are rendered by the game; for example diamond+arrow = falling diamond */
25 #define NUM_OF_CELLS (NUM_OF_CELLS_X*NUM_OF_CELLS_Y+64)
28 typedef guint32 GdColor;
30 typedef struct _c64_colors {
31 const char *name;
32 const GdColor rgb;
33 guint32 p;
34 } GDC64Color;
35 extern GDC64Color gd_c64_colors[16];
37 #define GD_C64_BLACK (gd_c64_colors[0].rgb)
38 #define GD_C64_WHITE (gd_c64_colors[1].rgb)
39 #define GD_C64_RED (gd_c64_colors[2].rgb)
40 #define GD_C64_PURPLE (gd_c64_colors[4].rgb)
41 #define GD_C64_CYAN (gd_c64_colors[3].rgb)
42 #define GD_C64_GREEN (gd_c64_colors[5].rgb)
43 #define GD_C64_BLUE (gd_c64_colors[6].rgb)
44 #define GD_C64_YELLOW (gd_c64_colors[7].rgb)
45 #define GD_C64_ORANGE (gd_c64_colors[8].rgb)
46 #define GD_C64_BROWN (gd_c64_colors[9].rgb)
47 #define GD_C64_LIGHTRED (gd_c64_colors[10].rgb)
48 #define GD_C64_GRAY1 (gd_c64_colors[11].rgb)
49 #define GD_C64_GRAY2 (gd_c64_colors[12].rgb)
50 #define GD_C64_LIGHTGREEN (gd_c64_colors[13].rgb)
51 #define GD_C64_LIGHTBLUE (gd_c64_colors[14].rgb)
52 #define GD_C64_GRAY3 (gd_c64_colors[15].rgb)
56 /* These are the objects in caves. */
57 typedef enum _element {
58 O_SPACE,
59 O_DIRT,
60 O_DIRT_SLOPED_UP_RIGHT,
61 O_DIRT_SLOPED_UP_LEFT,
62 O_DIRT_SLOPED_DOWN_LEFT,
63 O_DIRT_SLOPED_DOWN_RIGHT,
64 O_DIRT2,
65 O_BRICK,
66 O_BRICK_SLOPED_UP_RIGHT,
67 O_BRICK_SLOPED_UP_LEFT,
68 O_BRICK_SLOPED_DOWN_LEFT,
69 O_BRICK_SLOPED_DOWN_RIGHT,
70 O_MAGIC_WALL,
71 O_PRE_OUTBOX,
72 O_OUTBOX,
73 O_PRE_INVIS_OUTBOX,
74 O_INVIS_OUTBOX,
75 O_STEEL,
76 O_STEEL_SLOPED_UP_RIGHT,
77 O_STEEL_SLOPED_UP_LEFT,
78 O_STEEL_SLOPED_DOWN_LEFT,
79 O_STEEL_SLOPED_DOWN_RIGHT,
80 O_STEEL_EXPLODABLE,
81 O_STEEL_EATABLE,
82 O_BRICK_EATABLE,
83 O_STONE,
84 O_STONE_F,
85 O_MEGA_STONE,
86 O_MEGA_STONE_F,
87 O_DIAMOND,
88 O_DIAMOND_F,
89 O_BLADDER_SPENDER,
90 O_INBOX,
91 O_H_GROWING_WALL,
92 O_V_GROWING_WALL,
93 O_GROWING_WALL,
94 O_GROWING_WALL_SWITCH,
95 O_CREATURE_SWITCH,
96 O_BITER_SWITCH,
97 O_ACID,
98 O_FALLING_WALL,
99 O_FALLING_WALL_F,
100 O_BOX,
101 O_TIME_PENALTY,
102 O_GRAVESTONE,
103 O_STONE_GLUED,
104 O_DIAMOND_GLUED,
105 O_DIAMOND_KEY,
106 O_TRAPPED_DIAMOND,
107 O_CLOCK,
108 O_DIRT_GLUED,
109 O_KEY_1,
110 O_KEY_2,
111 O_KEY_3,
112 O_DOOR_1,
113 O_DOOR_2,
114 O_DOOR_3,
116 O_POT,
117 O_GRAVITY_SWITCH,
118 O_PNEUMATIC_HAMMER,
119 O_TELEPORTER,
120 O_SKELETON,
121 O_WATER,
122 O_WATER_1,
123 O_WATER_2,
124 O_WATER_3,
125 O_WATER_4,
126 O_WATER_5,
127 O_WATER_6,
128 O_WATER_7,
129 O_WATER_8,
130 O_WATER_9,
131 O_WATER_10,
132 O_WATER_11,
133 O_WATER_12,
134 O_WATER_13,
135 O_WATER_14,
136 O_WATER_15,
137 O_WATER_16,
138 O_COW_1,
139 O_COW_2,
140 O_COW_3,
141 O_COW_4,
142 O_COW_ENCLOSED_1,
143 O_COW_ENCLOSED_2,
144 O_COW_ENCLOSED_3,
145 O_COW_ENCLOSED_4,
146 O_COW_ENCLOSED_5,
147 O_COW_ENCLOSED_6,
148 O_COW_ENCLOSED_7,
149 O_WALLED_DIAMOND,
150 O_WALLED_KEY_1,
151 O_WALLED_KEY_2,
152 O_WALLED_KEY_3,
154 O_AMOEBA,
155 O_SWEET,
156 O_VOODOO,
157 O_SLIME,
158 O_BLADDER,
159 O_BLADDER_1,
160 O_BLADDER_2,
161 O_BLADDER_3,
162 O_BLADDER_4,
163 O_BLADDER_5,
164 O_BLADDER_6,
165 O_BLADDER_7,
166 O_BLADDER_8,
167 O_BLADDER_9,
169 O_WAITING_STONE,
170 O_CHASING_STONE,
171 O_GHOST,
172 O_GUARD_1,
173 O_GUARD_2,
174 O_GUARD_3,
175 O_GUARD_4,
176 O_ALT_GUARD_1,
177 O_ALT_GUARD_2,
178 O_ALT_GUARD_3,
179 O_ALT_GUARD_4,
180 O_BUTTER_1,
181 O_BUTTER_2,
182 O_BUTTER_3,
183 O_BUTTER_4,
184 O_ALT_BUTTER_1,
185 O_ALT_BUTTER_2,
186 O_ALT_BUTTER_3,
187 O_ALT_BUTTER_4,
188 O_STONEFLY_1,
189 O_STONEFLY_2,
190 O_STONEFLY_3,
191 O_STONEFLY_4,
192 O_BITER_1,
193 O_BITER_2,
194 O_BITER_3,
195 O_BITER_4,
197 O_PRE_PL_1,
198 O_PRE_PL_2,
199 O_PRE_PL_3,
200 O_PLAYER,
201 O_PLAYER_BOMB,
202 O_PLAYER_GLUED,
203 O_PLAYER_STIRRING,
205 O_BOMB,
206 O_BOMB_TICK_1,
207 O_BOMB_TICK_2,
208 O_BOMB_TICK_3,
209 O_BOMB_TICK_4,
210 O_BOMB_TICK_5,
211 O_BOMB_TICK_6,
212 O_BOMB_TICK_7,
214 O_PRE_CLOCK_1,
215 O_PRE_CLOCK_2,
216 O_PRE_CLOCK_3,
217 O_PRE_CLOCK_4,
218 O_PRE_DIA_1,
219 O_PRE_DIA_2,
220 O_PRE_DIA_3,
221 O_PRE_DIA_4,
222 O_PRE_DIA_5,
223 O_EXPLODE_1,
224 O_EXPLODE_2,
225 O_EXPLODE_3,
226 O_EXPLODE_4,
227 O_EXPLODE_5,
228 O_PRE_STONE_1,
229 O_PRE_STONE_2,
230 O_PRE_STONE_3,
231 O_PRE_STONE_4,
232 O_PRE_STEEL_1,
233 O_PRE_STEEL_2,
234 O_PRE_STEEL_3,
235 O_PRE_STEEL_4,
236 O_GHOST_EXPL_1,
237 O_GHOST_EXPL_2,
238 O_GHOST_EXPL_3,
239 O_GHOST_EXPL_4,
240 O_BOMB_EXPL_1,
241 O_BOMB_EXPL_2,
242 O_BOMB_EXPL_3,
243 O_BOMB_EXPL_4,
245 /* these are used internally for the pneumatic hammer, and should not be used in the editor! */
246 /* (not even as an effect destination or something like that) */
247 O_PLAYER_PNEUMATIC_LEFT,
248 O_PLAYER_PNEUMATIC_RIGHT,
249 O_PNEUMATIC_ACTIVE_LEFT,
250 O_PNEUMATIC_ACTIVE_RIGHT,
252 O_UNKNOWN, /* unknown element imported or read from bdcff */
253 O_NONE, /* do not draw this element when creating cave; can be used, for example, to skip drawing a maze's path */
255 /* remembering last index */
256 /* this should get an integer value which is 1 more than the one above. */
257 O_MAX,
259 /* fake elements to help drawing */
260 O_FAKE_BONUS,
261 O_OUTBOX_CLOSED,
262 O_OUTBOX_OPEN,
263 O_COVERED,
264 O_PLAYER_LEFT,
265 O_PLAYER_RIGHT,
266 O_PLAYER_TAP,
267 O_PLAYER_BLINK,
268 O_PLAYER_TAP_BLINK,
269 O_CREATURE_SWITCH_ON,
270 O_GROWING_WALL_SWITCH_HORIZ,
271 O_GROWING_WALL_SWITCH_VERT,
272 O_GRAVITY_SWITCH_ACTIVE,
274 O_DOWN_ARROW,
275 O_LEFTRIGHT_ARROW,
276 O_EVERYDIR_ARROW,
277 O_GLUED,
278 O_OUT,
279 O_EXCLAMATION_MARK,
281 SCANNED=0x100,
282 COVERED=0x200,
284 /* binary AND this to elements to get rid of properties above. */
285 O_MASK = ~(SCANNED | COVERED)
286 } GdElement;
288 extern GdElement gd_char_to_element[];
290 typedef enum _element_property {
291 /* properties */
292 P_SLOPED_LEFT = 1 << 0, /**< stones and diamonds roll down to left on this */
293 P_SLOPED_RIGHT = 1 << 1, /**< stones and diamonds roll down to right on this */
294 P_SLOPED_UP = 1 << 2,
295 P_SLOPED_DOWN = 1 << 3,
296 P_SLOPED = P_SLOPED_LEFT|P_SLOPED_RIGHT|P_SLOPED_UP|P_SLOPED_DOWN, /**< stones and diamonds roll down on this in any direction */
298 P_AMOEBA_CONSUMES = 1 << 4, /**< amoeba can eat this */
299 P_DIRT = 1 << 5, /* it is dirt, or something similar (dirt2 or sloped dirt) */
300 P_BLOWS_UP_FLIES = 1 << 6, /**< flies blow up, if they touch this */
302 P_EXPLODES_TO_SPACE = 1 << 7, /**< explodes if hit by a rock */
303 P_EXPLODES_TO_DIAMONDS = 1 << 8,/**< explodes to diamonds if hit by a rock */
304 P_EXPLODES_TO_STONES = 1 << 9, /**< explodes to rocks if hit by a rock */
305 P_EXPLODES=P_EXPLODES_TO_SPACE|P_EXPLODES_TO_DIAMONDS|P_EXPLODES_TO_STONES, /* explodes to something if hit */
307 P_NON_EXPLODABLE = 1 << 10, /**< selfexplaining */
308 P_CCW = 1 << 11, /**< this creature has a default counterclockwise rotation (for example, o_fire_1) */
309 P_CAN_BE_HAMMERED = 1 << 12, /**< can be broken by pneumatic hammer */
310 P_VISUAL_EFFECT = 1 << 13,
311 } GdElementProperties;
313 /** These are states of the magic wall. */
314 typedef enum magic_wall_state {
315 MW_DORMANT, /* Starting with this. */
316 MW_ACTIVE, /* Boulder or diamond dropped into. */
317 MW_EXPIRED /* Turned off after magic_wall_milling_time. */
318 } MAGIC_WALL_STATE;
320 /** These are states of Player. */
321 typedef enum player_state {
322 PL_NOT_YET, /* Not yet living. Beginning of cave time. */
323 PL_LIVING, /* Ok. */
324 PL_TIMEOUT, /* Time is up */
325 PL_DIED, /* Died. */
326 PL_EXITED /* Exited the cave, proceed to next one */
327 } PLAYER_STATE;
329 typedef enum _direction {
330 /* not moving */
331 MV_STILL=0,
332 MV_THIS=0,
334 /* directions */
335 MV_UP=1,
336 MV_UP_RIGHT=2,
337 MV_RIGHT=3,
338 MV_DOWN_RIGHT=4,
339 MV_DOWN=5,
340 MV_DOWN_LEFT=6,
341 MV_LEFT=7,
342 MV_UP_LEFT=8,
344 /* to be able to type MV_TWICE+MV_DOWN, for example */
345 MV_TWICE=8,
347 /* directions * 2 */
348 MV_UP_2=9,
349 MV_UP_RIGHT_2=10,
350 MV_RIGHT_2=11,
351 MV_DOWN_RIGHT_2=12,
352 MV_DOWN_2=13,
353 MV_DOWN_LEFT_2=14,
354 MV_LEFT_2=15,
355 MV_UP_LEFT_2=16,
356 } GdDirection;
358 typedef enum _sound {
359 GD_S_NONE,
360 GD_S_DIAMOND_RANDOM, /* randomly select a diamond sound */
361 GD_S_AMOEBA, /* loop */
362 GD_S_MAGIC_WALL, /* loop */
363 GD_S_COVER, /* loop */
364 GD_S_PNEUMATIC_HAMMER, /* loop */
365 GD_S_WATER, /* loop */
366 GD_S_CRACK,
367 GD_S_GRAVITY_CHANGE,
368 GD_S_STONE,
369 GD_S_FALLING_WALL,
370 GD_S_GROWING_WALL,
371 GD_S_DOOR_OPEN,
372 GD_S_WALK_EARTH,
373 GD_S_WALK_EMPTY,
374 GD_S_STIRRING,
375 GD_S_DIAMOND_1,
376 GD_S_DIAMOND_2,
377 GD_S_DIAMOND_3,
378 GD_S_DIAMOND_4,
379 GD_S_DIAMOND_5,
380 GD_S_DIAMOND_6,
381 GD_S_DIAMOND_7,
382 GD_S_DIAMOND_8,
383 GD_S_DIAMOND_COLLECT,
384 GD_S_PNEUMATIC_COLLECT,
385 GD_S_BOMB_COLLECT,
386 GD_S_CLOCK_COLLECT,
387 GD_S_SWEET_COLLECT,
388 GD_S_KEY_COLLECT,
389 GD_S_SKELETON_COLLECT,
390 GD_S_SLIME,
391 GD_S_ACID_SPREAD,
392 GD_S_WATER_SPREAD,
393 GD_S_BLADDER_CONVERT,
394 GD_S_BLADDER_SPENDER,
395 GD_S_BOX_PUSH,
396 GD_S_TELEPORTER,
397 GD_S_TIMEOUT_1,
398 GD_S_TIMEOUT_2,
399 GD_S_TIMEOUT_3,
400 GD_S_TIMEOUT_4,
401 GD_S_TIMEOUT_5,
402 GD_S_TIMEOUT_6,
403 GD_S_TIMEOUT_7,
404 GD_S_TIMEOUT_8,
405 GD_S_TIMEOUT_9,
406 GD_S_EXPLOSION,
407 GD_S_BOMB_EXPLOSION,
408 GD_S_GHOST_EXPLOSION,
409 GD_S_VOODOO_EXPLOSION,
410 GD_S_BOMB_PLACE,
411 GD_S_FINISHED,
412 GD_S_SWITCH_BITER,
413 GD_S_SWITCH_CREATURES,
414 GD_S_SWITCH_GRAVITY,
415 GD_S_SWITCH_GROWING,
416 GD_S_BONUS_LIFE,
417 GD_S_MAX,
418 } GdSound;
422 /* ELEMENTS DESCRIPTION */
423 typedef struct _elements {
424 GdElement element; /* element number. for example O_DIRT */
425 char *name; /* name in editor, for example "Dirt". some have different names than their real engine meaning! */
426 unsigned int properties;/* engine properties, like P_ROUNDED or P_EXPLODES */
427 char *filename; /* name in bdcff file, like "DIRT" */
428 char character; /* character representation in bdcff file, like '.' */
429 int image; /* image in editor (index in cells.png) */
430 int image_simple; /* image for simple view in editor, and for combo box (index in cells.png) */
431 int image_game; /* image for game. negative if animated */
432 int ckdelay; /* ckdelay ratio - how much time required for a c64 to process this element - in microseconds. */
434 char *lowercase_name; /* lowercase of translated name. for editor; generated inside the game. */
435 char character_new; /* character given automatically for elements which don't have one defined in original bdcff description */
436 } GdElements;
437 extern GdElements gd_elements[];
439 typedef char GdString[128];
441 typedef struct _highscore {
442 GdString name;
443 int score;
444 } GdHighScore;
446 enum _gd_demo_bits {
447 GD_DEMO_MOVEMENT_SHIFT=0,
448 GD_DEMO_MOVEMENT_MASK=0x0f,
449 GD_DEMO_FIRE_SHIFT=4,
450 GD_DEMO_FIRE_MASK=0x10,
451 GD_DEMO_SUICIDE_SHIFT=5,
452 GD_DEMO_SUICIDE_MASK=0x20,
455 typedef struct _gd_cave_demo {
456 int level; /* demo for level n */
457 guint32 seed; /* seed the cave is to be rendered with */
458 guint8 movements[4096]; /* movements. lower 4 bits: direction, bit 5: fire, bit 6: suicide. delimited with 0xff. */
459 int movements_num; /* number of movements so far */
460 } GdCaveDemo;
462 typedef enum _gd_scheduling {
463 GD_SCHEDULING_MILLISECONDS,
464 GD_SCHEDULING_BD1,
465 GD_SCHEDULING_PLCK,
466 GD_SCHEDULING_CRDR,
467 GD_SCHEDULING_MAX
468 } GdScheduling;
471 Structure holding all data belonging to a cave.
473 #define GD_HIGHSCORE_NUM 20
474 typedef struct _cave {
475 /* Defined by the editor. public data :) */
476 GdString name; /* Name of cave */
477 GdString description; /* Some words about the cave */
478 GdString author; /* Author */
479 GdString difficulty; /* difficulty of the game, for info purposes */
480 GdString www; /* link to author's webpage */
481 GdString date; /* date of creation */
482 GdString remark; /* some note */
484 GdString charset; /* these are not used by gdash */
485 GdString fontset;
487 /* and this one the highscores */
488 GdHighScore highscore[GD_HIGHSCORE_NUM];
490 GHashTable *tags; /* stores read-but-not-understood strings from bdcff, so we can save them later. */
492 GdElement **map; /* pointer to data for map, non-null if has a map */
493 GList *objects;
495 gboolean intermission; /* is this cave an intermission? */
496 gboolean intermission_instantlife; /* one life extra, if the intermission is reached */
497 gboolean intermission_rewardlife; /* one life extra, if the intermission is successfully finished */
498 gboolean selectable; /* is this selectable as an initial cave for a game? */
499 gboolean diagonal_movements; /* are diagonal movements allowed? */
500 gboolean snap_explosions; /* if true, snapping will create explosions */
501 gboolean short_explosions; /* in >=1stb, diamond and creature explosions were of 5 stages */
503 GdScheduling scheduling; /* scheduling type; see above */
504 gboolean pal_timing; /* use faster seconds */
506 gboolean active_is_first_found; /* active player is the uppermost. */
507 gboolean lineshift; /* true is line shifting emulation, false is perfect borders emulation */
509 GdElement initial_fill;
510 GdElement initial_border;
511 GdElement random_fill[4]; /* Random fill elements. */
512 int random_fill_probability[4]; /* Random fill, probability of each element. */
514 int level_rand[5]; /* Random seed. */
515 int level_diamonds[5]; /* Must collect diamonds, on level x */
516 int level_speed[5]; /* Time between game cycles in ms */
517 int level_ckdelay[5]; /* Timing in original game units */
518 int level_time[5]; /* Available time, per level */
519 int level_timevalue[5]; /* points for each second remaining, when exiting level */
521 int w, h; /* Sizes of cave, width and height. */
522 int x1,y1,x2,y2; /* Visible part of the cave */
523 guint32 colorb; /* border color */
524 guint32 color0, color1, color2, color3, color4, color5; /* c64-style colors; 4 and 5 are amoeba and slime. */
526 int diamond_value; /* Score for a diamond. */
527 int extra_diamond_value; /* Score for a diamond, when gate is open. */
529 int magic_wall_milling_time; /* magic wall 'on' state for seconds */
530 gboolean magic_wall_stops_amoeba; /* Turning on magic wall changes amoeba to diamonds. Original BD: yes, constkit: no */
531 gboolean magic_timer_wait_for_hatching; /* magic wall timer does not start before player's birth */
532 gboolean magic_wall_sound; /* magic wall has sound */
534 int amoeba_slow_growth_time; /* Amoeba growing slow (low probability, default 3%) for seconds. After that, fast growth default (25%) */
535 double amoeba_growth_prob; /* Amoeba slow growth probability */
536 double amoeba_fast_growth_prob; /* Amoeba fast growth probability */
537 int amoeba_threshold; /* amoeba to stones ratio */
538 gboolean amoeba_timer_started_immediately; /* FALSE: amoeba will start life at the first possibility of growing. */
539 gboolean amoeba_timer_wait_for_hatching; /* amoeba timer does not start before player's birth */
541 GdElement acid_eats_this; /* acid eats this element */
542 double acid_spread_ratio; /* Probability of acid blowing up, each frame */
543 gboolean acid_spread_sound; /* acid has sound */
544 GdElement acid_turns_to; /* whether acid converts to explosion on spreading or other */
546 double slime_permeability; /* true random slime */
547 int slime_permeability_c64; /* Appearing in bd 2 */
548 gboolean slime_predictable; /* predictable random start for slime. yes for plck. */
549 GdElement slime_eats_1, slime_converts_1; /* slime eats element x and converts to element x; for example diamond -> falling diamond */
550 GdElement slime_eats_2, slime_converts_2;
551 gboolean slime_sound; /* slime has sound */
553 int bonus_time; /* bonus time for clock collected. */
554 int hatching_delay_frame; /* Scan frames before Player's birth. */
555 int hatching_delay_time; /* Scan frames before Player's birth. */
557 int penalty_time; /* Time penalty when voodoo destroyed. */
558 gboolean voodoo_collects_diamonds; /* Voodoo can collect diamonds */
559 gboolean voodoo_dies_by_stone; /* Voodoo can be killed by a falling stone */
560 gboolean voodoo_can_be_destroyed; /* Voodoo can be destroyed by and explosion */
562 gboolean water_does_not_flow_down; /* if true, water will not grow downwards, only in other directions. */
563 gboolean water_sound; /* water has sound */
565 /* effects */
566 GdElement explosion_to; /* explosion converts to this element */
567 GdElement diamond_birth_to; /* a diamond birth converts to this element */
568 GdElement falling_stone_to; /* a falling stone converts to this element */
569 GdElement falling_diamond_to; /* a falling diamond converts to this element */
570 GdElement bouncing_stone_to; /* a bouncing stone converts to this element */
571 GdElement bouncing_diamond_to; /* a bouncing diamond converts to this element */
572 GdElement enclosed_amoeba_to; /* an enclosed amoeba converts to this element */
573 GdElement too_big_amoeba_to; /* an amoeba grown too big converts to this element */
575 GdElement expanding_wall_looks_like; /* an expanding wall looks like this element */
576 GdElement dirt_looks_like; /* dirt looks like this element */
578 GdElement magic_stone_to; /* magic wall converts falling stone to */
579 GdElement magic_diamond_to; /* magic wall converts falling diamond to */
581 GdElement bladder_converts_by; /* bladder converts to clock by touching this element */
582 GdElement bomb_explode_to; /* bombs explode to this element */
584 double pushing_stone_prob; /* probability of pushing boulder, normally 0.25 */
585 double pushing_stone_prob_sweet; /* probability of pushing, after eating sweet, normally 1.0 */
587 gboolean creatures_backwards; /* creatures changed direction */
588 gboolean creatures_direction_auto_change_on_start; /* the change occurs also at the start signal */
589 int creatures_direction_auto_change_time; /* creatures automatically change direction every x seconds */
591 int skeletons_needed_for_pot; /* how many skeletons to be collected, to use a pot */
592 int skeletons_worth_diamonds; /* for crazy dream 7 compatibility: collecting skeletons might open the cave door. */
594 GdDirection gravity;
595 int gravity_change_time;
596 gboolean gravity_affects_all; /* if true, gravity also affects falling wall, bladder and waiting stones */
598 int biter_delay_frame; /* frame count biters do move */
599 GdElement biter_eat; /* biters eat this */
601 gboolean hammered_walls_reappear;
602 int pneumatic_hammer_frame;
603 int hammered_wall_reappear_frame;
605 /* internal variables, used during the game. private data :) */
606 gboolean hatched; /* hatching has happened. (timers may run, ...) */
607 gboolean gate_open; /* self-explaining */
608 guint32 render_seed; /* the seed value, which was used to render the cave, is saved here. will be used by record&playback */
609 GRand *random; /* random number generator of rendered cave */
610 int rendered; /* if not null, rendered at level x */
611 int timing_factor; /* number of "milliseconds" in each second :) 1000 for ntsc, 1200 for pal. */
612 gpointer **objects_order; /* two-dimensional map of cave; each cell is a pointer to the drawing object, which created this element. NULL if map or random. */
613 int **hammered_reappear; /* integer map of cave; if non-zero, a brick wall will appear there */
614 int speed; /* Time between game cycles in ms */
615 int c64_timing; /* a ckdelay value for the level this cave is rendered for */
616 int ckdelay; /* ckdelay value for the current iteration */
617 int ckdelay_extra_for_animation; /* bd1 and similar engines had animation bits in cave data, to set which elements to animate (firefly, butterfly, amoeba).
618 animating an element also caused some delay each frame; according to my measurements, around 2.6 ms/element. */
619 int time; /* seconds remaining to finish cave */
620 int timevalue; /* points for remaining seconds */
621 int diamonds_needed; /* diamonds needed to open outbox */
622 int diamonds_collected; /* diamonds collected */
623 int gate_open_flash; /* flashing of screen when gate opens */
624 int score; /* Score got this frame. */
625 gboolean amoeba_too_big; /* Too much amoeba found, and amoeba will convert into stones next frame. */
626 gboolean amoeba_enclosed; /* Amoeba closed, so will convert into diamonds next frame */
627 MAGIC_WALL_STATE magic_wall_state; /* State of magic wall */
628 PLAYER_STATE player_state; /* Player state. not yet living, living, exited... */
629 int player_seen_ago; /* player was seen this number of scans ago */
630 gboolean kill_player; /* Voodoo died, or used pressed escape to restart level. */
631 gboolean amoeba_started; /* amoeba started. */
632 gboolean sweet_eaten; /* player ate sweet, he's strong. prob_sweet applies, and also able to push chasing stones */
633 int player_x, player_y; /* Coordinates of player (for scrolling) */
634 int px[16], py[16]; /* coordinates of player, for chasing stone */
635 gboolean diamond_key_collected; /* Key collected, so trapped diamonds convert to diamonds */
636 int key1, key2, key3; /* The player is holding this number of keys of each color */
637 gboolean expanding_wall_changed; /* growing wall direction is changed */
638 int time_decrement; /* time to subtract after destroying voodoo (time penalties converting to gravestones) */
639 int skeletons_collected; /* number of skeletons collected */
641 gboolean inbox_flash_toggle; /* negated every scan. helps drawing inboxes, and making players be born at different times. */
642 GdDirection last_direction; /* last direction player moved. used by draw routines */
643 GdDirection last_horizontal_direction;
644 int biters_wait_frame; /* number of frames to wait until biteres will move again */
645 int creatures_direction_will_change; /* creatures automatically change direction every x seconds */
646 unsigned int rand_seed_1, rand_seed_2; /* used for predictable random generator during the game. */
647 GdElement* (*getp) (const struct _cave*, int x, int y); /* returns a pointer to the element at x, y. this points to a perfect border or a line shifting get function. */
648 gboolean gravity_switch_active; /* true if gravity switch is activated, and can be used. */
649 int gravity_will_change; /* gravity will change in this number of seconds */
650 gboolean gravity_disabled; /* when the player is stirring the pot, there is no gravity. */
651 GdDirection gravity_next_direction; /* next direction when the gravity changes. will be set by the player "getting" a gravity switch */
652 gboolean got_pneumatic_hammer; /* true if the player has a pneumatic hammer */
653 int pneumatic_hammer_active_delay; /* number of frames to wait, till pneumatic hammer will destroy the wall */
654 GdSound sound1, sound2, sound3; /* sound set for 3 channels after each iteration */
655 } Cave;
660 /* CAVE DESCRIPTION */
661 typedef enum _gd_type {
662 /* not real types, only used by editor to build ui */
663 GD_TAB,
664 GD_LABEL,
665 GD_LEVEL_LABEL,
667 /* gd types */
668 GD_TYPE_STRING,
669 GD_TYPE_INT,
670 GD_TYPE_RATIO,
671 GD_TYPE_ELEMENT,
672 GD_TYPE_BOOLEAN,
673 GD_TYPE_PROBABILITY,
674 GD_TYPE_COLOR,
675 GD_TYPE_EFFECT,
676 GD_TYPE_DIRECTION,
677 GD_TYPE_SCHEDULING,
678 } GdType;
680 enum _gd_property_flags {
681 GD_FOR_CAVESET=1<<0,
682 GD_ALWAYS_SAVE=1<<1,
683 GD_DONT_SAVE=1<<2,
684 GD_DONT_SHOW_IN_EDITOR=1<<3,
687 typedef struct {
688 char *identifier;
689 GdType type;
690 int flags;
691 char *name;
692 int offset;
693 int count;
694 char *tooltip;
695 int defval;
696 int min, max;
697 } GdCaveProperties;
699 extern const GdCaveProperties gd_cave_properties[];
701 extern const GdColor gd_flash_color;
702 extern const GdColor gd_select_color;
705 /* arrays for movements */
706 /* also no1 and bd2 cave data import helpers; line direction coordinates */
707 extern const int gd_dx[], gd_dy[];
709 /* names of directions */
710 extern const char* gd_direction_name[];
711 /* names of schedulings */
712 extern const char* gd_scheduling_name[];
713 extern const char* gd_scheduling_filename[]; /* identifiers in bdcff */
715 /* init cave engine */
716 void gd_cave_init();
718 /* for cave tags hash table */
719 gboolean gd_str_case_equal(gconstpointer s1, gconstpointer s2);
720 guint gd_str_case_hash(gconstpointer v);
722 /* cave highscore functions */
723 int gd_highscore_compare(gconstpointer a, gconstpointer b);
724 gboolean gd_cave_is_highscore(Cave *cave, int score);
725 int gd_cave_add_highscore(Cave *cave, GdHighScore hs);
726 void gd_cave_clear_highscore(Cave *cave);
728 /* cave creator and destructor functions */
729 Cave *gd_cave_new(void);
730 Cave *gd_cave_new_from_cave(const Cave *orig);
731 void gd_cave_copy(Cave *dest, const Cave *src);
732 void gd_cave_free(Cave *cave);
734 /* cave manipulation */
735 void gd_cave_set_defaults(Cave *cave);
736 void gd_cave_correct_visible_size(Cave *cave);
737 void gd_cave_shrink(Cave *cave);
738 void gd_cave_easy(Cave *cave);
739 void gd_cave_set_random_colors(Cave *cave);
740 void gd_cave_set_ckdelay_extra_for_animation(Cave *cave);
741 void gd_cave_setup_for_game(Cave *cave);
742 void gd_cave_count_diamonds(Cave *cave);
744 /* support */
745 gpointer gd_cave_map_new_for_cave(const Cave *cave, const int cell_size);
746 gpointer gd_cave_map_dup_size(const Cave * cave, const gpointer map, const int cell_size);
747 #define gd_cave_map_new(CAVE, TYPE) ((TYPE **)gd_cave_map_new_for_cave((CAVE), sizeof(TYPE)))
748 #define gd_cave_map_dup(CAVE, MAP) ((gpointer)gd_cave_map_dup_size((CAVE), (gpointer *)(CAVE)->MAP, sizeof((CAVE)->MAP[0][0])))
749 void gd_cave_map_free(gpointer map);
750 void gd_cave_store_rc (Cave * cave, const int x, const int y, const GdElement element, const void* order);
751 static inline GdElement
752 gd_cave_get_rc (const Cave *cave, const int x, const int y)
754 g_assert(x >= 0 && x < cave->w && y >= 0 && y < cave->h); /* check bounds */
756 return cave->map[y][x];
758 unsigned int gd_c64_predictable_random(Cave *);
759 void gd_cave_clear_strings(Cave *cave);
761 /* i/o */
762 const char* gd_get_color_name(GdColor color);
763 int gd_get_c64_color_index(GdColor color);
764 GdColor gd_get_color_from_string(const char *color);
766 void gd_create_char_to_element_table();
767 GdElement gd_get_element_from_character (guint8 character);
768 GdElement gd_get_element_from_string (const char *string);
770 #define GD_REDRAW (1<<10)
771 void gd_drawcave_game (const Cave *cave, int **gfx_buffer, gboolean bonus_life_flash, gboolean paused);
773 gboolean gd_cave_scroll(int width, int visible, int center, gboolean exact, int start, int to, int *current, int *desired, int *speed);
776 #endif /* _CAVE_H */