#include "bd_random.h"
-/******************************************
- *
- * BIG STRUCT HANDLING
- *
- */
+// ============================================================================
+// BIG STRUCT HANDLING
+// ============================================================================
-/* possible types handled */
+// possible types handled
typedef enum _gd_type
{
- /* not real types, only used by editor to build ui */
+ // not real types, only used by editor to build ui
GD_TAB,
GD_LABEL,
- /* gd types */
- GD_TYPE_STRING, /* static string, fixed array of characters */
- GD_TYPE_LONGSTRING, /* long string which has its own notebook page in
- the editor */
+ // gd types
+ GD_TYPE_STRING, // static string, fixed array of characters
+ GD_TYPE_LONGSTRING, // long string which has its own notebook page in the editor
GD_TYPE_INT,
GD_TYPE_RATIO,
GD_TYPE_ELEMENT,
GD_TYPE_BOOLEAN,
- GD_TYPE_PROBABILITY, /* probabilities are stored in parts per million,
- ie. *1E6, converted to int. */
+ GD_TYPE_PROBABILITY, // probabilities are stored in parts per million,
+ // ie. *1E6, converted to int.
GD_TYPE_COLOR,
GD_TYPE_EFFECT,
GD_TYPE_DIRECTION,
typedef struct _gd_struct_descriptor
{
- char *identifier; /* bdcff identifier */
- GdType type; /* data type */
- int flags; /* flags for bdcff saving/loading */
- char *name; /* name in editor */
- int offset; /* byte offset in a GdCave structure. use the CAVE_OFFSET macro */
- int count; /* size of array; usually 1, for non-arrays. */
- char *tooltip; /* tooltip text in editor */
- int min, max; /* integers have minimum and maximum */
+ char *identifier; // bdcff identifier
+ GdType type; // data type
+ int flags; // flags for bdcff saving/loading
+ char *name; // name in editor
+ int offset; // byte offset in a GdCave structure. use the CAVE_OFFSET macro
+ int count; // size of array; usually 1, for non-arrays.
+ char *tooltip; // tooltip text in editor
+ int min, max; // integers have minimum and maximum
} GdStructDescriptor;
typedef struct _gd_property_default
{
- int offset; /* data offset (bytes) in a cave structure */
- int defval; /* default value, converted to int. if type is a float, *1000000 */
+ int offset; // data offset (bytes) in a cave structure
+ int defval; // default value, converted to int. if type is a float, *1000000
- int property_index; /* index in gd_cave_properties; created at runtime */
+ int property_index; // index in gd_cave_properties; created at runtime
} GdPropertyDefault;
void gd_struct_set_defaults_from_array(void *str, const GdStructDescriptor *properties, GdPropertyDefault *defaults);
-/* these define the number of the cells in the png file */
-#define GD_NUM_OF_CELLS_X 8
-#define GD_NUM_OF_CELLS_Y 46
+// these define the number of the cells in the png file
+#define GD_NUM_OF_CELLS_X 8
+#define GD_NUM_OF_CELLS_Y 47
-/* +80: placeholder for cells which are rendered by the game;
- for example diamond + arrow = falling diamond */
-#define GD_NUM_OF_CELLS (GD_NUM_OF_CELLS_X*GD_NUM_OF_CELLS_Y+80)
+// +80: placeholder for cells which are rendered by the game;
+// for example diamond + arrow = falling diamond
+#define GD_NUM_OF_CELLS (GD_NUM_OF_CELLS_X * GD_NUM_OF_CELLS_Y + 80)
-/* maximum replay size (maximum seconds x game cycles per second) */
-#define MAX_REPLAY_LEN (10000 * FRAMES_PER_SECOND / 8)
+// maximum replay size (maximum seconds x game cycles per second)
+#define MAX_REPLAY_LEN (10000 * FRAMES_PER_SECOND / 8)
extern const GdColor gd_flash_color;
extern const GdColor gd_select_color;
enum _element_property
{
- E_P_SLOPED_LEFT, /* stones and diamonds roll down to left on this */
- E_P_SLOPED_RIGHT, /* stones and diamonds roll down to right on this */
+ E_P_SLOPED_LEFT, // stones and diamonds roll down to left on this
+ E_P_SLOPED_RIGHT, // stones and diamonds roll down to right on this
E_P_SLOPED_UP,
E_P_SLOPED_DOWN,
- E_P_BLADDER_SLOPED, /* element act sloped also for the bladder */
-
- E_P_AMOEBA_CONSUMES, /* amoeba can eat this */
- E_P_DIRT, /* it is dirt, or something similar (dirt2 or sloped dirt) */
- E_P_BLOWS_UP_FLIES, /* flies blow up, if they touch this */
- E_P_EXPLODES_BY_HIT, /* explodes if hit by a stone */
-
- E_P_EXPLOSION, /* set for every stage of every explosion. */
- E_P_EXPLOSION_FIRST_STAGE, /* set for first stage of every explosion.
- helps slower/faster explosions changing */
-
- E_P_NON_EXPLODABLE, /* selfexplaining */
- E_P_CCW, /* this creature has a default counterclockwise
- rotation (for example, o_fire_1) */
- E_P_CAN_BE_HAMMERED, /* can be broken by pneumatic hammer */
- E_P_VISUAL_EFFECT, /* if the element can use a visual effect.
- used to check consistency of the code */
- E_P_PLAYER, /* easier to find out if it is a player element */
- E_P_MOVED_BY_CONVEYOR_TOP, /* can be moved by conveyor belt */
- E_P_MOVED_BY_CONVEYOR_BOTTOM, /* can be moved UNDER the conveyor belt */
-
- E_P_COLLECTIBLE, /* can be collected */
+ E_P_BLADDER_SLOPED, // element act sloped also for the bladder
+
+ E_P_AMOEBA_CONSUMES, // amoeba can eat this
+ E_P_DIRT, // it is dirt, or something similar (dirt2 or sloped dirt)
+ E_P_BLOWS_UP_FLIES, // flies blow up, if they touch this
+ E_P_EXPLODES_BY_HIT, // explodes if hit by a stone
+
+ E_P_EXPLOSION, // set for every stage of every explosion.
+ E_P_EXPLOSION_FIRST_STAGE, // set for first stage of every explosion.
+ // helps slower/faster explosions changing
+
+ E_P_NON_EXPLODABLE, // selfexplaining
+ E_P_CCW, // this creature has a default counterclockwise
+ // rotation (for example, o_fire_1)
+ E_P_CAN_BE_HAMMERED, // can be broken by pneumatic hammer
+ E_P_VISUAL_EFFECT, // if the element can use a visual effect.
+ // used to check consistency of the code
+ E_P_PLAYER, // easier to find out if it is a player element
+ E_P_MOVED_BY_CONVEYOR_TOP, // can be moved by conveyor belt
+ E_P_MOVED_BY_CONVEYOR_BOTTOM, // can be moved UNDER the conveyor belt
+
+ E_P_DIGGABLE, // can be digged
+ E_P_COLLECTIBLE, // can be collected
+ E_P_PUSHABLE, // can be pushed
+ E_P_CAN_MOVE, // can move
+ E_P_CAN_FALL, // can fall
};
-/* properties */
+// properties
#define P_SLOPED_LEFT (1 << E_P_SLOPED_LEFT)
#define P_SLOPED_RIGHT (1 << E_P_SLOPED_RIGHT)
#define P_SLOPED_UP (1 << E_P_SLOPED_UP)
#define P_SLOPED_DOWN (1 << E_P_SLOPED_DOWN)
-/* flag to say "any direction" */
+// flag to say "any direction"
#define P_SLOPED (P_SLOPED_LEFT | \
P_SLOPED_RIGHT | \
P_SLOPED_UP | \
#define P_MOVED_BY_CONVEYOR_TOP (1 << E_P_MOVED_BY_CONVEYOR_TOP)
#define P_MOVED_BY_CONVEYOR_BOTTOM (1 << E_P_MOVED_BY_CONVEYOR_BOTTOM)
+#define P_DIGGABLE (1 << E_P_DIGGABLE)
#define P_COLLECTIBLE (1 << E_P_COLLECTIBLE)
+#define P_PUSHABLE (1 << E_P_PUSHABLE)
+#define P_CAN_MOVE (1 << E_P_CAN_MOVE)
+#define P_CAN_FALL (1 << E_P_CAN_FALL)
-/* These are states of the magic wall. */
+// These are states of the magic wall.
typedef enum _magic_wall_state
{
- GD_MW_DORMANT, /* Starting with this. */
- GD_MW_ACTIVE, /* Boulder or diamond dropped into. */
- GD_MW_EXPIRED /* Turned off after magic_wall_milling_time. */
+ GD_MW_DORMANT, // Starting with this.
+ GD_MW_ACTIVE, // Boulder or diamond dropped into.
+ GD_MW_EXPIRED // Turned off after magic_wall_milling_time.
} GdMagicWallState;
-/* These are states of Player. */
+// These are states of Player.
typedef enum _player_state
{
- GD_PL_NOT_YET, /* Not yet living. Beginning of cave time. */
- GD_PL_LIVING, /* Ok. */
- GD_PL_TIMEOUT, /* Time is up */
- GD_PL_DIED, /* Died. */
- GD_PL_EXITED /* Exited the cave, proceed to next one */
+ GD_PL_NOT_YET, // Not yet living. Beginning of cave time.
+ GD_PL_LIVING, // Ok.
+ GD_PL_TIMEOUT, // Time is up
+ GD_PL_DIED, // Died.
+ GD_PL_EXITED // Exited the cave, proceed to next one
} GdPlayerState;
-/* States of amoeba */
+// States of amoeba
typedef enum _amoeba_state
{
- GD_AM_SLEEPING, /* sleeping - not yet let out. */
- GD_AM_AWAKE, /* living, growing */
- GD_AM_TOO_BIG, /* grown too big, will convert to stones */
- GD_AM_ENCLOSED, /* enclosed, will convert to diamonds */
+ GD_AM_SLEEPING, // sleeping - not yet let out.
+ GD_AM_AWAKE, // living, growing
+ GD_AM_TOO_BIG, // grown too big, will convert to stones
+ GD_AM_ENCLOSED, // enclosed, will convert to diamonds
} GdAmoebaState;
typedef enum _direction
{
- /* not moving */
+ // not moving
GD_MV_STILL = 0,
GD_MV_THIS = 0,
- /* directions */
+ // directions
GD_MV_UP = 1,
GD_MV_UP_RIGHT = 2,
GD_MV_RIGHT = 3,
GD_MV_LEFT = 7,
GD_MV_UP_LEFT = 8,
- /* to be able to type GD_MV_TWICE + GD_MV_DOWN, for example */
+ // to be able to type GD_MV_TWICE + GD_MV_DOWN, for example
GD_MV_TWICE = 8,
- /* directions * 2 */
+ // directions * 2
GD_MV_UP_2 = 9,
GD_MV_UP_RIGHT_2 = 10,
GD_MV_RIGHT_2 = 11,
};
-/* ELEMENTS DESCRIPTION */
+// ELEMENTS DESCRIPTION
typedef struct _elements
{
- GdElement element; /* element number. for example O_DIRT */
- char *name; /* name in editor, for example "Dirt". some have
- different names than their real engine meaning! */
- unsigned int properties; /* engine properties, like P_SLOPED or P_EXPLODES */
- char *filename; /* name in bdcff file, like "DIRT" */
- char character; /* character representation in bdcff file, like '.' */
- int image; /* image in editor (index in cells.png) */
- int image_simple; /* image for simple view in editor, and for combo box (index in cells.png) */
- int image_game; /* image for game. negative if animated */
- int ckdelay; /* ckdelay ratio - how much time required for a c64 to
- process this element - in microseconds. */
-
- char *lowercase_name; /* lowercase of translated name. for editor; generated inside the game. */
- char character_new; /* character given automatically for elements which
- don't have one defined in original bdcff description */
+ GdElement element; // element number. for example O_DIRT
+ char *name; // name in editor, for example "Dirt". some have
+ // different names than their real engine meaning!
+ unsigned int properties; // engine properties, like P_SLOPED or P_EXPLODES
+ char *filename; // name in bdcff file, like "DIRT"
+ char character; // character representation in bdcff file, like '.'
+ int image; // image in editor (index in cells.png)
+ int image_simple; // image in editor (index in cells.png) (simple view / combo box)
+ int image_game; // image for game. negative if animated
+ int ckdelay; // ckdelay ratio - how much time required for a c64 to
+ // process this element - in microseconds.
+
+ char *lowercase_name; // lowercase of translated name. for editor;
+ // generated inside the game.
+ char character_new; // character given automatically for elements which
+ // don't have one defined in original bdcff description
} GdElements;
-typedef char GdString[128];
+typedef char GdString[MAX_LINE_LEN];
typedef struct _highscore
{
unsigned int len;
} GdReplayMovements;
-/* maximum seed value for the cave random generator. should be smaller than a signed int. */
+// maximum seed value for the cave random generator. should be smaller than a signed int.
#define GD_CAVE_SEED_MAX (1 << 30)
typedef struct _gd_cave_replay
{
- int level; /* replay for level n */
- unsigned int seed; /* seed the cave is to be rendered with */
- boolean saved; /* also store it in the saved bdcff */
- GdString recorded_with; /* recorded with - application name and version */
+ int level; // replay for level n
+ unsigned int seed; // seed the cave is to be rendered with
+ boolean saved; // also store it in the saved bdcff
+ GdString recorded_with; // recorded with - application name and version
- GdString player_name; /* who played this */
- GdString date; /* when played */
- char *comment; /* some comments from the player */
+ GdString player_name; // who played this
+ GdString date; // when played
+ char *comment; // some comments from the player
- int score; /* score collected */
- int duration; /* number of seconds played */
- boolean success; /* successful playing of cave? */
- unsigned int checksum; /* checksum of the rendered cave. */
+ int score; // score collected
+ int duration; // number of seconds played
+ boolean success; // successful playing of cave?
+ unsigned int checksum; // checksum of the rendered cave.
boolean wrong_checksum;
GdReplayMovements *movements;
int rand_seed_1, rand_seed_2;
} GdC64RandomGenerator;
-/*
- Structure holding all data belonging to a cave.
-*/
+// ----------------------------------------------------------------------------
+// Structure holding all data belonging to a cave.
+// ----------------------------------------------------------------------------
#define GD_HIGHSCORE_NUM 20
typedef struct _gd_cave
{
- /* Defined by the editor. public data :) */
- GdString name; /* Name of cave */
- GdString description; /* Some words about the cave */
- GdString author; /* Author */
- GdString difficulty; /* difficulty of the game, for info purposes */
- GdString www; /* link to author's webpage */
- GdString date; /* date of creation */
- char *story; /* story for the cave - will be shown when the cave is played. */
- char *remark; /* some note */
-
- GdString charset; /* these are not used by gdash */
+ // Defined by the editor. public data :)
+ GdString name; // name of cave
+ GdString description; // some words about the cave
+ GdString author; // author
+ GdString difficulty; // difficulty of the game, for info purposes
+ GdString www; // link to author's webpage
+ GdString date; // date of creation
+ char *story; // story for the cave - will be shown when cave is played.
+ char *remark; // some note
+
+ GdString charset; // these are not used by gdash
GdString fontset;
- /* and this one the highscores */
+ // and this one the highscores
GdHighScore highscore[GD_HIGHSCORE_NUM];
- HashTable *tags; /* stores read-but-not-understood strings from bdcff, so we can save them later. */
+ HashTable *tags; // stores read-but-not-understood strings from bdcff,
+ // so we can save them later.
- GdElement **map; /* pointer to data for map, non-null if has a map */
+ GdElement **map; // pointer to data for map, non-null if has a map
List *objects;
List *replays;
- boolean intermission; /* is this cave an intermission? */
- boolean intermission_instantlife; /* one life extra, if the intermission is reached */
- boolean intermission_rewardlife; /* one life extra, if the intermission is successfully finished */
- boolean selectable; /* is this selectable as an initial cave for a game? */
- boolean diagonal_movements; /* are diagonal movements allowed? */
- GdElement snap_element; /* snapping (press fire+move) usually leaves space behind, but can be other */
- boolean short_explosions; /* in >=1stb, diamond and creature explosions were of 5 stages */
-
- GdScheduling scheduling; /* scheduling type; see above */
- boolean pal_timing; /* use faster seconds */
-
- boolean active_is_first_found; /* active player is the uppermost. */
- boolean lineshift; /* true is line shifting emulation, false is perfect borders emulation */
- boolean border_scan_first_and_last; /* if true, scans the first and last line of the border. false for plck */
- boolean wraparound_objects; /* if this is true, object drawing (cave rendering) will wraparound as well. */
+ boolean intermission; // is this cave an intermission?
+ boolean intermission_instantlife; // one life extra, if the intermission is reached
+ boolean intermission_rewardlife; // one life extra, if the intermission is finished
+ boolean selectable; // is this selectable as an initial cave for a game?
+ boolean diagonal_movements; // are diagonal movements allowed?
+ GdElement snap_element; // snapping (press fire+move) usually leaves space behind,
+ // but can be other
+ boolean short_explosions; // in >= 1stb, diamond/creature explosions were of 5 stages
+
+ GdScheduling scheduling; // scheduling type; see above
+ boolean pal_timing; // use faster seconds
+
+ boolean active_is_first_found; // active player is the uppermost.
+ boolean lineshift; // true is line shifting emulation,
+ // false is perfect borders emulation
+ boolean border_scan_first_and_last; // if true, scans the first and last line of the border.
+ // false for plck
+ boolean wraparound_objects; // if this is true, object drawing (cave rendering)
+ // will wraparound as well.
GdElement initial_fill;
GdElement initial_border;
- GdElement random_fill[4]; /* Random fill elements. */
- int random_fill_probability[4]; /* Random fill, probability of each element. */
+ GdElement random_fill[4]; // Random fill elements.
+ int random_fill_probability[4]; // Random fill, probability of each element.
- int level_rand[5]; /* Random seed. */
- int level_diamonds[5]; /* Must collect diamonds, on level x */
- int level_speed[5]; /* Time between game cycles in ms */
- int level_ckdelay[5]; /* Timing in original game units */
- int level_time[5]; /* Available time, per level */
- int level_timevalue[5]; /* points for each second remaining, when exiting level */
+ int level_rand[5]; // Random seed.
+ int level_diamonds[5]; // Must collect diamonds, on level x
+ int level_speed[5]; // Time between game cycles in ms
+ int level_ckdelay[5]; // Timing in original game units
+ int level_time[5]; // Available time, per level
+ int level_timevalue[5]; // points for each second remaining, when exiting level
- int max_time; /* the maximum time in seconds. if above, it overflows */
+ int max_time; // the maximum time in seconds. if above, it overflows
- int w, h; /* Sizes of cave, width and height. */
- int x1,y1,x2,y2; /* Visible part of the cave */
- GdColor colorb; /* border color */
- GdColor color0, color1, color2, color3, color4, color5; /* c64-style colors; 4 and 5 are amoeba and slime. */
+ int w, h; // Sizes of cave, width and height.
+ int x1,y1,x2,y2; // Visible part of the cave
+ GdColor colorb; // border color
+ GdColor color0, color1, color2, color3, color4, color5; // c64-style colors;
+ // color 4 and 5 are amoeba and slime.
- int diamond_value; /* Score for a diamond. */
- int extra_diamond_value; /* Score for a diamond, when gate is open. */
+ int diamond_value; // Score for a diamond.
+ int extra_diamond_value; // Score for a diamond, when gate is open.
boolean stone_sound;
boolean nut_sound;
boolean bladder_spender_sound;
boolean bladder_convert_sound;
- int level_magic_wall_time[5]; /* magic wall 'on' state for each level (seconds) */
- boolean magic_wall_stops_amoeba; /* Turning on magic wall changes amoeba to diamonds. Original BD: yes, constkit: no */
- boolean magic_timer_wait_for_hatching; /* magic wall timer does not start before player's birth */
- boolean magic_wall_sound; /* magic wall has sound */
-
- int level_amoeba_time[5]; /* amoeba time for each level */
- int amoeba_growth_prob; /* Amoeba slow growth probability */
- int amoeba_fast_growth_prob; /* Amoeba fast growth probability */
- int level_amoeba_threshold[5]; /* amoeba turns to stones; if count is bigger than this (number of cells) */
- GdElement amoeba_enclosed_effect; /* an enclosed amoeba converts to this element */
- GdElement amoeba_too_big_effect; /* an amoeba grown too big converts to this element */
-
- int level_amoeba_2_time[5]; /* amoeba time for each level */
- int amoeba_2_growth_prob; /* Amoeba slow growth probability */
- int amoeba_2_fast_growth_prob; /* Amoeba fast growth probability */
- int level_amoeba_2_threshold[5]; /* amoeba turns to stones; if count is bigger than this (number of cells) */
- GdElement amoeba_2_enclosed_effect; /* an enclosed amoeba converts to this element */
- GdElement amoeba_2_too_big_effect; /* an amoeba grown too big converts to this element */
- boolean amoeba_2_explodes_by_amoeba; /* amoeba 2 will explode if touched by amoeba1 */
- GdElement amoeba_2_explosion_effect; /* amoeba 2 explosion ends in ... */
- GdElement amoeba_2_looks_like; /* an amoeba 2 looks like this element */
-
- boolean amoeba_timer_started_immediately; /* FALSE: amoeba will start life at the first possibility of growing. */
- boolean amoeba_timer_wait_for_hatching; /* amoeba timer does not start before player's birth */
- boolean amoeba_sound; /* if the living amoeba has sound. */
-
- GdElement acid_eats_this; /* acid eats this element */
- int acid_spread_ratio; /* Probability of acid blowing up, each frame */
- boolean acid_spread_sound; /* acid has sound */
- GdElement acid_turns_to; /* whether acid converts to explosion on spreading or other */
-
- GdElement nut_turns_to_when_crushed; /* when a nut is hit by a stone, it converts to this element */
-
- int level_slime_permeability[5]; /* true random slime */
- int level_slime_permeability_c64[5]; /* Appearing in bd 2 */
- int level_slime_seed_c64[5]; /* predictable slime random seed */
- boolean slime_predictable; /* predictable random start for slime. yes for plck. */
- GdElement slime_eats_1, slime_converts_1; /* slime eats element x and converts to element x; for example diamond -> falling diamond */
- GdElement slime_eats_2, slime_converts_2; /* this is usually stone -> stone_f */
- GdElement slime_eats_3, slime_converts_3; /* this is usually nut -> nut_f */
- boolean slime_sound; /* slime has sound */
-
- boolean lava_sound; /* elements sinking in lava have sound */
-
- int level_hatching_delay_frame[5]; /* Scan frames before Player's birth. */
- int level_hatching_delay_time[5]; /* Scan frames before Player's birth. */
-
- int level_bonus_time[5]; /* bonus time for clock collected. */
- int level_penalty_time[5]; /* Time penalty when voodoo destroyed. */
- boolean voodoo_collects_diamonds; /* Voodoo can collect diamonds */
- boolean voodoo_dies_by_stone; /* Voodoo can be killed by a falling stone */
- boolean voodoo_disappear_in_explosion; /* Voodoo can be destroyed by and explosion */
- boolean voodoo_any_hurt_kills_player; /* If any of the voodoos are hurt in any way, the player is killed. */
-
- boolean water_does_not_flow_down; /* if true, water will not grow downwards, only in other directions. */
- boolean water_sound; /* water has sound */
-
- boolean bladder_sound; /* bladder moving and pushing has sound */
- GdElement bladder_converts_by; /* bladder converts to clock by touching this element */
-
- int biter_delay_frame; /* frame count biters do move */
- GdElement biter_eat; /* biters eat this */
- boolean biter_sound; /* biters have sound */
-
- boolean expanding_wall_changed; /* expanding wall direction is changed */
-
- int replicator_delay_frame; /* replicator delay in frames (number of frames to wait between creating a new element) */
- boolean replicators_active; /* replicators are active. */
- boolean replicator_sound; /* when replicating an element, play sound or not. */
+ int level_magic_wall_time[5]; // magic wall 'on' state for each level (seconds)
+ boolean magic_wall_stops_amoeba; // Turning on magic wall changes amoeba to diamonds.
+ // Original BD: yes, constkit: no
+ boolean magic_wall_breakscan; // Currently this setting enabled will turn the amoeba to
+ // an enclosed state. To implement buggy BD1 behaviour.
+ boolean magic_timer_zero_is_infinite; // magic wall timer 0 is interpreted as infinite
+ boolean magic_timer_wait_for_hatching;// magic wall timer does not start before player's birth
+ boolean magic_wall_sound; // magic wall has sound
+
+ int level_amoeba_time[5]; // amoeba time for each level
+ int amoeba_growth_prob; // Amoeba slow growth probability
+ int amoeba_fast_growth_prob; // Amoeba fast growth probability
+ int level_amoeba_threshold[5]; // amoeba turns to stones; if count is bigger than this
+ // (number of cells)
+ GdElement amoeba_enclosed_effect; // an enclosed amoeba converts to this element
+ GdElement amoeba_too_big_effect; // an amoeba grown too big converts to this element
+
+ int level_amoeba_2_time[5]; // amoeba time for each level
+ int amoeba_2_growth_prob; // Amoeba slow growth probability
+ int amoeba_2_fast_growth_prob; // Amoeba fast growth probability
+ int level_amoeba_2_threshold[5]; // amoeba turns to stones; if count is bigger than this
+ // (number of cells)
+ GdElement amoeba_2_enclosed_effect; // an enclosed amoeba converts to this element
+ GdElement amoeba_2_too_big_effect; // an amoeba grown too big converts to this element
+ boolean amoeba_2_explodes_by_amoeba; // amoeba 2 will explode if touched by amoeba1
+ GdElement amoeba_2_explosion_effect; // amoeba 2 explosion ends in ...
+ GdElement amoeba_2_looks_like; // an amoeba 2 looks like this element
+
+ boolean amoeba_timer_started_immediately; // FALSE: amoeba will start life at the first
+ // possibility of growing.
+ boolean amoeba_timer_wait_for_hatching; // amoeba timer does not start before player's birth
+ boolean amoeba_sound; // if the living amoeba has sound.
+
+ GdElement acid_eats_this; // acid eats this element
+ int acid_spread_ratio; // Probability of acid blowing up, each frame
+ boolean acid_spread_sound; // acid has sound
+ GdElement acid_turns_to; // whether acid converts to explosion on spreading or other
+
+ GdElement nut_turns_to_when_crushed; // when nut is hit by stone, it converts to this element
+
+ int level_slime_permeability[5]; // true random slime
+ int level_slime_permeability_c64[5]; // Appearing in bd 2
+ int level_slime_seed_c64[5]; // predictable slime random seed
+ boolean slime_predictable; // predictable random start for slime. yes for plck.
+ boolean slime_correct_random; // correct random number generator for rendered caves
+ GdElement slime_eats_1, slime_converts_1; // slime eats element x and converts to element x;
+ // for example diamond -> falling diamond
+ GdElement slime_eats_2, slime_converts_2; // this is usually stone -> stone_f
+ GdElement slime_eats_3, slime_converts_3; // this is usually nut -> nut_f
+ boolean slime_sound; // slime has sound
+
+ boolean lava_sound; // elements sinking in lava have sound
+
+ int level_hatching_delay_frame[5]; // Scan frames before Player's birth.
+ int level_hatching_delay_time[5]; // Scan frames before Player's birth.
+
+ int level_bonus_time[5]; // bonus time for clock collected.
+ int level_penalty_time[5]; // Time penalty when voodoo destroyed.
+ boolean voodoo_collects_diamonds; // Voodoo can collect diamonds
+ boolean voodoo_dies_by_stone; // Voodoo can be killed by a falling stone
+ boolean voodoo_disappear_in_explosion;// Voodoo can be destroyed by and explosion
+ boolean voodoo_any_hurt_kills_player; // If any voodoo hurt in any way, player is killed.
+
+ boolean water_does_not_flow_down; // if true, water will not grow downwards,
+ // only in other directions.
+ boolean water_sound; // water has sound
+
+ boolean bladder_sound; // bladder moving and pushing has sound
+ GdElement bladder_converts_by; // bladder converts to clock by touching this element
+
+ int biter_delay_frame; // frame count biters do move
+ GdElement biter_eat; // biters eat this
+ boolean biter_sound; // biters have sound
+
+ boolean expanding_wall_changed; // expanding wall direction is changed
+
+ int replicator_delay_frame; // replicator delay in frames (number of frames
+ // to wait between creating a new element)
+ boolean replicators_active; // replicators are active.
+ boolean replicator_sound; // when replicating an element, play sound or not.
boolean conveyor_belts_active;
boolean conveyor_belts_direction_changed;
- /* effects */
- GdElement explosion_effect; /* explosion converts to this element after its last stage. diego effect. */
- GdElement diamond_birth_effect; /* a diamond birth converts to this element after its last stage. diego effect. */
- GdElement bomb_explosion_effect; /* bombs explode to this element. diego effect (almost). */
- GdElement nitro_explosion_effect; /* nitros explode to this */
-
- GdElement firefly_explode_to; /* fireflies explode to this when hit by a stone */
- GdElement alt_firefly_explode_to; /* alternative fireflies explode to this when hit by a stone */
- GdElement butterfly_explode_to; /* butterflies explode to this when hit by a stone */
- GdElement alt_butterfly_explode_to; /* alternative butterflies explode to this when hit by a stone */
- GdElement stonefly_explode_to; /* stoneflies explode to this when hit by a stone */
- GdElement dragonfly_explode_to; /* dragonflies explode to this when hit by a stone */
-
- GdElement stone_falling_effect; /* a falling stone converts to this element. diego effect. */
- GdElement diamond_falling_effect; /* a falling diamond converts to this element. diego effect. */
- GdElement stone_bouncing_effect; /* a bouncing stone converts to this element. diego effect. */
- GdElement diamond_bouncing_effect; /* a bouncing diamond converts to this element. diego effect. */
-
- GdElement expanding_wall_looks_like; /* an expanding wall looks like this element. diego effect. */
- GdElement dirt_looks_like; /* dirt looks like this element. diego effect. */
-
- GdElement magic_stone_to; /* magic wall converts falling stone to */
- GdElement magic_diamond_to; /* magic wall converts falling diamond to */
- GdElement magic_mega_stone_to; /* magic wall converts a falling mega stone to */
- GdElement magic_nitro_pack_to; /* magic wall converts a falling nitro pack to */
- GdElement magic_nut_to; /* magic wall converts a falling nut to */
- GdElement magic_flying_stone_to; /* flying stones are converted to */
- GdElement magic_flying_diamond_to; /* flying diamonds are converted to */
-
- int pushing_stone_prob; /* probability of pushing stone */
- int pushing_stone_prob_sweet; /* probability of pushing, after eating sweet */
- boolean mega_stones_pushable_with_sweet; /* mega stones may be pushed with sweet */
-
- boolean creatures_backwards; /* creatures changed direction */
- boolean creatures_direction_auto_change_on_start; /* the change occurs also at the start signal */
- int creatures_direction_auto_change_time; /* creatures automatically change direction every x seconds */
- boolean creature_direction_auto_change_sound; /* automatically changing creature direction may have the sound of the creature dir switch */
-
- int skeletons_needed_for_pot; /* how many skeletons to be collected, to use a pot */
- int skeletons_worth_diamonds; /* for crazy dream 7 compatibility: collecting skeletons might open the cave door. */
+ // effects
+ GdElement explosion_effect; // explosion converts to this element after its last stage.
+ // diego effect.
+ GdElement diamond_birth_effect; // a diamond birth converts to this element after its last
+ // stage. diego effect.
+ GdElement bomb_explosion_effect; // bombs explode to this element. diego effect (almost).
+ GdElement nitro_explosion_effect; // nitros explode to this
+
+ GdElement firefly_explode_to; // fireflies explode to this when hit by stone
+ GdElement alt_firefly_explode_to; // alternative fireflies explode to this when hit by stone
+ GdElement butterfly_explode_to; // butterflies explode to this when hit by stone
+ GdElement alt_butterfly_explode_to; // alternative butterflies explode to this when hit by stone
+ GdElement stonefly_explode_to; // stoneflies explode to this when hit by stone
+ GdElement dragonfly_explode_to; // dragonflies explode to this when hit by stone
+
+ GdElement stone_falling_effect; // falling stone converts to this element. diego effect.
+ GdElement diamond_falling_effect; // falling diamond converts to this element. diego effect.
+ GdElement stone_bouncing_effect; // bouncing stone converts to this element. diego effect.
+ GdElement diamond_bouncing_effect; // bouncing diamond converts to this element. diego effect.
+
+ GdElement expanding_wall_looks_like; // an expanding wall looks like this element. diego effect.
+ GdElement dirt_looks_like; // dirt looks like this element. diego effect.
+
+ GdElement magic_stone_to; // magic wall converts falling stone to
+ GdElement magic_diamond_to; // magic wall converts falling diamond to
+ GdElement magic_mega_stone_to; // magic wall converts a falling mega stone to
+ GdElement magic_nitro_pack_to; // magic wall converts a falling nitro pack to
+ GdElement magic_nut_to; // magic wall converts a falling nut to
+ GdElement magic_flying_stone_to; // flying stones are converted to
+ GdElement magic_flying_diamond_to; // flying diamonds are converted to
+
+ int pushing_stone_prob; // probability of pushing stone
+ int pushing_stone_prob_sweet; // probability of pushing, after eating sweet
+ boolean mega_stones_pushable_with_sweet; // mega stones may be pushed with sweet
+
+ boolean creatures_backwards; // creatures changed direction
+ boolean creatures_direction_auto_change_on_start; // the change occurs also at the start signal
+ int creatures_direction_auto_change_time; // creatures automatically change direction every x
+ // seconds
+ boolean creature_direction_auto_change_sound; // automatically changing creature direction may
+ // have the sound of the creature dir switch
+
+ int skeletons_needed_for_pot; // how many skeletons to be collected, to use a pot
+ int skeletons_worth_diamonds; // for crazy dream 7 compatibility: collecting skeletons
+ // might open the cave door.
GdDirection gravity;
int gravity_change_time;
boolean gravity_change_sound;
- boolean gravity_affects_all; /* if true, gravity also affects falling wall, bladder and waiting stones */
- boolean gravity_switch_active; /* true if gravity switch is activated, and can be used. */
+ boolean gravity_affects_all; // if true, gravity also affects falling wall, bladder
+ // and waiting stones
+ boolean gravity_switch_active; // true if gravity switch is activated, and can be used.
boolean hammered_walls_reappear;
int pneumatic_hammer_frame;
int hammered_wall_reappear_frame;
boolean pneumatic_hammer_sound;
- /* internal variables, used during the game. private data :) */
+ boolean infinite_rockets; // if true, the player which got a rocket launcher will be
+ // able to launch an infinite number of rockets
+
+ // internal variables, used during the game. private data :)
- /* returns range corrected x/y position (points to perfect or line shifting get function) */
+ // returns range corrected x/y position (points to perfect or line shifting get function)
int (*getx) (const struct _gd_cave*, int x, int y);
int (*gety) (const struct _gd_cave*, int x, int y);
- /* returns pointer to element at x, y (points to perfect border or a line shifting get function) */
+ // returns pointer to element at x, y (points to perfect border or a line shifting get function)
GdElement* (*getp) (const struct _gd_cave*, int x, int y);
- boolean hatched; /* hatching has happened. (timers may run, ...) */
- boolean gate_open; /* self-explaining */
- unsigned int render_seed; /* the seed value, which was used to render the cave, is saved here. will be used by record&playback */
- GdRand *random; /* random number generator of rendered cave */
- int rendered; /* if not zero, rendered at level x */
- int timing_factor; /* number of "milliseconds" in each second :) 1000 for ntsc, 1200 for pal. */
- 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. */
- int **hammered_reappear; /* integer map of cave; if non-zero, a brick wall will appear there */
-
- int speed; /* Time between game cycles in ms */
- int c64_timing; /* a ckdelay value for the level this cave is rendered for */
- int ckdelay; /* ckdelay value for the current iteration */
- int ckdelay_extra_for_animation; /* bd1 and similar engines had animation bits in cave data, to set which elements to animate (firefly, butterfly, amoeba).
- animating an element also caused some delay each frame; according to my measurements, around 2.6 ms/element. */
-
- int frame; /* XXX */
+ boolean hatched; // hatching has happened. (timers may run, ...)
+ boolean gate_open; // self-explaining
+ unsigned int render_seed; // the seed value, which was used to render the cave,
+ // is saved here. will be used by record&playback
+ GdRand *random; // random number generator of rendered cave
+ int rendered; // if not zero, rendered at level x
+ int timing_factor; // number of "milliseconds" in each second :)
+ // 1000 for ntsc, 1200 for pal.
+ 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.
+ int **hammered_reappear; // integer map of cave; if non-zero, a brick wall will
+ // appear there
+
+ int speed; // Time between game cycles in ms
+ int c64_timing; // a ckdelay value for the level this cave is rendered for
+ int ckdelay; // ckdelay value for the current iteration
+ int ckdelay_extra_for_animation; // bd1 and similar engines had animation bits in cave data,
+ // to set which elements to animate (firefly, butterfly,
+ // amoeba).
+ // animating an element also caused some delay each frame;
+ // according to my measurements, around 2.6 ms/element.
+
+ int frame; // XXX
int hatching_delay_frame;
int hatching_delay_time;
- int time_bonus; /* bonus time for clock collected. */
- int time_penalty; /* Time penalty when voodoo destroyed. */
- int time; /* milliseconds remaining to finish cave */
- int timevalue; /* points for remaining seconds - for current level */
- int diamonds_needed; /* diamonds needed to open outbox */
- int diamonds_collected; /* diamonds collected */
- int skeletons_collected; /* number of skeletons collected */
- int gate_open_flash; /* flashing of screen when gate opens */
- int score; /* Score got this frame. */
- int amoeba_time; /* Amoeba growing slow (low probability, default 3%) for milliseconds. After that, fast growth default (25%) */
- int amoeba_2_time; /* Amoeba growing slow (low probability, default 3%) for milliseconds. After that, fast growth default (25%) */
- int amoeba_max_count; /* selected amoeba 1 threshold for this level */
- int amoeba_2_max_count; /* selected amoeba 2 threshold for this level */
- GdAmoebaState amoeba_state; /* state of amoeba 1 */
- GdAmoebaState amoeba_2_state; /* state of amoeba 2 */
- int magic_wall_time; /* magic wall 'on' state for seconds */
- int slime_permeability; /* true random slime */
- int slime_permeability_c64; /* Appearing in bd 2 */
- GdMagicWallState magic_wall_state; /* State of magic wall */
- GdPlayerState player_state; /* Player state. not yet living, living, exited... */
- int player_seen_ago; /* player was seen this number of scans ago */
- boolean voodoo_touched; /* as its name says */
- boolean kill_player; /* Voodoo died, or used pressed escape to restart level. */
- boolean sweet_eaten; /* player ate sweet, he's strong. prob_sweet applies, and also able to push chasing stones */
- int player_x, player_y; /* Coordinates of player (for scrolling) */
- int px[16], py[16]; /* coordinates of player, for chasing stone */
- int key1, key2, key3; /* The player is holding this number of keys of each color */
- boolean diamond_key_collected; /* Key collected, so trapped diamonds convert to diamonds */
- boolean inbox_flash_toggle; /* negated every scan. helps drawing inboxes, and making players be born at different times. */
- GdDirection last_direction; /* last direction player moved. used by draw routines */
+ int time_bonus; // bonus time for clock collected.
+ int time_penalty; // Time penalty when voodoo destroyed.
+ int time; // milliseconds remaining to finish cave
+ int timevalue; // points for remaining seconds - for current level
+ int diamonds_needed; // diamonds needed to open outbox
+ int diamonds_collected; // diamonds collected
+ int skeletons_collected; // number of skeletons collected
+ int gate_open_flash; // flashing of screen when gate opens
+ int score; // Score got this frame.
+ int amoeba_time; // Amoeba growing slow (low probability, default 3%) for
+ // milliseconds. After that, fast growth default (25%)
+ int amoeba_2_time; // Amoeba growing slow (low probability, default 3%) for
+ // milliseconds. After that, fast growth default (25%)
+ int amoeba_max_count; // selected amoeba 1 threshold for this level
+ int amoeba_2_max_count; // selected amoeba 2 threshold for this level
+ GdAmoebaState amoeba_state; // state of amoeba 1
+ GdAmoebaState amoeba_2_state; // state of amoeba 2
+ boolean convert_amoeba_this_frame; // To implement BD1 buggy amoeba+magic wall behaviour.
+ int magic_wall_time; // magic wall 'on' state for seconds
+ int slime_permeability; // true random slime
+ int slime_permeability_c64; // Appearing in bd 2
+ GdMagicWallState magic_wall_state; // State of magic wall
+ GdPlayerState player_state; // Player state. not yet living, living, exited...
+ int player_seen_ago; // player was seen this number of scans ago
+ boolean voodoo_touched; // as its name says
+ boolean kill_player; // Voodoo died, or used pressed escape to restart level.
+ boolean sweet_eaten; // player ate sweet, he's strong. prob_sweet applies,
+ // and also able to push chasing stones
+ int player_x, player_y; // Coordinates of player (for scrolling)
+ int px[16], py[16]; // coordinates of player, for chasing stone
+ int key1, key2, key3; // The player is holding this number of keys of each color
+ boolean diamond_key_collected; // Key collected, so trapped diamonds convert to diamonds
+ boolean inbox_flash_toggle; // negated every scan. helps drawing inboxes, and making
+ // players be born at different times.
+ GdDirection last_direction; // last direction player moved. used by draw routines
GdDirection last_horizontal_direction;
- int biters_wait_frame; /* number of frames to wait until biters will move again */
- int replicators_wait_frame; /* number of frames to wait until replicators are activated again */
- int creatures_direction_will_change; /* creatures automatically change direction every x seconds */
- GdC64RandomGenerator c64_rand; /* used for predictable random generator during the game. */
-
- int gravity_will_change; /* gravity will change in this number of milliseconds */
- boolean gravity_disabled; /* when the player is stirring the pot, there is no gravity. */
- GdDirection gravity_next_direction; /* next direction when the gravity changes. will be set by the player "getting" a gravity switch */
- boolean got_pneumatic_hammer; /* true if the player has a pneumatic hammer */
- int pneumatic_hammer_active_delay; /* number of frames to wait, till pneumatic hammer will destroy the wall */
- GdSound sound1, sound2, sound3; /* sound set for 3 channels after each iteration */
+ int biters_wait_frame; // number of frames to wait until biters will move again
+ int replicators_wait_frame; // number of frames to wait until replicators are
+ // activated again
+ int creatures_direction_will_change; // creatures automatically change direction every x seconds
+ GdC64RandomGenerator c64_rand; // used for predictable random generator during the game.
+
+ int gravity_will_change; // gravity will change in this number of milliseconds
+ boolean gravity_disabled; // when player is stirring the pot, there is no gravity.
+ GdDirection gravity_next_direction; // next direction when the gravity changes.
+ // will be set by the player "getting" a gravity switch
+ boolean got_pneumatic_hammer; // true if the player has a pneumatic hammer
+ int pneumatic_hammer_active_delay; // number of frames to wait, till pneumatic hammer will
+ // destroy the wall
+ GdSound sound1, sound2, sound3; // sound set for 3 channels after each iteration
} GdCave;
#define CAVE_OFFSET(property) (STRUCT_OFFSET(GdCave, property))
-/* arrays for movements */
-/* also no1 and bd2 cave data import helpers; line direction coordinates */
+// arrays for movements
+// also no1 and bd2 cave data import helpers; line direction coordinates
extern const int gd_dx[], gd_dy[];
extern GdElement gd_char_to_element[];
GdElement gd_get_element_from_character(unsigned char character);
GdElement gd_get_element_from_string(const char *string);
-/* init cave engine */
+// init cave engine
void gd_cave_init(void);
-/* for cave tags hash table */
+// for cave tags hash table
int gd_str_case_equal(void *s1, void *s2);
unsigned int gd_str_case_hash(void *v);
-/* cave highscore functions */
+// cave highscore functions
int gd_highscore_compare(const void *a, const void *b);
boolean gd_is_highscore(GdHighScore *scores, int score);
int gd_add_highscore(GdHighScore *highscores, const char *name, int score);
void gd_clear_highscore(GdHighScore *hs);
boolean gd_has_highscore(GdHighScore *hs);
-/* cave creator and destructor functions */
+// cave creator and destructor functions
GdCave *gd_cave_new(void);
GdCave *gd_cave_new_from_cave(const GdCave *orig);
void gd_cave_copy(GdCave *dest, const GdCave *src);
void gd_cave_free(GdCave *cave);
-/* cave manipulation */
+// cave manipulation
void gd_cave_set_gdash_defaults(GdCave *cave);
void gd_cave_set_defaults_from_array(GdCave* cave, GdPropertyDefault *defaults);
void gd_cave_correct_visible_size(GdCave *cave);
+void gd_cave_set_random_colors(GdCave *cave, GdColorType type);
void gd_cave_auto_shrink(GdCave *cave);
void gd_cave_setup_for_game(GdCave *cave);
void gd_cave_count_diamonds(GdCave *cave);
-/* c64 random generator support for cave fill */
+// c64 random generator support for cave fill
unsigned int gd_c64_random(GdC64RandomGenerator *rand);
unsigned int gd_cave_c64_random(GdCave *);
void gd_c64_random_set_seed(GdC64RandomGenerator *rand, int seed1, int seed2);
void gd_cave_c64_random_set_seed(GdCave *cave, int seed1, int seed2);
+void gd_cave_set_random_c64_colors(GdCave *cave);
-/* support */
+// support
void *gd_cave_map_new_for_cave(const GdCave *cave, const int cell_size);
void *gd_cave_map_dup_size(const GdCave * cave, const void *map, const int cell_size);
#define gd_cave_map_new(CAVE, TYPE) ((TYPE **)gd_cave_map_new_for_cave((CAVE), sizeof(TYPE)))
void gd_cave_store_rc(GdCave * cave, int x, int y, const GdElement element, const void* order);
GdElement gd_cave_get_rc (const GdCave *cave, int x, int y);
-/* direction */
+// direction
const char *gd_direction_get_visible_name(GdDirection dir);
const char *gd_direction_get_filename(GdDirection dir);
GdDirection gd_direction_from_string(const char *str);
-/* scheduling */
+// scheduling
const char *gd_scheduling_get_visible_name(GdScheduling sched);
const char *gd_scheduling_get_filename(GdScheduling sched);
GdScheduling gd_scheduling_from_string(const char *str);
-/* game playing helpers */
+// game playing helpers
#define GD_REDRAW (1 << 10)
void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer,
boolean bonus_life_flash, int animcycle, boolean hate_invisible_outbox);
-/* function to copy a GdString */
+// function to copy a GdString
static inline char *gd_strcpy(GdString dest, const GdString src)
{
return strncpy(dest, src, sizeof(GdString));