removed library dependency to glib-2.0
[rocksndiamonds.git] / src / game_bd / bd_cave.h
1 /*
2  * Copyright (c) 2007, 2008, 2009, Czirkos Zoltan <cirix@fw.hu>
3  *
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.
7  *
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.
15  */
16
17 #ifndef BD_CAVE_H
18 #define BD_CAVE_H
19
20 #include "bd_elements.h"
21 #include "bd_random.h"
22
23
24 // colors
25
26 typedef unsigned int GdColor;
27
28 /* color internal:
29    XXRRGGBB;
30    XX is 0 for RGB,
31          1 for c64 colors (bb=index)
32          3 for c64dtv (bb=index)
33          2 for atari colors (bb=index)
34 */
35
36 typedef enum _color_type
37 {
38   GD_COLOR_TYPE_RGB     = 0,
39   GD_COLOR_TYPE_C64     = 1,
40   GD_COLOR_TYPE_C64DTV  = 2,
41   GD_COLOR_TYPE_ATARI   = 3,
42
43   GD_COLOR_TYPE_UNKNOWN    /* should be the last one */
44 } GdColorType;
45
46 /* traditional c64 color indexes. */
47 #define GD_COLOR_INDEX_BLACK            (0)
48 #define GD_COLOR_INDEX_WHITE            (1)
49 #define GD_COLOR_INDEX_RED              (2)
50 #define GD_COLOR_INDEX_CYAN             (3)
51 #define GD_COLOR_INDEX_PURPLE           (4)
52 #define GD_COLOR_INDEX_GREEN            (5)
53 #define GD_COLOR_INDEX_BLUE             (6)
54 #define GD_COLOR_INDEX_YELLOW           (7)
55 #define GD_COLOR_INDEX_ORANGE           (8)
56 #define GD_COLOR_INDEX_BROWN            (9)
57 #define GD_COLOR_INDEX_LIGHTRED         (10)
58 #define GD_COLOR_INDEX_GRAY1            (11)
59 #define GD_COLOR_INDEX_GRAY2            (12)
60 #define GD_COLOR_INDEX_LIGHTGREEN       (13)
61 #define GD_COLOR_INDEX_LIGHTBLUE        (14)
62 #define GD_COLOR_INDEX_GRAY3            (15)
63
64 #define GD_GDASH_BLACK          (0x000000)
65 #define GD_GDASH_WHITE          (0xFFFFFF)
66 #define GD_GDASH_RED            (0x880000)
67 #define GD_GDASH_CYAN           (0xAAFFEE)
68 #define GD_GDASH_PURPLE         (0xCC44CC)
69 #define GD_GDASH_GREEN          (0x00CC55)
70 #define GD_GDASH_BLUE           (0x0000AA)
71 #define GD_GDASH_YELLOW         (0xEEEE77)
72 #define GD_GDASH_ORANGE         (0xDD8855)
73 #define GD_GDASH_BROWN          (0x664400)
74 #define GD_GDASH_LIGHTRED       (0xFF7777)
75 #define GD_GDASH_GRAY1          (0x333333)
76 #define GD_GDASH_GRAY2          (0x777777)
77 #define GD_GDASH_LIGHTGREEN     (0xAAFF66)
78 #define GD_GDASH_LIGHTBLUE      (0x0088FF)
79 #define GD_GDASH_GRAY3          (0xBBBBBB)
80
81 #define GD_COLOR_INVALID (0xFFFFFFFF)
82
83
84 /******************************************
85  *
86  * BIG STRUCT HANDLING
87  *
88  */
89
90 /* possible types handled */
91 typedef enum _gd_type
92 {
93   /* not real types, only used by editor to build ui */
94   GD_TAB,
95   GD_LABEL,
96
97   /* gd types */
98   GD_TYPE_STRING,        /* static string, fixed array of characters */
99   GD_TYPE_LONGSTRING,    /* long string which has its own notebook page in
100                             the editor */
101   GD_TYPE_INT,
102   GD_TYPE_RATIO,
103   GD_TYPE_ELEMENT,
104   GD_TYPE_BOOLEAN,
105   GD_TYPE_PROBABILITY,   /* probabilities are stored in parts per million,
106                             ie. *1E6, converted to int. */
107   GD_TYPE_COLOR,
108   GD_TYPE_EFFECT,
109   GD_TYPE_DIRECTION,
110   GD_TYPE_SCHEDULING,
111 } GdType;
112
113 enum _gd_property_flags
114 {
115   GD_ALWAYS_SAVE           = 1 << 0,
116   GD_DONT_SAVE             = 1 << 1,
117   GD_DONT_SHOW_IN_EDITOR   = 1 << 2,
118   GD_SHOW_LEVEL_LABEL      = 1 << 3,
119   GD_COMPATIBILITY_SETTING = 1 << 4,
120 };
121
122 typedef struct _gd_struct_descriptor
123 {
124   char *identifier; /* bdcff identifier */
125   GdType type;      /* data type */
126   int flags;        /* flags for bdcff saving/loading */
127   char *name;       /* name in editor */
128   int offset;       /* byte offset in a GdCave structure. use the CAVE_OFFSET macro */
129   int count;        /* size of array; usually 1, for non-arrays. */
130   char *tooltip;    /* tooltip text in editor */
131   int min, max;     /* integers have minimum and maximum */
132 } GdStructDescriptor;
133
134 typedef struct _gd_property_default
135 {
136   int offset;    /* data offset (bytes) in a cave structure */
137   int defval;    /* default value, converted to int. if type is a float, *1000000 */
138
139   int property_index;    /* index in gd_cave_properties; created at runtime */
140 } GdPropertyDefault;
141
142
143 void gd_struct_set_defaults_from_array(void *str, const GdStructDescriptor *properties, GdPropertyDefault *defaults);
144
145 /* these define the number of the cells in the png file */
146 #define GD_NUM_OF_CELLS_X 8
147 #define GD_NUM_OF_CELLS_Y 46
148
149 /* +80: placeholder for cells which are rendered by the game;
150    for example diamond + arrow = falling diamond */
151 #define GD_NUM_OF_CELLS (GD_NUM_OF_CELLS_X*GD_NUM_OF_CELLS_Y+80)
152
153 /* maximum replay size (maximum seconds x game cycles per second) */
154 #define MAX_REPLAY_LEN  (10000 * FRAMES_PER_SECOND / 8)
155
156 extern const GdColor gd_flash_color;
157 extern const GdColor gd_select_color;
158
159 enum _element_property
160 {
161   E_P_SLOPED_LEFT,      /* stones and diamonds roll down to left on this */
162   E_P_SLOPED_RIGHT,     /* stones and diamonds roll down to right on this */
163   E_P_SLOPED_UP,
164   E_P_SLOPED_DOWN,
165   E_P_BLADDER_SLOPED,   /* element act sloped also for the bladder */
166
167   E_P_AMOEBA_CONSUMES,  /* amoeba can eat this */
168   E_P_DIRT,             /* it is dirt, or something similar (dirt2 or sloped dirt) */
169   E_P_BLOWS_UP_FLIES,   /* flies blow up, if they touch this */
170   E_P_EXPLODES_BY_HIT,  /* explodes if hit by a stone */
171
172   E_P_EXPLOSION,                /* set for every stage of every explosion. */
173   E_P_EXPLOSION_FIRST_STAGE,    /* set for first stage of every explosion.
174                                    helps slower/faster explosions changing */
175
176   E_P_NON_EXPLODABLE,           /* selfexplaining */
177   E_P_CCW,                      /* this creature has a default counterclockwise
178                                    rotation (for example, o_fire_1) */
179   E_P_CAN_BE_HAMMERED,          /* can be broken by pneumatic hammer */
180   E_P_VISUAL_EFFECT,            /* if the element can use a visual effect.
181                                    used to check consistency of the code */
182   E_P_PLAYER,                   /* easier to find out if it is a player element */
183   E_P_MOVED_BY_CONVEYOR_TOP,    /* can be moved by conveyor belt */
184   E_P_MOVED_BY_CONVEYOR_BOTTOM, /* can be moved UNDER the conveyor belt */
185
186   E_P_COLLECTIBLE,              /* can be collected */
187 };
188
189 /* properties */
190 #define P_SLOPED_LEFT                   (1 << E_P_SLOPED_LEFT)
191 #define P_SLOPED_RIGHT                  (1 << E_P_SLOPED_RIGHT)
192 #define P_SLOPED_UP                     (1 << E_P_SLOPED_UP)
193 #define P_SLOPED_DOWN                   (1 << E_P_SLOPED_DOWN)
194
195 /* flag to say "any direction" */
196 #define P_SLOPED                        (P_SLOPED_LEFT  |               \
197                                          P_SLOPED_RIGHT |               \
198                                          P_SLOPED_UP    |               \
199                                          P_SLOPED_DOWN)
200
201 #define P_BLADDER_SLOPED                (1 << E_P_BLADDER_SLOPED)
202
203 #define P_AMOEBA_CONSUMES               (1 << E_P_AMOEBA_CONSUMES)
204 #define P_DIRT                          (1 << E_P_DIRT)
205 #define P_BLOWS_UP_FLIES                (1 << E_P_BLOWS_UP_FLIES)
206
207 #define P_EXPLODES_BY_HIT               (1 << E_P_EXPLODES_BY_HIT)
208 #define P_EXPLOSION                     (1 << E_P_EXPLOSION)
209 #define P_EXPLOSION_FIRST_STAGE         (1 << E_P_EXPLOSION_FIRST_STAGE)
210
211 #define P_NON_EXPLODABLE                (1 << E_P_NON_EXPLODABLE)
212 #define P_CCW                           (1 << E_P_CCW)
213 #define P_CAN_BE_HAMMERED               (1 << E_P_CAN_BE_HAMMERED)
214 #define P_VISUAL_EFFECT                 (1 << E_P_VISUAL_EFFECT)
215 #define P_PLAYER                        (1 << E_P_PLAYER)
216 #define P_MOVED_BY_CONVEYOR_TOP         (1 << E_P_MOVED_BY_CONVEYOR_TOP)
217 #define P_MOVED_BY_CONVEYOR_BOTTOM      (1 << E_P_MOVED_BY_CONVEYOR_BOTTOM)
218
219 #define P_COLLECTIBLE                   (1 << E_P_COLLECTIBLE)
220
221 /* These are states of the magic wall. */
222 typedef enum _magic_wall_state
223 {
224   GD_MW_DORMANT,                /* Starting with this. */
225   GD_MW_ACTIVE,                 /* Boulder or diamond dropped into. */
226   GD_MW_EXPIRED                 /* Turned off after magic_wall_milling_time. */
227 } GdMagicWallState;
228
229 /* These are states of Player. */
230 typedef enum _player_state
231 {
232   GD_PL_NOT_YET,                /* Not yet living. Beginning of cave time. */
233   GD_PL_LIVING,                 /* Ok. */
234   GD_PL_TIMEOUT,                /* Time is up */
235   GD_PL_DIED,                   /* Died. */
236   GD_PL_EXITED                  /* Exited the cave, proceed to next one */
237 } GdPlayerState;
238
239 /* States of amoeba */
240 typedef enum _amoeba_state
241 {
242   GD_AM_SLEEPING,               /* sleeping - not yet let out. */
243   GD_AM_AWAKE,                  /* living, growing */
244   GD_AM_TOO_BIG,                /* grown too big, will convert to stones */
245   GD_AM_ENCLOSED,               /* enclosed, will convert to diamonds */
246 } GdAmoebaState;
247
248 typedef enum _direction
249 {
250   /* not moving */
251   GD_MV_STILL           = 0,
252   GD_MV_THIS            = 0,
253
254   /* directions */
255   GD_MV_UP              = 1,
256   GD_MV_UP_RIGHT        = 2,
257   GD_MV_RIGHT           = 3,
258   GD_MV_DOWN_RIGHT      = 4,
259   GD_MV_DOWN            = 5,
260   GD_MV_DOWN_LEFT       = 6,
261   GD_MV_LEFT            = 7,
262   GD_MV_UP_LEFT         = 8,
263
264   /* to be able to type GD_MV_TWICE + GD_MV_DOWN, for example */
265   GD_MV_TWICE           = 8,
266
267   /* directions * 2 */
268   GD_MV_UP_2            = 9,
269   GD_MV_UP_RIGHT_2      = 10,
270   GD_MV_RIGHT_2         = 11,
271   GD_MV_DOWN_RIGHT_2    = 12,
272   GD_MV_DOWN_2          = 13,
273   GD_MV_DOWN_LEFT_2     = 14,
274   GD_MV_LEFT_2          = 15,
275   GD_MV_UP_LEFT_2       = 16,
276
277   GD_MV_MAX,
278 } GdDirection;
279
280 enum
281 {
282   GD_REPLAY_MOVE_MASK    = 0x0f,
283   GD_REPLAY_FIRE_MASK    = 0x10,
284   GD_REPLAY_SUICIDE_MASK = 0x20,
285 };
286
287
288 /* ELEMENTS DESCRIPTION */
289 typedef struct _elements
290 {
291   GdElement element;    /* element number. for example O_DIRT */
292   char *name;           /* name in editor, for example "Dirt". some have
293                            different names than their real engine meaning! */
294   unsigned int properties; /* engine properties, like P_SLOPED or P_EXPLODES */
295   char *filename;       /* name in bdcff file, like "DIRT" */
296   char character;       /* character representation in bdcff file, like '.' */
297   int image;            /* image in editor (index in cells.png) */
298   int image_simple;     /* image for simple view in editor, and for combo box (index in cells.png) */
299   int image_game;       /* image for game. negative if animated */
300   int ckdelay;          /* ckdelay ratio - how much time required for a c64 to
301                            process this element - in microseconds. */
302
303   char *lowercase_name; /* lowercase of translated name. for editor; generated inside the game. */
304   char character_new;   /* character given automatically for elements which
305                            don't have one defined in original bdcff description */
306 } GdElements;
307
308
309 typedef char GdString[128];
310
311 typedef struct _highscore
312 {
313   GdString name;
314   int score;
315 } GdHighScore;
316
317 typedef struct _replay_movements
318 {
319   unsigned char data[MAX_REPLAY_LEN];
320   unsigned int len;
321 } GdReplayMovements;
322
323 /* maximum seed value for the cave random generator. should be smaller than a signed int. */
324 #define GD_CAVE_SEED_MAX        (1 << 30)
325
326 typedef struct _gd_cave_replay
327 {
328   int level;                /* replay for level n */
329   unsigned int seed;        /* seed the cave is to be rendered with */
330   boolean saved;            /* also store it in the saved bdcff */
331   GdString recorded_with;   /* recorded with - application name and version */
332
333   GdString player_name;     /* who played this */
334   GdString date;            /* when played */
335   char *comment;            /* some comments from the player */
336
337   int score;                /* score collected */
338   int duration;             /* number of seconds played */
339   boolean success;          /* successful playing of cave? */
340   unsigned int checksum;    /* checksum of the rendered cave. */
341
342   boolean wrong_checksum;
343   GdReplayMovements *movements;
344   int current_playing_pos;
345 } GdReplay;
346
347 typedef enum _gd_scheduling
348 {
349   GD_SCHEDULING_MILLISECONDS,
350   GD_SCHEDULING_BD1,
351   GD_SCHEDULING_BD2,
352   GD_SCHEDULING_PLCK,
353   GD_SCHEDULING_CRDR,
354   GD_SCHEDULING_BD1_ATARI,
355   GD_SCHEDULING_BD2_PLCK_ATARI,
356   GD_SCHEDULING_MAX
357 } GdScheduling;
358
359 typedef struct _gd_c64_random_generator
360 {
361   int rand_seed_1, rand_seed_2;
362 } GdC64RandomGenerator;
363
364 /*
365     Structure holding all data belonging to a cave.
366 */
367
368 #define GD_HIGHSCORE_NUM 20
369
370 typedef struct _gd_cave
371 {
372   /* Defined by the editor. public data :) */
373   GdString name;                /* Name of cave */
374   GdString description;        /* Some words about the cave */
375   GdString author;            /* Author */
376   GdString difficulty;        /* difficulty of the game, for info purposes */
377   GdString www;                /* link to author's webpage */
378   GdString date;                /* date of creation */
379   char *story;                  /* story for the cave - will be shown when the cave is played. */
380   char *remark;                 /* some note */
381
382   GdString charset;            /* these are not used by gdash */
383   GdString fontset;
384
385   /* and this one the highscores */
386   GdHighScore highscore[GD_HIGHSCORE_NUM];
387
388   HashTable *tags;      /* stores read-but-not-understood strings from bdcff, so we can save them later. */
389
390   GdElement **map;            /* pointer to data for map, non-null if has a map */
391   List *objects;
392   List *replays;
393
394   boolean intermission;        /* is this cave an intermission? */
395   boolean intermission_instantlife;    /* one life extra, if the intermission is reached */
396   boolean intermission_rewardlife;    /* one life extra, if the intermission is successfully finished */
397   boolean selectable;            /* is this selectable as an initial cave for a game? */
398   boolean diagonal_movements;    /* are diagonal movements allowed? */
399   GdElement snap_element;        /* snapping (press fire+move) usually leaves space behind, but can be other */
400   boolean short_explosions;        /* in >=1stb, diamond and creature explosions were of 5 stages */
401
402   GdScheduling scheduling;    /* scheduling type; see above */
403   boolean pal_timing;        /* use faster seconds */
404
405   boolean active_is_first_found;    /* active player is the uppermost. */
406   boolean lineshift;                /* true is line shifting emulation, false is perfect borders emulation */
407   boolean border_scan_first_and_last;    /* if true, scans the first and last line of the border. false for plck */
408   boolean wraparound_objects;    /* if this is true, object drawing (cave rendering) will wraparound as well. */
409
410   GdElement initial_fill;
411   GdElement initial_border;
412   GdElement random_fill[4];        /* Random fill elements. */
413   int random_fill_probability[4];    /* Random fill, probability of each element. */
414
415   int level_rand[5];            /* Random seed. */
416   int level_diamonds[5];        /* Must collect diamonds, on level x */
417   int level_speed[5];            /* Time between game cycles in ms */
418   int level_ckdelay[5];        /* Timing in original game units */
419   int level_time[5];            /* Available time, per level */
420   int level_timevalue[5];        /* points for each second remaining, when exiting level */
421
422   int max_time;            /* the maximum time in seconds. if above, it overflows */
423
424   int w, h;                /* Sizes of cave, width and height. */
425   int x1,y1,x2,y2;        /* Visible part of the cave */
426   GdColor colorb;            /* border color */
427   GdColor color0, color1, color2, color3, color4, color5;    /* c64-style colors; 4 and 5 are amoeba and slime. */
428
429   int diamond_value;            /* Score for a diamond. */
430   int extra_diamond_value;    /* Score for a diamond, when gate is open. */
431
432   boolean stone_sound;
433   boolean nut_sound;
434   boolean diamond_sound;
435   boolean nitro_sound;
436   boolean falling_wall_sound;
437   boolean expanding_wall_sound;
438   boolean bladder_spender_sound;
439   boolean bladder_convert_sound;
440
441   int level_magic_wall_time[5];    /* magic wall 'on' state for each level (seconds) */
442   boolean magic_wall_stops_amoeba;    /* Turning on magic wall changes amoeba to diamonds. Original BD: yes, constkit: no */
443   boolean magic_timer_wait_for_hatching;    /* magic wall timer does not start before player's birth */
444   boolean magic_wall_sound;    /* magic wall has sound */
445
446   int level_amoeba_time[5];        /* amoeba time for each level */
447   int amoeba_growth_prob;        /* Amoeba slow growth probability */
448   int amoeba_fast_growth_prob;    /* Amoeba fast growth probability */
449   int level_amoeba_threshold[5];        /* amoeba turns to stones; if count is bigger than this (number of cells) */
450   GdElement amoeba_enclosed_effect;    /* an enclosed amoeba converts to this element */
451   GdElement amoeba_too_big_effect;    /* an amoeba grown too big converts to this element */
452
453   int level_amoeba_2_time[5];        /* amoeba time for each level */
454   int amoeba_2_growth_prob;        /* Amoeba slow growth probability */
455   int amoeba_2_fast_growth_prob;    /* Amoeba fast growth probability */
456   int level_amoeba_2_threshold[5];        /* amoeba turns to stones; if count is bigger than this (number of cells) */
457   GdElement amoeba_2_enclosed_effect;    /* an enclosed amoeba converts to this element */
458   GdElement amoeba_2_too_big_effect;    /* an amoeba grown too big converts to this element */
459   boolean amoeba_2_explodes_by_amoeba;    /* amoeba 2 will explode if touched by amoeba1 */
460   GdElement amoeba_2_explosion_effect;    /* amoeba 2 explosion ends in ... */
461   GdElement amoeba_2_looks_like;    /* an amoeba 2 looks like this element */
462
463   boolean amoeba_timer_started_immediately;    /* FALSE: amoeba will start life at the first possibility of growing. */
464   boolean amoeba_timer_wait_for_hatching;    /* amoeba timer does not start before player's birth */
465   boolean amoeba_sound;            /* if the living amoeba has sound. */
466
467   GdElement acid_eats_this;        /* acid eats this element */
468   int acid_spread_ratio;        /* Probability of acid blowing up, each frame */
469   boolean acid_spread_sound;        /* acid has sound */
470   GdElement acid_turns_to;        /* whether acid converts to explosion on spreading or other */
471
472   GdElement nut_turns_to_when_crushed;    /* when a nut is hit by a stone, it converts to this element */
473
474   int level_slime_permeability[5];        /* true random slime */
475   int level_slime_permeability_c64[5];    /* Appearing in bd 2 */
476   int level_slime_seed_c64[5];            /* predictable slime random seed */
477   boolean slime_predictable;                /* predictable random start for slime. yes for plck. */
478   GdElement slime_eats_1, slime_converts_1;    /* slime eats element x and converts to element x; for example diamond -> falling diamond */
479   GdElement slime_eats_2, slime_converts_2;    /* this is usually stone -> stone_f */
480   GdElement slime_eats_3, slime_converts_3;    /* this is usually nut -> nut_f */
481   boolean slime_sound;            /* slime has sound */
482
483   boolean lava_sound;            /* elements sinking in lava have sound */
484
485   int level_hatching_delay_frame[5];        /* Scan frames before Player's birth. */
486   int level_hatching_delay_time[5];        /* Scan frames before Player's birth. */
487
488   int level_bonus_time[5];        /* bonus time for clock collected. */
489   int level_penalty_time[5];                /* Time penalty when voodoo destroyed. */
490   boolean voodoo_collects_diamonds;    /* Voodoo can collect diamonds */
491   boolean voodoo_dies_by_stone;        /* Voodoo can be killed by a falling stone */
492   boolean voodoo_disappear_in_explosion;    /* Voodoo can be destroyed by and explosion */
493   boolean voodoo_any_hurt_kills_player;    /* If any of the voodoos are hurt in any way, the player is killed. */
494
495   boolean water_does_not_flow_down;    /* if true, water will not grow downwards, only in other directions. */
496   boolean water_sound;            /* water has sound */
497
498   boolean bladder_sound;        /* bladder moving and pushing has sound */
499   GdElement bladder_converts_by;    /* bladder converts to clock by touching this element */
500
501   int biter_delay_frame;        /* frame count biters do move */
502   GdElement biter_eat;        /* biters eat this */
503   boolean biter_sound;        /* biters have sound */
504
505   boolean expanding_wall_changed;    /* expanding wall direction is changed */
506
507   int    replicator_delay_frame;        /* replicator delay in frames (number of frames to wait between creating a new element) */
508   boolean replicators_active;        /* replicators are active. */
509   boolean replicator_sound;        /* when replicating an element, play sound or not. */
510
511   boolean conveyor_belts_active;
512   boolean conveyor_belts_direction_changed;
513
514   /* effects */
515   GdElement explosion_effect;            /* explosion converts to this element after its last stage. diego effect. */
516   GdElement diamond_birth_effect;        /* a diamond birth converts to this element after its last stage. diego effect. */
517   GdElement bomb_explosion_effect;        /* bombs explode to this element. diego effect (almost). */
518   GdElement nitro_explosion_effect;    /* nitros explode to this */
519
520   GdElement firefly_explode_to;        /* fireflies explode to this when hit by a stone */
521   GdElement alt_firefly_explode_to;    /* alternative fireflies explode to this when hit by a stone */
522   GdElement butterfly_explode_to;        /* butterflies explode to this when hit by a stone */
523   GdElement alt_butterfly_explode_to;    /* alternative butterflies explode to this when hit by a stone */
524   GdElement stonefly_explode_to;        /* stoneflies explode to this when hit by a stone */
525   GdElement dragonfly_explode_to;        /* dragonflies explode to this when hit by a stone */
526
527   GdElement stone_falling_effect;        /* a falling stone converts to this element. diego effect. */
528   GdElement diamond_falling_effect;    /* a falling diamond converts to this element. diego effect. */
529   GdElement stone_bouncing_effect;    /* a bouncing stone converts to this element. diego effect. */
530   GdElement diamond_bouncing_effect;    /* a bouncing diamond converts to this element. diego effect. */
531
532   GdElement expanding_wall_looks_like;    /* an expanding wall looks like this element. diego effect. */
533   GdElement dirt_looks_like;            /* dirt looks like this element. diego effect. */
534
535   GdElement magic_stone_to;        /* magic wall converts falling stone to */
536   GdElement magic_diamond_to;        /* magic wall converts falling diamond to */
537   GdElement magic_mega_stone_to;    /* magic wall converts a falling mega stone to */
538   GdElement magic_nitro_pack_to;    /* magic wall converts a falling nitro pack to */
539   GdElement magic_nut_to;                /* magic wall converts a falling nut to */
540   GdElement magic_flying_stone_to;    /* flying stones are converted to */
541   GdElement magic_flying_diamond_to;    /* flying diamonds are converted to */
542
543   int pushing_stone_prob;        /* probability of pushing stone */
544   int pushing_stone_prob_sweet;    /* probability of pushing, after eating sweet */
545   boolean mega_stones_pushable_with_sweet;    /* mega stones may be pushed with sweet */
546
547   boolean creatures_backwards;    /* creatures changed direction */
548   boolean creatures_direction_auto_change_on_start;    /* the change occurs also at the start signal */
549   int creatures_direction_auto_change_time;    /* creatures automatically change direction every x seconds */
550   boolean creature_direction_auto_change_sound;    /* automatically changing creature direction may have the sound of the creature dir switch */
551
552   int skeletons_needed_for_pot;    /* how many skeletons to be collected, to use a pot */
553   int skeletons_worth_diamonds;    /* for crazy dream 7 compatibility: collecting skeletons might open the cave door. */
554
555   GdDirection gravity;
556   int gravity_change_time;
557   boolean gravity_change_sound;
558   boolean gravity_affects_all;    /* if true, gravity also affects falling wall, bladder and waiting stones */
559   boolean gravity_switch_active;    /* true if gravity switch is activated, and can be used. */
560
561   boolean hammered_walls_reappear;
562   int pneumatic_hammer_frame;
563   int hammered_wall_reappear_frame;
564   boolean pneumatic_hammer_sound;
565
566   /* internal variables, used during the game. private data :) */
567
568   /* returns range corrected x/y position (points to perfect or line shifting get function) */
569   int (*getx) (const struct _gd_cave*, int x, int y);
570   int (*gety) (const struct _gd_cave*, int x, int y);
571
572   /* returns pointer to element at x, y (points to perfect border or a line shifting get function) */
573   GdElement* (*getp) (const struct _gd_cave*, int x, int y);
574
575   boolean hatched;            /* hatching has happened. (timers may run, ...) */
576   boolean gate_open;            /* self-explaining */
577   unsigned int render_seed;        /* the seed value, which was used to render the cave, is saved here. will be used by record&playback */
578   GdRand *random;               /* random number generator of rendered cave */
579   int rendered;                /* if not zero, rendered at level x */
580   int timing_factor;            /* number of "milliseconds" in each second :) 1000 for ntsc, 1200 for pal. */
581   void ***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. */
582   int **hammered_reappear;    /* integer map of cave; if non-zero, a brick wall will appear there */
583
584   int speed;                    /* Time between game cycles in ms */
585   int c64_timing;                /* a ckdelay value for the level this cave is rendered for */
586   int ckdelay;                /* ckdelay value for the current iteration */
587   int ckdelay_extra_for_animation;    /* bd1 and similar engines had animation bits in cave data, to set which elements to animate (firefly, butterfly, amoeba).
588                                             animating an element also caused some delay each frame; according to my measurements, around 2.6 ms/element. */
589
590   int frame;  /* XXX */
591
592   int hatching_delay_frame;
593   int hatching_delay_time;
594   int time_bonus;                /* bonus time for clock collected. */
595   int time_penalty;            /* Time penalty when voodoo destroyed. */
596   int time;                    /* milliseconds remaining to finish cave */
597   int timevalue;                /* points for remaining seconds - for current level */
598   int diamonds_needed;        /* diamonds needed to open outbox */
599   int diamonds_collected;        /* diamonds collected */
600   int skeletons_collected;    /* number of skeletons collected */
601   int gate_open_flash;        /* flashing of screen when gate opens */
602   int score;                    /* Score got this frame. */
603   int amoeba_time;            /* Amoeba growing slow (low probability, default 3%) for milliseconds. After that, fast growth default (25%) */
604   int amoeba_2_time;            /* Amoeba growing slow (low probability, default 3%) for milliseconds. After that, fast growth default (25%) */
605   int amoeba_max_count;            /* selected amoeba 1 threshold for this level */
606   int amoeba_2_max_count;            /* selected amoeba 2 threshold for this level */
607   GdAmoebaState amoeba_state;        /* state of amoeba 1 */
608   GdAmoebaState amoeba_2_state;    /* state of amoeba 2 */
609   int magic_wall_time;            /* magic wall 'on' state for seconds */
610   int slime_permeability;        /* true random slime */
611   int slime_permeability_c64;        /* Appearing in bd 2 */
612   GdMagicWallState magic_wall_state;        /* State of magic wall */
613   GdPlayerState player_state;        /* Player state. not yet living, living, exited... */
614   int player_seen_ago;            /* player was seen this number of scans ago */
615   boolean voodoo_touched;        /* as its name says */
616   boolean kill_player;            /* Voodoo died, or used pressed escape to restart level. */
617   boolean sweet_eaten;            /* player ate sweet, he's strong. prob_sweet applies, and also able to push chasing stones */
618   int player_x, player_y;            /* Coordinates of player (for scrolling) */
619   int px[16], py[16];                /* coordinates of player, for chasing stone */
620   int key1, key2, key3;            /* The player is holding this number of keys of each color */
621   boolean diamond_key_collected;    /* Key collected, so trapped diamonds convert to diamonds */
622   boolean inbox_flash_toggle;    /* negated every scan. helps drawing inboxes, and making players be born at different times. */
623   GdDirection last_direction;        /* last direction player moved. used by draw routines */
624   GdDirection last_horizontal_direction;
625   int biters_wait_frame;                /* number of frames to wait until biters will move again */
626   int replicators_wait_frame;            /* number of frames to wait until replicators are activated again */
627   int creatures_direction_will_change;    /* creatures automatically change direction every x seconds */
628   GdC64RandomGenerator c64_rand;    /* used for predictable random generator during the game. */
629
630   int gravity_will_change;    /* gravity will change in this number of milliseconds */
631   boolean gravity_disabled;    /* when the player is stirring the pot, there is no gravity. */
632   GdDirection gravity_next_direction;    /* next direction when the gravity changes. will be set by the player "getting" a gravity switch */
633   boolean got_pneumatic_hammer;    /* true if the player has a pneumatic hammer */
634   int pneumatic_hammer_active_delay;    /* number of frames to wait, till pneumatic hammer will destroy the wall */
635   GdSound sound1, sound2, sound3;    /* sound set for 3 channels after each iteration */
636 } GdCave;
637
638
639 #define CAVE_OFFSET(property) (STRUCT_OFFSET(GdCave, property))
640
641 /* arrays for movements */
642 /* also no1 and bd2 cave data import helpers; line direction coordinates */
643 extern const int gd_dx[], gd_dy[];
644
645 extern GdElement gd_char_to_element[];
646
647 void gd_create_char_to_element_table(void);
648 GdElement gd_get_element_from_character(unsigned char character);
649 GdElement gd_get_element_from_string(const char *string);
650
651 /* init cave engine */
652 void gd_cave_init(void);
653
654 /* for cave tags hash table */
655 int gd_str_case_equal(void *s1, void *s2);
656 unsigned int gd_str_case_hash(void *v);
657
658 /* cave highscore functions */
659 int gd_highscore_compare(const void *a, const void *b);
660 boolean gd_is_highscore(GdHighScore *scores, int score);
661 int gd_add_highscore(GdHighScore *highscores, const char *name, int score);
662 void gd_clear_highscore(GdHighScore *hs);
663 boolean gd_has_highscore(GdHighScore *hs);
664
665 /* cave creator and destructor functions */
666 GdCave *gd_cave_new(void);
667 GdCave *gd_cave_new_from_cave(const GdCave *orig);
668 void gd_cave_copy(GdCave *dest, const GdCave *src);
669 void gd_cave_free(GdCave *cave);
670
671 /* cave manipulation */
672 void gd_cave_set_gdash_defaults(GdCave *cave);
673 void gd_cave_set_defaults_from_array(GdCave* cave, GdPropertyDefault *defaults);
674 void gd_cave_correct_visible_size(GdCave *cave);
675 void gd_cave_auto_shrink(GdCave *cave);
676
677 void gd_cave_setup_for_game(GdCave *cave);
678 void gd_cave_count_diamonds(GdCave *cave);
679
680 /* c64 random generator support for cave fill */
681 unsigned int gd_c64_random(GdC64RandomGenerator *rand);
682 unsigned int gd_cave_c64_random(GdCave *);
683 void gd_c64_random_set_seed(GdC64RandomGenerator *rand, int seed1, int seed2);
684 void gd_cave_c64_random_set_seed(GdCave *cave, int seed1, int seed2);
685
686 /* support */
687 void *gd_cave_map_new_for_cave(const GdCave *cave, const int cell_size);
688 void *gd_cave_map_dup_size(const GdCave * cave, const void *map, const int cell_size);
689 #define gd_cave_map_new(CAVE, TYPE) ((TYPE **)gd_cave_map_new_for_cave((CAVE), sizeof(TYPE)))
690 #define gd_cave_map_dup(CAVE, MAP) ((void *)gd_cave_map_dup_size((CAVE), (void **)(CAVE)->MAP, sizeof((CAVE)->MAP[0][0])))
691 void gd_cave_map_free(void *map);
692
693 void gd_cave_store_rc(GdCave * cave, int x, int y, const GdElement element, const void* order);
694 GdElement gd_cave_get_rc (const GdCave *cave, int x, int y);
695
696 /* direction */
697 const char *gd_direction_get_visible_name(GdDirection dir);
698 const char *gd_direction_get_filename(GdDirection dir);
699 GdDirection gd_direction_from_string(const char *str);
700
701 /* scheduling */
702 const char *gd_scheduling_get_visible_name(GdScheduling sched);
703 const char *gd_scheduling_get_filename(GdScheduling sched);
704 GdScheduling gd_scheduling_from_string(const char *str);
705
706 /* game playing helpers */
707 #define GD_REDRAW (1 << 10)
708
709 void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer,
710                       boolean bonus_life_flash, int animcycle, boolean hate_invisible_outbox);
711
712 /* function to copy a GdString */
713 static inline char *gd_strcpy(GdString dest, const GdString src)
714 {
715     return strncpy(dest, src, sizeof(GdString));
716 }
717
718 int gd_cave_time_show(const GdCave *cave, int internal_time);
719
720 GdReplay *gd_replay_new(void);
721 GdReplay *gd_replay_new_from_replay(GdReplay *orig);
722 void gd_replay_free(GdReplay *replay);
723 void gd_replay_store_movement(GdReplay *replay, GdDirection player_move, boolean player_fire, boolean suicide);
724
725 unsigned int gd_cave_adler_checksum(GdCave *cave);
726 void gd_cave_adler_checksum_more(GdCave *cave, unsigned int *a, unsigned int *b);
727
728 GdColor gd_c64_color(int);
729
730 #endif  // BD_CAVE_H