gd_c64_random_set_seed(&cave->c64_rand, seed1, seed2);
}
+/*
+ select random colors for a given cave.
+ this function will select colors so that they should look somewhat nice; for example
+ brick walls won't be the darkest color, for example.
+*/
+static inline void swap(int *i1, int *i2)
+{
+ int t = *i1;
+
+ *i1 = *i2;
+ *i2 = t;
+}
+
void gd_cave_set_random_c64_colors(GdCave *cave)
{
const int bright_colors[] = { 1, 3, 7 };
cave->color5 = cave->color1;
}
+static void cave_set_random_indexed_colors(GdCave *cave, GdColor (*color_indexer_func) (int, int))
+{
+ int hue = gd_random_int_range(0, 15);
+ int hue_spread = gd_random_int_range(1, 6); // 1..5
+
+ // we only use 0..6, as saturation 15 is too bright (almost always white)
+ // also, saturation 0..1..2 is too dark. the color0=black is there for dark.
+ // so this is also 1..5. when hue spread is low, brightness spread is high
+ int bri_spread = 6 - hue_spread;
+ int bri1 = 8, bri2 = 8 - bri_spread, bri3 = 8 + bri_spread;
+
+ // there are 15 valid choices for hue, so we do a %15
+ int col1 = hue, col2 = (hue + hue_spread + 15) % 15, col3 = (hue - hue_spread + 15) % 15;
+
+ // this makes up a random color, and selects a color triad by hue+5 and hue+10.
+ // also creates a random saturation.
+ // color of brick is 8+sat, so it is always a bright color.
+ // another two are 8-sat and 8.
+ // order of colors is also changed randomly.
+ if (gd_random_boolean()) swap(&bri1, &bri2);
+
+ // we do not touch bri3 (8+sat), as it should be a bright color
+ if (gd_random_boolean()) swap(&col1, &col2);
+ if (gd_random_boolean()) swap(&col2, &col3);
+ if (gd_random_boolean()) swap(&col1, &col3);
+
+ cave->colorb = color_indexer_func(0, 0);
+ cave->color0 = color_indexer_func(0, 0);
+ cave->color1 = color_indexer_func(col1 + 1, bri1);
+ cave->color2 = color_indexer_func(col2 + 1, bri2);
+ cave->color3 = color_indexer_func(col3 + 1, bri3);
+ // amoeba and slime are different
+ // some green thing
+ cave->color4 = color_indexer_func(gd_random_int_range(11, 13), gd_random_int_range(6, 12));
+ // some blueish thing
+ cave->color5 = color_indexer_func(gd_random_int_range(7, 10), gd_random_int_range(0, 6));
+}
+
+static void gd_cave_set_random_atari_colors(GdCave *cave)
+{
+ cave_set_random_indexed_colors(cave, gd_atari_color_huesat);
+}
+
+static void gd_cave_set_random_c64dtv_colors(GdCave *cave)
+{
+ cave_set_random_indexed_colors(cave, gd_c64dtv_color_huesat);
+}
+
+static inline void swapd(double *i1, double *i2)
+{
+ double t = *i1;
+
+ *i1 = *i2;
+ *i2 = t;
+}
+
+static void gd_cave_set_random_rgb_colors(GdCave *cave)
+{
+ const double hue_max = 10.0 / 30.0;
+ // any hue allowed
+ double hue = gd_random_double();
+ // hue 360 degress=1. hue spread is min. 24 degrees, max 120 degrees (1/3)
+ double hue_spread = gd_random_double_range(2.0 / 30.0, hue_max);
+ double h1 = hue, h2 = hue + hue_spread, h3 = hue + 2 * hue_spread;
+ double v1, v2, v3;
+ double s1, s2, s3;
+
+ if (gd_random_boolean())
+ {
+ // when hue spread is low, brightness(saturation) spread is high
+ // this formula gives a number (x) between 0.1 and 0.4,
+ // which will be 0.5-x and 0.5+x, so the range is 0.1->0.9
+ double spread = 0.1 + 0.3 * (1 - hue_spread / hue_max);
+ v1 = 0.6; // brightness variation, too
+ v2 = 0.7;
+ v3 = 0.8;
+ s1 = 0.5; // saturation is different
+ s2 = 0.5 - spread;
+ s3 = 0.5 + spread;
+ }
+ else
+ {
+ // when hue spread is low, brightness(saturation) spread is high
+ // this formula gives a number (x) between 0.1 and 0.25,
+ // which will be 0.5+x and 0.5+2x, so the range is 0.5->0.9
+ double spread = 0.1 + 0.15 * (1 - hue_spread / hue_max);
+ v1 = 0.5; // brightness is different
+ v2 = 0.5 + spread;
+ v3 = 0.5 + 2 * spread;
+ s1 = 0.7; // saturation is same - a not fully saturated one
+ s2 = 0.8;
+ s3 = 0.9;
+ }
+
+ // randomly change values, but do not touch v3, as cave->color3 should be a bright color
+ if (gd_random_boolean()) swapd(&v1, &v2);
+
+ // randomly change hues and saturations
+ if (gd_random_boolean()) swapd(&h1, &h2);
+ if (gd_random_boolean()) swapd(&h2, &h3);
+ if (gd_random_boolean()) swapd(&h1, &h3);
+ if (gd_random_boolean()) swapd(&s1, &s2);
+ if (gd_random_boolean()) swapd(&s2, &s3);
+ if (gd_random_boolean()) swapd(&s1, &s3);
+
+ h1 = h1 * 360.0;
+ h2 = h2 * 360.0;
+ h3 = h3 * 360.0;
+
+ cave->colorb = gd_color_get_from_hsv(0, 0, 0);
+ cave->color0 = gd_color_get_from_hsv(0, 0, 0); // black for background
+ cave->color1 = gd_color_get_from_hsv(h1, s1, v1); // dirt
+ cave->color2 = gd_color_get_from_hsv(h2, s2, v2); // steel
+ cave->color3 = gd_color_get_from_hsv(h3, s3, v3); // brick
+ // green(120+-20) with the saturation and brightness of brick
+ cave->color4 = gd_color_get_from_hsv(gd_random_int_range(100, 140), s2, v2);
+ // blue(240+-20) with saturation and brightness of dirt
+ cave->color5 = gd_color_get_from_hsv(gd_random_int_range(220, 260), s1, v1);
+}
+
+void gd_cave_set_random_colors(GdCave *cave, GdColorType type)
+{
+ switch (type)
+ {
+ case GD_COLOR_TYPE_RGB:
+ gd_cave_set_random_rgb_colors(cave);
+ break;
+
+ case GD_COLOR_TYPE_C64:
+ gd_cave_set_random_c64_colors(cave);
+ break;
+
+ case GD_COLOR_TYPE_C64DTV:
+ gd_cave_set_random_c64dtv_colors(cave);
+ break;
+
+ case GD_COLOR_TYPE_ATARI:
+ gd_cave_set_random_atari_colors(cave);
+ break;
+
+ default:
+ break;
+ }
+}
+
/*
shrink cave
if last line or last row is just steel wall (or (invisible) outbox).
if a cell is changed, it is flagged with GD_REDRAW; the flag can be cleared
by the caller.
*/
-void gd_drawcave_game(const GdCave *cave, int **element_buffer, int **gfx_buffer,
+void gd_drawcave_game(const GdCave *cave,
+ int **element_buffer, int **last_element_buffer, int **gfx_buffer,
boolean bonus_life_flash, int animcycle, boolean hate_invisible_outbox)
{
static int player_blinking = 0;
static int player_tapping = 0;
- int elemmapping[O_MAX];
- int elemdrawing[O_MAX];
+ int elemmapping[O_MAX_ALL];
+ int elemdrawing[O_MAX_ALL];
int x, y, map, draw;
if (cave->last_direction)
}
}
- for (x = 0; x < O_MAX; x++)
+ for (x = 0; x < O_MAX_ALL; x++)
{
elemmapping[x] = x;
elemdrawing[x] = gd_elements[x].image_game;
draw = gd_elements[O_PLAYER].image_game;
}
}
+ else if (cave->last_direction == GD_MV_UP && use_bd_up_down_graphics())
+ {
+ map = O_PLAYER_UP;
+ draw = gd_elements[O_PLAYER_UP].image_game;
+ }
+ else if (cave->last_direction == GD_MV_DOWN && use_bd_up_down_graphics())
+ {
+ map = O_PLAYER_DOWN;
+ draw = gd_elements[O_PLAYER_DOWN].image_game;
+ }
else if (cave->last_horizontal_direction == GD_MV_LEFT)
{
map = O_PLAYER_LEFT;
// change only graphically
if (hate_invisible_outbox)
{
- elemmapping[O_PRE_INVIS_OUTBOX] = O_PRE_OUTBOX;
- elemmapping[O_INVIS_OUTBOX] = O_OUTBOX;
+ elemmapping[O_PRE_INVIS_OUTBOX] = elemmapping[O_PRE_OUTBOX];
+ elemmapping[O_INVIS_OUTBOX] = elemmapping[O_OUTBOX];
}
if (hate_invisible_outbox)
else
draw = elemdrawing[actual];
+ // draw special graphics if player is pushing something
+ if (use_bd_pushing_graphics() &&
+ (cave->last_direction == GD_MV_LEFT || cave->last_direction == GD_MV_RIGHT) &&
+ is_player(cave, x, y) && can_be_pushed_dir(cave, x, y, cave->last_direction))
+ {
+ // special check needed when smooth game element movements selected in setup menu:
+ // last element must either be player (before pushing) or pushable element (while pushing)
+ // (extra check needed to prevent pushing animation when moving towards pushable element)
+ if (!use_bd_smooth_movements() || last_element_buffer[y][x] != O_SPACE)
+ {
+ if (cave->last_direction == GD_MV_LEFT)
+ map = O_PLAYER_PUSH_LEFT;
+ else
+ map = O_PLAYER_PUSH_RIGHT;
+
+ if (cave->last_direction == GD_MV_LEFT)
+ draw = elemdrawing[O_PLAYER_PUSH_LEFT];
+ else
+ draw = elemdrawing[O_PLAYER_PUSH_RIGHT];
+ }
+ }
+
// if negative, animated.
if (draw < 0)
draw = -draw + animcycle;
gd_cave_adler_checksum_more(cave, &a, &b);
return (b << 16) + a;
}
+
+boolean gd_cave_has_levels(GdCave *cave)
+{
+ GdCave c = *cave;
+ int *cave_level_value[] =
+ {
+ c.level_diamonds,
+ c.level_speed,
+ c.level_ckdelay,
+ c.level_time,
+ c.level_magic_wall_time,
+ c.level_amoeba_time,
+ c.level_amoeba_threshold,
+ c.level_amoeba_2_time,
+ c.level_amoeba_2_threshold,
+ c.level_slime_permeability,
+ c.level_slime_permeability_c64,
+ c.level_slime_seed_c64,
+ c.level_hatching_delay_frame,
+ c.level_hatching_delay_time,
+ c.level_bonus_time,
+ c.level_penalty_time,
+
+ NULL
+ };
+ int i, j;
+
+ for (i = 0; cave_level_value[i] != NULL; i++)
+ for (j = 1; j < 5; j++)
+ if (cave_level_value[i][j] != cave_level_value[i][0])
+ return TRUE;
+
+ for (j = 1; j < 5; j++)
+ if (cave->level_rand[j] != j &&
+ cave->level_rand[j - 1] != j - 1 &&
+ cave->level_rand[j] != cave->level_rand[0])
+ return TRUE;
+
+ for (j = 1; j < 5; j++)
+ if (cave->level_timevalue[j] != j + 1 &&
+ cave->level_timevalue[j - 1] != j &&
+ cave->level_timevalue[j] != cave->level_timevalue[0])
+ return TRUE;
+
+ return FALSE;
+}
+
+boolean gd_caveset_has_levels(void)
+{
+ List *iter;
+
+ for (iter = gd_caveset; iter != NULL; iter = iter->next)
+ if (gd_cave_has_levels((GdCave *)iter->data))
+ return TRUE;
+
+ return FALSE;
+}