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