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.
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
{
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
{
60 O_DIRT_SLOPED_UP_RIGHT
,
61 O_DIRT_SLOPED_UP_LEFT
,
62 O_DIRT_SLOPED_DOWN_LEFT
,
63 O_DIRT_SLOPED_DOWN_RIGHT
,
66 O_BRICK_SLOPED_UP_RIGHT
,
67 O_BRICK_SLOPED_UP_LEFT
,
68 O_BRICK_SLOPED_DOWN_LEFT
,
69 O_BRICK_SLOPED_DOWN_RIGHT
,
76 O_STEEL_SLOPED_UP_RIGHT
,
77 O_STEEL_SLOPED_UP_LEFT
,
78 O_STEEL_SLOPED_DOWN_LEFT
,
79 O_STEEL_SLOPED_DOWN_RIGHT
,
94 O_GROWING_WALL_SWITCH
,
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. */
259 /* fake elements to help drawing */
269 O_CREATURE_SWITCH_ON
,
270 O_GROWING_WALL_SWITCH_HORIZ
,
271 O_GROWING_WALL_SWITCH_VERT
,
272 O_GRAVITY_SWITCH_ACTIVE
,
284 /* binary AND this to elements to get rid of properties above. */
285 O_MASK
= ~(SCANNED
| COVERED
)
288 extern GdElement gd_char_to_element
[];
290 typedef enum _element_property
{
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. */
320 /** These are states of Player. */
321 typedef enum player_state
{
322 PL_NOT_YET
, /* Not yet living. Beginning of cave time. */
324 PL_TIMEOUT
, /* Time is up */
326 PL_EXITED
/* Exited the cave, proceed to next one */
329 typedef enum _direction
{
344 /* to be able to type MV_TWICE+MV_DOWN, for example */
358 typedef enum _sound
{
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 */
383 GD_S_DIAMOND_COLLECT
,
384 GD_S_PNEUMATIC_COLLECT
,
389 GD_S_SKELETON_COLLECT
,
393 GD_S_BLADDER_CONVERT
,
394 GD_S_BLADDER_SPENDER
,
408 GD_S_GHOST_EXPLOSION
,
409 GD_S_VOODOO_EXPLOSION
,
413 GD_S_SWITCH_CREATURES
,
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 */
437 extern GdElements gd_elements
[];
439 typedef char GdString
[128];
441 typedef struct _highscore
{
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 */
462 typedef enum _gd_scheduling
{
463 GD_SCHEDULING_MILLISECONDS
,
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 */
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 */
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 */
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. */
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 */
660 /* CAVE DESCRIPTION */
661 typedef enum _gd_type
{
662 /* not real types, only used by editor to build ui */
680 enum _gd_property_flags
{
684 GD_DONT_SHOW_IN_EDITOR
=1<<3,
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 */
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
);
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
);
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
);