+2005-12-12
+ * added level file chunk "CONF" for generic level and element settings
+
+2005-12-11
+ * uploaded pre-release (test) version 3.2.0-4 binary and source code
+
2005-12-11
* skip empty level sets (with "levels: 0"; may be artwork base sets)
* added sound action ".page[1]" to ".page[32]" for each CE change page
backup_gfx:
./Scripts/make_backup.sh gfx
+# prerelease:
+# ./Scripts/make_prerelease.sh
+
dist-unix:
./Scripts/make_dist.sh unix .
-#define COMPILE_DATE_STRING "[2005-12-11 03:16]"
+#define COMPILE_DATE_STRING "[2005-12-13 01:12]"
for (x = 0; x < 3; x++)
DrawMiniGraphicExt(drawto,
gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY,
- el2edimg(custom_element.content[x][y]));
+ el2edimg(custom_element.content.e[x][y]));
else if (id == ED_DRAWING_ID_CUSTOM_MOVE_ENTER)
DrawMiniGraphicExt(drawto, gi->x, gi->y,
el2edimg(custom_element.move_enter_element));
for (x = 0; x < 3; x++)
DrawMiniGraphicExt(drawto,
gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY,
- el2edimg(custom_element_change.target_content[x][y]));
+ el2edimg(custom_element_change.target_content.e[x][y]));
else if (id == ED_DRAWING_ID_CUSTOM_CHANGE_TRIGGER)
DrawMiniGraphicExt(drawto, gi->x, gi->y,
el2edimg(custom_element_change.trigger_element));
for (x = 0; x < 3; x++)
DrawMiniGraphicExt(drawto,
gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY,
- el2edimg(level.yamyam_content[nr][x][y]));
+ el2edimg(level.yamyam_content[nr].e[x][y]));
}
else if (id >= ED_DRAWING_ID_MAGIC_BALL_CONTENT_0 &&
id <= ED_DRAWING_ID_MAGIC_BALL_CONTENT_7)
for (x = 0; x < 3; x++)
DrawMiniGraphicExt(drawto,
gi->x + x * MINI_TILEX, gi->y + y * MINI_TILEY,
- el2edimg(level.ball_content[nr][x][y]));
+ el2edimg(level.ball_content[nr].e[x][y]));
}
}
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- ei_to->content[x][y] = ei_from->content[x][y];
+ ei_to->content.e[x][y] = ei_from->content.e[x][y];
ei_to->explosion_type = ei_from->explosion_type;
ei_to->explosion_delay = ei_from->explosion_delay;
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- if (ei->content[x][y] == element_from)
- ei->content[x][y] = element_to;
+ if (ei->content.e[x][y] == element_from)
+ ei->content.e[x][y] = element_to;
for (j = 0; j < ei->num_change_pages; j++)
{
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- if (change->target_content[x][y] == element_from)
- change->target_content[x][y] = element_to;
+ if (change->target_content.e[x][y] == element_from)
+ change->target_content.e[x][y] = element_to;
}
if (ei->group != NULL) /* group or internal */
int y = SY + ED_AREA_MAGIC_BALL_CONTENT_YPOS(0) + ED_BORDER_AREA_YSIZE;
int i;
- for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+ for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
MapDrawingArea(ED_DRAWING_ID_MAGIC_BALL_CONTENT_0 + i);
DrawText(x, y + 0 * MINI_TILEY, "generated", FONT_TEXT_1);
}
else if (id == GADGET_ID_CUSTOM_CONTENT)
{
- custom_element.content[sx][sy] = new_element;
+ custom_element.content.e[sx][sy] = new_element;
CopyCustomElementPropertiesToGame(properties_element);
}
}
else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
{
- custom_element_change.target_content[sx][sy] = new_element;
+ custom_element_change.target_content.e[sx][sy] = new_element;
CopyCustomElementPropertiesToGame(properties_element);
}
random_placement_background_element = new_element;
else if (id >= GADGET_ID_YAMYAM_CONTENT_0 &&
id <= GADGET_ID_YAMYAM_CONTENT_7)
- level.yamyam_content[id - GADGET_ID_YAMYAM_CONTENT_0][sx][sy] =
+ level.yamyam_content[id - GADGET_ID_YAMYAM_CONTENT_0].e[sx][sy] =
new_element;
else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 &&
id <= GADGET_ID_MAGIC_BALL_CONTENT_7)
- level.ball_content[id - GADGET_ID_MAGIC_BALL_CONTENT_0][sx][sy] =
+ level.ball_content[id - GADGET_ID_MAGIC_BALL_CONTENT_0].e[sx][sy] =
new_element;
}
break;
else if (id == GADGET_ID_CUSTOM_GRAPHIC)
PickDrawingElement(button, custom_element.gfx_element);
else if (id == GADGET_ID_CUSTOM_CONTENT)
- PickDrawingElement(button, custom_element.content[sx][sy]);
+ PickDrawingElement(button, custom_element.content.e[sx][sy]);
else if (id == GADGET_ID_CUSTOM_MOVE_ENTER)
PickDrawingElement(button, custom_element.move_enter_element);
else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE)
else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
PickDrawingElement(button, custom_element_change.target_element);
else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
- PickDrawingElement(button, custom_element_change.target_content[sx][sy]);
+ PickDrawingElement(button, custom_element_change.target_content.e[sx][sy]);
else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
PickDrawingElement(button, custom_element_change.trigger_element);
else if (id == GADGET_ID_GROUP_CONTENT)
{
int i = id - GADGET_ID_YAMYAM_CONTENT_0;
- PickDrawingElement(button, level.yamyam_content[i][sx][sy]);
+ PickDrawingElement(button, level.yamyam_content[i].e[sx][sy]);
}
else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 &&
id <= GADGET_ID_MAGIC_BALL_CONTENT_7)
{
int i = id - GADGET_ID_MAGIC_BALL_CONTENT_0;
- PickDrawingElement(button, level.ball_content[i][sx][sy]);
+ PickDrawingElement(button, level.ball_content[i].e[sx][sy]);
}
break;
else if (id == GADGET_ID_CUSTOM_GRAPHIC)
element = custom_element.gfx_element;
else if (id == GADGET_ID_CUSTOM_CONTENT)
- element = custom_element.content[sx][sy];
+ element = custom_element.content.e[sx][sy];
else if (id == GADGET_ID_CUSTOM_MOVE_ENTER)
element = custom_element.move_enter_element;
else if (id == GADGET_ID_CUSTOM_MOVE_LEAVE)
else if (id == GADGET_ID_CUSTOM_CHANGE_TARGET)
element = custom_element_change.target_element;
else if (id == GADGET_ID_CUSTOM_CHANGE_CONTENT)
- element = custom_element_change.target_content[sx][sy];
+ element = custom_element_change.target_content.e[sx][sy];
else if (id == GADGET_ID_CUSTOM_CHANGE_TRIGGER)
element = custom_element_change.trigger_element;
else if (id == GADGET_ID_GROUP_CONTENT)
element = random_placement_background_element;
else if (id >= GADGET_ID_YAMYAM_CONTENT_0 &&
id <= GADGET_ID_YAMYAM_CONTENT_7)
- element = level.yamyam_content[id - GADGET_ID_YAMYAM_CONTENT_0][sx][sy];
+ element = level.yamyam_content[id -GADGET_ID_YAMYAM_CONTENT_0].e[sx][sy];
else if (id >= GADGET_ID_MAGIC_BALL_CONTENT_0 &&
id <= GADGET_ID_MAGIC_BALL_CONTENT_7)
- element = level.ball_content[id -GADGET_ID_MAGIC_BALL_CONTENT_0][sx][sy];
+ element =level.ball_content[id-GADGET_ID_MAGIC_BALL_CONTENT_0].e[sx][sy];
strncpy(infotext, getElementInfoText(element), max_infotext_len);
}
#define TAPE_COOKIE_TMPL "ROCKSNDIAMONDS_TAPE_FILE_VERSION_x.x"
#define SCORE_COOKIE "ROCKSNDIAMONDS_SCORE_FILE_VERSION_1.2"
+/* values for "CONF" chunk */
+#define CONF_MASK_1_BYTE 0x00
+#define CONF_MASK_2_BYTE 0x40
+#define CONF_MASK_4_BYTE 0x80
+#define CONF_MASK_MULTI_BYTES 0xc0
+
+#define CONF_MASK_BYTES 0xc0
+#define CONF_MASK_TOKEN 0x3f
+
+#define CONF_LAST_ENTRY (CONF_MASK_1_BYTE | 0)
+
+#define CONF_VALUE_SCORE_1 (CONF_MASK_1_BYTE | 1)
+#define CONF_VALUE_SCORE_2 (CONF_MASK_1_BYTE | 2)
+#define CONF_VALUE_SCORE_3 (CONF_MASK_1_BYTE | 3)
+#define CONF_VALUE_SCORE_4 (CONF_MASK_1_BYTE | 4)
+#define CONF_VALUE_TIME_1 (CONF_MASK_1_BYTE | 5)
+#define CONF_VALUE_TIME_2 (CONF_MASK_1_BYTE | 6)
+#define CONF_VALUE_TIME_3 (CONF_MASK_1_BYTE | 7)
+#define CONF_VALUE_TIME_4 (CONF_MASK_1_BYTE | 8)
+#define CONF_VALUE_SWITCH_1 (CONF_MASK_1_BYTE | 9)
+#define CONF_VALUE_SWITCH_2 (CONF_MASK_1_BYTE | 10)
+#define CONF_VALUE_SWITCH_3 (CONF_MASK_1_BYTE | 11)
+#define CONF_VALUE_SWITCH_4 (CONF_MASK_1_BYTE | 12)
+#define CONF_VALUE_USE_BUG_1 (CONF_MASK_1_BYTE | 13)
+#define CONF_VALUE_USE_BUG_2 (CONF_MASK_1_BYTE | 14)
+#define CONF_VALUE_USE_BUG_3 (CONF_MASK_1_BYTE | 15)
+#define CONF_VALUE_USE_BUG_4 (CONF_MASK_1_BYTE | 16)
+
+#define CONF_VALUE_ELEMENT_1 (CONF_MASK_2_BYTE | 1)
+#define CONF_VALUE_ELEMENT_2 (CONF_MASK_2_BYTE | 2)
+
+#define CONF_VALUE_CONTENT_1 (CONF_MASK_MULTI_BYTES | 1)
+#define CONF_VALUE_CONTENT_8 (CONF_MASK_MULTI_BYTES | 2)
+
+#define CONF_VALUE_BOOLEAN(x) ((x) >= CONF_VALUE_SWITCH_1 && \
+ (x) <= CONF_VALUE_USE_BUG_4)
+
+#define CONF_VALUE_NUM_BYTES(x) ((x) == CONF_MASK_1_BYTE ? 1 : \
+ (x) == CONF_MASK_2_BYTE ? 2 : \
+ (x) == CONF_MASK_4_BYTE ? 4 : 0)
+
+#define CONF_CONTENT_NUM_ELEMENTS (3 * 3)
+#define CONF_CONTENT_NUM_BYTES (CONF_CONTENT_NUM_ELEMENTS * 2)
+
+#define CONF_CONTENT_ELEMENT_POS(c,x,y) ((c) * CONF_CONTENT_NUM_ELEMENTS + \
+ (y) * 3 + (x))
+#define CONF_CONTENT_BYTE_POS(c,x,y) (CONF_CONTENT_ELEMENT_POS(c,x,y) * 2)
+#define CONF_CONTENT_ELEMENT(b,c,x,y) ((b[CONF_CONTENT_BYTE_POS(c,x,y)] << 8)|\
+ (b[CONF_CONTENT_BYTE_POS(c,x,y) + 1]))
+
+static struct LevelInfo li;
+
+static struct
+{
+ int element;
+ int type;
+ void *value;
+} element_conf[] =
+{
+ /* 1-byte values */
+ { EL_EMC_ANDROID, CONF_VALUE_TIME_1, &li.android_move_time },
+ { EL_EMC_ANDROID, CONF_VALUE_TIME_2, &li.android_clone_time },
+ { EL_EMC_MAGIC_BALL, CONF_VALUE_TIME_1, &li.ball_time },
+ { EL_EMC_LENSES, CONF_VALUE_SCORE_1, &li.lenses_score },
+ { EL_EMC_LENSES, CONF_VALUE_TIME_1, &li.lenses_time },
+ { EL_EMC_MAGNIFIER, CONF_VALUE_SCORE_1, &li.magnify_score },
+ { EL_EMC_MAGNIFIER, CONF_VALUE_TIME_1, &li.magnify_time },
+ { EL_ROBOT, CONF_VALUE_SCORE_2, &li.slurp_score },
+
+ /* multi-byte values */
+ { EL_EMC_MAGIC_BALL, CONF_VALUE_CONTENT_8, &li.ball_content },
+
+ { -1, -1, NULL },
+};
+
static struct
{
int filetype;
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
- change->target_content[x][y] = EL_EMPTY_SPACE;
+ change->target_content.e[x][y] = EL_EMPTY_SPACE;
change->direct_action = 0;
change->other_action = 0;
level->lenses_time = 10;
level->magnify_time = 10;
level->wind_direction_initial = MV_NO_MOVING;
- for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+ for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
- level->ball_content[i][x][y] = EL_EMPTY;
+ level->ball_content[i].e[x][y] = EL_EMPTY;
for (i = 0; i < 16; i++)
level->android_array[i] = FALSE;
for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
- level->yamyam_content[i][x][y] =
+ level->yamyam_content[i].e[x][y] =
(i < STD_ELEMENT_CONTENTS ? EL_ROCK : EL_EMPTY);
level->field[0][0] = EL_PLAYER_1;
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
- element_info[element].content[x][y] = EL_EMPTY_SPACE;
+ element_info[element].content.e[x][y] = EL_EMPTY_SPACE;
element_info[element].access_type = 0;
element_info[element].access_layer = 0;
for (i = 0; i < STD_ELEMENT_CONTENTS; i++)
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- level->yamyam_content[i][x][y] = getMappedElement(getFile8Bit(file));
+ level->yamyam_content[i].e[x][y] = getMappedElement(getFile8Bit(file));
level->amoeba_speed = getFile8Bit(file);
level->time_magic_wall = getFile8Bit(file);
for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- level->yamyam_content[i][x][y] =
+ level->yamyam_content[i].e[x][y] =
getMappedElement(level->encoding_16bit_field ?
getFile16BitBE(file) : getFile8Bit(file));
return chunk_size;
for (i = 0; i < num_contents; i++)
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- level->yamyam_content[i][x][y] = content_array[i][x][y];
+ level->yamyam_content[i].e[x][y] = content_array[i][x][y];
}
else if (element == EL_BD_AMOEBA)
{
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- element_info[element].content[x][y] =
+ element_info[element].content.e[x][y] =
getMappedElement(getFile16BitBE(file));
event_bits = getFile32BitBE(file);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- element_info[element].change->target_content[x][y] =
+ element_info[element].change->target_content.e[x][y] =
getMappedElement(getFile16BitBE(file));
element_info[element].slippery_type = getFile8Bit(file);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- ei->content[x][y] = getMappedElement(getFile16BitBE(file));
+ ei->content.e[x][y] = getMappedElement(getFile16BitBE(file));
ei->move_enter_element = getMappedElement(getFile16BitBE(file));
ei->move_leave_element = getMappedElement(getFile16BitBE(file));
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- change->target_content[x][y] = getMappedElement(getFile16BitBE(file));
+ change->target_content.e[x][y]= getMappedElement(getFile16BitBE(file));
change->can_change = getFile8Bit(file);
return chunk_size;
}
+static int LoadLevel_CONF(FILE *file, int chunk_size, struct LevelInfo *level)
+{
+ int real_chunk_size = 0;
+ int i;
+
+ while (!feof(file))
+ {
+ int element = getFile16BitBE(file);
+ int type = getFile8Bit(file);
+ int bytes = type & CONF_MASK_BYTES;
+ boolean element_found = FALSE;
+
+ real_chunk_size += 3;
+
+ li = *level; /* copy level information into temporary buffer */
+
+ if (bytes == CONF_MASK_MULTI_BYTES)
+ {
+ int num_bytes = getFile16BitBE(file);
+ byte *buffer = checked_malloc(num_bytes);
+
+ ReadBytesFromFile(file, buffer, num_bytes);
+
+ for (i = 0; element_conf[i].element != -1; i++)
+ {
+ if (element_conf[i].element == element &&
+ element_conf[i].type == type)
+ {
+ element_found = TRUE;
+
+ if (type == CONF_VALUE_CONTENT_8)
+ {
+ struct Content *content= (struct Content *)(element_conf[i].value);
+ int num_contents = num_bytes / CONF_CONTENT_NUM_BYTES;
+ int c, x, y;
+
+ for (c = 0; c < num_contents; c++)
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ content[c].e[x][y] =
+ getMappedElement(CONF_CONTENT_ELEMENT(buffer, c, x, y));
+ }
+ else
+ element_found = FALSE;
+
+ break;
+ }
+ }
+
+ checked_free(buffer);
+
+ real_chunk_size += 2 + num_bytes;
+ }
+ else
+ {
+ int value = (bytes == CONF_MASK_1_BYTE ? getFile8Bit (file) :
+ bytes == CONF_MASK_2_BYTE ? getFile16BitBE(file) :
+ bytes == CONF_MASK_4_BYTE ? getFile32BitBE(file) : 0);
+
+ for (i = 0; element_conf[i].element != -1; i++)
+ {
+ if (element_conf[i].element == element &&
+ element_conf[i].type == type)
+ {
+ if (CONF_VALUE_BOOLEAN(type))
+ *(boolean *)(element_conf[i].value) = value;
+ else
+ *(int *) (element_conf[i].value) = value;
+
+ element_found = TRUE;
+
+ break;
+ }
+ }
+
+ real_chunk_size += CONF_VALUE_NUM_BYTES(bytes);
+ }
+
+ *level = li; /* copy temporary buffer back to level information */
+
+ if (!element_found)
+ Error(ERR_WARN, "cannot load CONF value for element %d", element);
+
+ if (type == CONF_LAST_ENTRY || real_chunk_size >= chunk_size)
+ break;
+ }
+
+ return real_chunk_size;
+}
+
static void LoadLevelFromFileInfo_RND(struct LevelInfo *level,
struct LevelFileInfo *level_file_info)
{
{ "CUS3", -1, LoadLevel_CUS3 },
{ "CUS4", -1, LoadLevel_CUS4 },
{ "GRP1", -1, LoadLevel_GRP1 },
+ { "CONF", -1, LoadLevel_CONF },
+
{ NULL, 0, NULL }
};
for (i = 0; i < level->num_yamyam_contents; i++)
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- level->yamyam_content[i][x][y] =
+ level->yamyam_content[i].e[x][y] =
map_em_element_yam(header[i * 9 + y * 3 + x]);
level->amoeba_speed = (header[52] * 256 + header[53]) % 256;
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
lev->eater_array[i][y * 3 + x] =
- map_element_RND_to_EM(level->yamyam_content[i][x][y]);
+ map_element_RND_to_EM(level->yamyam_content[i].e[x][y]);
lev->amoeba_time = level->amoeba_speed;
lev->wonderwall_time_initial = level->time_magic_wall;
lev->magnify_time = level->magnify_time;
lev->wind_direction_initial = level->wind_direction_initial;
- for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+ for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
for (j = 0; j < 8; j++)
lev->ball_array[i][j] =
map_element_RND_to_EM(level->
- ball_content[i][ball_xy[j][0]][ball_xy[j][1]]);
+ ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]]);
for (i = 0; i < 16; i++)
lev->android_array[i] = FALSE; /* !!! YET TO COME !!! */
for (i = 0; i < level->num_yamyam_contents; i++)
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- level->yamyam_content[i][x][y] =
+ level->yamyam_content[i].e[x][y] =
map_element_EM_to_RND(lev->eater_array[i][y * 3 + x]);
level->amoeba_speed = lev->amoeba_time;
level->magnify_time = lev->magnify_time;
level->wind_direction_initial = lev->wind_direction_initial;
- for (i = 0; i < NUM_MAGIC_BALL_CONTENTS; i++)
+ for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
for (j = 0; j < 8; j++)
- level->ball_content[i][ball_xy[j][0]][ball_xy[j][1]] =
+ level->ball_content[i].e[ball_xy[j][0]][ball_xy[j][1]] =
map_element_EM_to_RND(lev->ball_array[i][j]);
for (i = 0; i < 16; i++)
for (i = 0; i < level->num_yamyam_contents; i++)
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- level->yamyam_content[i][x][y] = EL_EMPTY;
+ level->yamyam_content[i].e[x][y] = EL_EMPTY;
}
static void LoadLevelFromFileInfo_SP(struct LevelInfo *level,
for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
for (x = 0; x < 3; x++)
for (y = 0; y < 3; y++)
- level->yamyam_content[i][x][y] =
- getMappedElementByVersion(level->yamyam_content[i][x][y],
+ level->yamyam_content[i].e[x][y] =
+ getMappedElementByVersion(level->yamyam_content[i].e[x][y],
level->game_version);
/* initialize element properties for level editor etc. */
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
putFile8Bit(file, (level->encoding_16bit_yamyam ? EL_EMPTY :
- level->yamyam_content[i][x][y]));
+ level->yamyam_content[i].e[x][y]));
putFile8Bit(file, level->amoeba_speed);
putFile8Bit(file, level->time_magic_wall);
putFile8Bit(file, level->time_wheel);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
if (level->encoding_16bit_field)
- putFile16BitBE(file, level->yamyam_content[i][x][y]);
+ putFile16BitBE(file, level->yamyam_content[i].e[x][y]);
else
- putFile8Bit(file, level->yamyam_content[i][x][y]);
+ putFile8Bit(file, level->yamyam_content[i].e[x][y]);
}
#endif
for (i = 0; i < MAX_ELEMENT_CONTENTS; i++)
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- content_array[i][x][y] = level->yamyam_content[i][x][y];
+ content_array[i][x][y] = level->yamyam_content[i].e[x][y];
}
else if (element == EL_BD_AMOEBA)
{
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- putFile16BitBE(file, element_info[element].content[x][y]);
+ putFile16BitBE(file, element_info[element].content.e[x][y]);
putFile32BitBE(file, element_info[element].change->events);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- putFile16BitBE(file, element_info[element].change->content[x][y]);
+ putFile16BitBE(file,element_info[element].change->content.e[x][y]);
putFile8Bit(file, element_info[element].slippery_type);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- putFile16BitBE(file, ei->content[x][y]);
+ putFile16BitBE(file, ei->content.e[x][y]);
putFile16BitBE(file, ei->move_enter_element);
putFile16BitBE(file, ei->move_leave_element);
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- putFile16BitBE(file, change->target_content[x][y]);
+ putFile16BitBE(file, change->target_content.e[x][y]);
putFile8Bit(file, change->can_change);
putFile16BitBE(file, group->element[i]);
}
+static int SaveLevel_CONF_Value(FILE *file, int element, int type, int value)
+{
+ int bytes = type & CONF_MASK_BYTES;
+ int num_bytes = 0;
+
+ if (bytes == CONF_MASK_MULTI_BYTES)
+ Error(ERR_EXIT, "SaveLevel_CONF_INT: invalid type CONF_MASK_MULTI_BYTES");
+
+ num_bytes += putFile16BitBE(file, element);
+ num_bytes += putFile8Bit(file, type);
+ num_bytes += (bytes == CONF_MASK_1_BYTE ? putFile8Bit (file, value) :
+ bytes == CONF_MASK_2_BYTE ? putFile16BitBE(file, value) :
+ bytes == CONF_MASK_4_BYTE ? putFile32BitBE(file, value) : 0);
+
+ return num_bytes;
+}
+
+static int SaveLevel_CONF_Content(FILE *file, int element, int type,
+ struct Content *content, int num_contents)
+{
+ int num_bytes = 0;
+ int i, x, y;
+
+ num_bytes += putFile16BitBE(file, element);
+ num_bytes += putFile8Bit(file, type);
+ num_bytes += putFile16BitBE(file, num_contents * CONF_CONTENT_NUM_BYTES);
+
+ for (i = 0; i < num_contents; i++)
+ for (y = 0; y < 3; y++)
+ for (x = 0; x < 3; x++)
+ num_bytes += putFile16BitBE(file, content[i].e[x][y]);
+
+ return num_bytes;
+}
+
+static int SaveLevel_CONF(FILE *file, struct LevelInfo *level)
+{
+ int chunk_size = 0;
+ int i;
+
+ li = *level; /* copy level information into temporary buffer */
+
+ for (i = 0; element_conf[i].element != -1; i++)
+ {
+ int element = element_conf[i].element;
+ int type = element_conf[i].type;
+ void *value = element_conf[i].value;
+ int bytes = type & CONF_MASK_BYTES;
+
+ if (bytes == CONF_MASK_MULTI_BYTES)
+ {
+ if (type == CONF_VALUE_CONTENT_8)
+ {
+ struct Content *content = (struct Content *)value;
+
+ chunk_size += SaveLevel_CONF_Content(file, element, type,
+ content, MAX_ELEMENT_CONTENTS);
+ }
+ else
+ Error(ERR_WARN, "cannot save CONF value for element %d", element);
+ }
+ else
+ {
+ int value_int = (CONF_VALUE_BOOLEAN(type) ? *(boolean *)value :
+ *(int *)value);
+
+ chunk_size += SaveLevel_CONF_Value(file, element, type, value_int);
+ }
+ }
+
+ return chunk_size;
+}
+
static void SaveLevelFromFilename(struct LevelInfo *level, char *filename)
{
- int body_chunk_size;
+ int body_chunk_size, conf_chunk_size;
int i, x, y;
FILE *file;
for (i = 0; i < level->num_yamyam_contents; i++)
for (y = 0; y < 3; y++)
for (x = 0; x < 3; x++)
- if (level->yamyam_content[i][x][y] > 255)
+ if (level->yamyam_content[i].e[x][y] > 255)
level->encoding_16bit_yamyam = TRUE;
/* check amoeba content for 16-bit elements */
}
}
+ conf_chunk_size = SaveLevel_CONF(NULL, level); /* get chunk size */
+
+ putFileChunkBE(file, "CONF", conf_chunk_size);
+ SaveLevel_CONF(file, level);
+
fclose(file);
SetFilePermissions(filename, PERMS_PRIVATE);
#define USE_NEW_AMOEBA_CODE FALSE
/* EXPERIMENTAL STUFF */
-#define USE_NEW_STUFF ( * 1)
+#define USE_NEW_STUFF ( 1)
#define USE_NEW_SP_SLIPPERY (USE_NEW_STUFF * 1)
#define USE_NEW_COLLECT_COUNT (USE_NEW_STUFF * 1)
for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3; xx++)
{
- content = element_info[element].content[xx][yy];
+ content = element_info[element].content.e[xx][yy];
is_player = ELEM_IS_PLAYER(content);
if (is_player && (found_rating < 2 || element < found_element))
for (i = 0; i < element_info[element].num_change_pages; i++)
{
- content= element_info[element].change_page[i].target_content[xx][yy];
+ content =
+ element_info[element].change_page[i].target_content.e[xx][yy];
+
is_player = ELEM_IS_PLAYER(content);
if (is_player && (found_rating < 1 || element < found_element))
else if (center_element == EL_AMOEBA_TO_DIAMOND)
Store[x][y] = level.amoeba_content;
else if (center_element == EL_YAMYAM)
- Store[x][y] = level.yamyam_content[game.yamyam_content_nr][xx][yy];
+ Store[x][y] = level.yamyam_content[game.yamyam_content_nr].e[xx][yy];
else if (IS_CUSTOM_ELEMENT(center_element) &&
- element_info[center_element].content[xx][yy] != EL_EMPTY)
- Store[x][y] = element_info[center_element].content[xx][yy];
+ element_info[center_element].content.e[xx][yy] != EL_EMPTY)
+ Store[x][y] = element_info[center_element].content.e[xx][yy];
else if (element == EL_WALL_EMERALD)
Store[x][y] = EL_EMERALD;
else if (element == EL_WALL_DIAMOND)
else if (element == EL_WALL_CRYSTAL)
Store[x][y] = EL_CRYSTAL;
else if (IS_CUSTOM_ELEMENT(element) && !CAN_EXPLODE(element))
- Store[x][y] = element_info[element].content[1][1];
+ Store[x][y] = element_info[element].content.e[1][1];
else
Store[x][y] = EL_EMPTY;
boolean is_destructible;
int ex = x + xx - 1;
int ey = y + yy - 1;
- int content_element = change->target_content[xx][yy];
+ int content_element = change->target_content.e[xx][yy];
int e;
can_replace[xx][yy] = TRUE;
ChangeEvent[ex][ey] = ChangeEvent[x][y];
- content_element = change->target_content[xx][yy];
+ content_element = change->target_content.e[xx][yy];
target_element = GET_TARGET_ELEMENT(content_element, change);
ChangeElementNowExt(change, ex, ey, target_element);
*y2 = help_y;
}
+/* the "put" variants of the following file access functions check for the file
+ pointer being != NULL and return the number of bytes they have or would have
+ written; this allows for chunk writing functions to first determine the size
+ of the (not yet written) chunk, write the correct chunk size and finally
+ write the chunk itself */
+
+int getFile8BitInteger(FILE *file)
+{
+ return fgetc(file);
+}
+
+int putFile8BitInteger(FILE *file, int value)
+{
+ if (file != NULL)
+ fputc(value, file);
+
+ return 1;
+}
+
int getFile16BitInteger(FILE *file, int byte_order)
{
if (byte_order == BYTE_ORDER_BIG_ENDIAN)
(fgetc(file) << 8));
}
-void putFile16BitInteger(FILE *file, int value, int byte_order)
+int putFile16BitInteger(FILE *file, int value, int byte_order)
{
- if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+ if (file != NULL)
{
- fputc((value >> 8) & 0xff, file);
- fputc((value >> 0) & 0xff, file);
- }
- else /* BYTE_ORDER_LITTLE_ENDIAN */
- {
- fputc((value >> 0) & 0xff, file);
- fputc((value >> 8) & 0xff, file);
+ if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+ {
+ fputc((value >> 8) & 0xff, file);
+ fputc((value >> 0) & 0xff, file);
+ }
+ else /* BYTE_ORDER_LITTLE_ENDIAN */
+ {
+ fputc((value >> 0) & 0xff, file);
+ fputc((value >> 8) & 0xff, file);
+ }
}
+
+ return 2;
}
int getFile32BitInteger(FILE *file, int byte_order)
(fgetc(file) << 24));
}
-void putFile32BitInteger(FILE *file, int value, int byte_order)
+int putFile32BitInteger(FILE *file, int value, int byte_order)
{
- if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+ if (file != NULL)
{
- fputc((value >> 24) & 0xff, file);
- fputc((value >> 16) & 0xff, file);
- fputc((value >> 8) & 0xff, file);
- fputc((value >> 0) & 0xff, file);
- }
- else /* BYTE_ORDER_LITTLE_ENDIAN */
- {
- fputc((value >> 0) & 0xff, file);
- fputc((value >> 8) & 0xff, file);
- fputc((value >> 16) & 0xff, file);
- fputc((value >> 24) & 0xff, file);
+ if (byte_order == BYTE_ORDER_BIG_ENDIAN)
+ {
+ fputc((value >> 24) & 0xff, file);
+ fputc((value >> 16) & 0xff, file);
+ fputc((value >> 8) & 0xff, file);
+ fputc((value >> 0) & 0xff, file);
+ }
+ else /* BYTE_ORDER_LITTLE_ENDIAN */
+ {
+ fputc((value >> 0) & 0xff, file);
+ fputc((value >> 8) & 0xff, file);
+ fputc((value >> 16) & 0xff, file);
+ fputc((value >> 24) & 0xff, file);
+ }
}
+
+ return 4;
}
boolean getFileChunk(FILE *file, char *chunk_name, int *chunk_size,
fputc(version_build, file);
}
+void ReadBytesFromFile(FILE *file, byte *buffer, unsigned long bytes)
+{
+ int i;
+
+ for(i = 0; i < bytes && !feof(file); i++)
+ buffer[i] = fgetc(file);
+}
+
+void WriteBytesToFile(FILE *file, byte *buffer, unsigned long bytes)
+{
+ int i;
+
+ for(i = 0; i < bytes; i++)
+ fputc(buffer[i], file);
+}
+
void ReadUnusedBytesFromFile(FILE *file, unsigned long bytes)
{
while (bytes-- && !feof(file))
inline void swap_numbers(int *, int *);
inline void swap_number_pairs(int *, int *, int *, int *);
+int getFile8BitInteger(FILE *);
+int putFile8BitInteger(FILE *, int);
int getFile16BitInteger(FILE *, int);
-void putFile16BitInteger(FILE *, int, int);
+int putFile16BitInteger(FILE *, int, int);
int getFile32BitInteger(FILE *, int);
-void putFile32BitInteger(FILE *, int, int);
+int putFile32BitInteger(FILE *, int, int);
+
boolean getFileChunk(FILE *, char *, int *, int);
void putFileChunk(FILE *, char *, int, int);
int getFileVersion(FILE *);
void putFileVersion(FILE *, int);
+
+void ReadBytesFromFile(FILE *, byte *, unsigned long);
+void WriteBytesToFile(FILE *, byte *, unsigned long);
+
void ReadUnusedBytesFromFile(FILE *, unsigned long);
void WriteUnusedBytesToFile(FILE *, unsigned long);
-#define getFile8Bit(f) fgetc(f)
-#define putFile8Bit(f,x) fputc(x, f)
+#define getFile8Bit(f) getFile8BitInteger(f)
+#define putFile8Bit(f,x) putFile8BitInteger(f,x)
#define getFile16BitBE(f) getFile16BitInteger(f,BYTE_ORDER_BIG_ENDIAN)
#define getFile16BitLE(f) getFile16BitInteger(f,BYTE_ORDER_LITTLE_ENDIAN)
#define putFile16BitBE(f,x) putFile16BitInteger(f,x,BYTE_ORDER_BIG_ENDIAN)
#define getFile32BitLE(f) getFile32BitInteger(f,BYTE_ORDER_LITTLE_ENDIAN)
#define putFile32BitBE(f,x) putFile32BitInteger(f,x,BYTE_ORDER_BIG_ENDIAN)
#define putFile32BitLE(f,x) putFile32BitInteger(f,x,BYTE_ORDER_LITTLE_ENDIAN)
+
#define getFileChunkBE(f,s,x) getFileChunk(f,s,x,BYTE_ORDER_BIG_ENDIAN)
#define getFileChunkLE(f,s,x) getFileChunk(f,s,x,BYTE_ORDER_LITTLE_ENDIAN)
#define putFileChunkBE(f,s,x) putFileChunk(f,s,x,BYTE_ORDER_BIG_ENDIAN)
#define MIN_ELEMENT_CONTENTS 1
#define STD_ELEMENT_CONTENTS 4
#define MAX_ELEMENT_CONTENTS 8
-#define NUM_MAGIC_BALL_CONTENTS 8
#define LEVEL_SCORE_ELEMENTS 16 /* level elements with score */
#define PROGRAM_VERSION_MAJOR 3
#define PROGRAM_VERSION_MINOR 2
#define PROGRAM_VERSION_PATCH 0
-#define PROGRAM_VERSION_BUILD 4
+#define PROGRAM_VERSION_BUILD 5
#endif
#define PROGRAM_TITLE_STRING "Rocks'n'Diamonds"
int Score;
};
+struct Content
+{
+ int e[3][3];
+};
+
struct PlayerInfo
{
boolean present; /* player present in level playfield */
int score[LEVEL_SCORE_ELEMENTS];
- int yamyam_content[MAX_ELEMENT_CONTENTS][3][3];
+ struct Content yamyam_content[MAX_ELEMENT_CONTENTS];
int num_yamyam_contents;
int amoeba_speed;
int lenses_time;
int magnify_time;
int wind_direction_initial;
- int ball_content[NUM_MAGIC_BALL_CONTENTS][3][3];
+ struct Content ball_content[MAX_ELEMENT_CONTENTS];
boolean android_array[16];
int can_move_into_acid_bits; /* bitfield to store property for elements */
short trigger_element; /* element triggering change */
- int target_content[3][3]; /* elements for extended change target */
+ struct Content target_content;/* elements for extended change target */
boolean use_target_content; /* use extended change target */
boolean only_if_complete; /* only use complete target content */
boolean use_random_replace; /* use random value for replacing elements */
int slippery_type; /* how/where other elements slip away */
- int content[3][3]; /* new elements after explosion */
+ struct Content content; /* new elements after explosion */
int explosion_type; /* type of explosion, like 3x3, 3+3 or 1x1 */
int explosion_delay; /* duration of explosion of this element */