+2004-01-29
+ * fixed bug: infotron can now smash yellow disks
+
+2004-01-26
+ * added "choice type" for group element selection
+
+2004-01-25
+ * fixed bug with initial invulnerability of non-yellow player
+
+2004-01-23
+ * added level loader for loading native Supaplex packed levels
+ (including multi-part levels like the "splvls99" levels)
2004-01-19
* fixed bug which allowed creating emeralds by escaping explosions
-#define COMPILE_DATE_STRING "[2004-01-25 13:45]"
+#define COMPILE_DATE_STRING "[2004-01-29 17:39]"
#define GADGET_ID_CHANGE_SIDES (GADGET_ID_SELECTBOX_FIRST + 14)
#define GADGET_ID_CHANGE_POWER (GADGET_ID_SELECTBOX_FIRST + 15)
#define GADGET_ID_SELECT_CHANGE_PAGE (GADGET_ID_SELECTBOX_FIRST + 16)
+#define GADGET_ID_GROUP_CHOICE_MODE (GADGET_ID_SELECTBOX_FIRST + 17)
/* textbutton identifiers */
-#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 17)
+#define GADGET_ID_TEXTBUTTON_FIRST (GADGET_ID_SELECTBOX_FIRST + 18)
#define GADGET_ID_PROPERTIES_INFO (GADGET_ID_TEXTBUTTON_FIRST + 0)
#define GADGET_ID_PROPERTIES_CONFIG (GADGET_ID_TEXTBUTTON_FIRST + 1)
#define ED_SELECTBOX_ID_CHANGE_SIDES 14
#define ED_SELECTBOX_ID_CHANGE_POWER 15
#define ED_SELECTBOX_ID_SELECT_CHANGE_PAGE 16
+#define ED_SELECTBOX_ID_GROUP_CHOICE_MODE 17
-#define ED_NUM_SELECTBOX 17
+#define ED_NUM_SELECTBOX 18
#define ED_SELECTBOX_ID_CUSTOM_FIRST ED_SELECTBOX_ID_CUSTOM_ACCESS_TYPE
#define ED_SELECTBOX_ID_CUSTOM_LAST ED_SELECTBOX_ID_CUSTOM_CONSISTENCY
static struct ValueTextInfo options_move_leave_type[] =
{
{ LEAVE_TYPE_UNLIMITED, "leave behind" },
- { LEAVE_TYPE_LIMITED, "change to" },
+ { LEAVE_TYPE_LIMITED, "change it to" },
{ -1, NULL }
};
{ -1, NULL }
};
+static struct ValueTextInfo options_group_choice_mode[] =
+{
+ { ANIM_RANDOM, "random" },
+ { ANIM_LOOP, "loop" },
+ { ANIM_LINEAR, "linear" },
+ { ANIM_PINGPONG, "pingpong" },
+ { ANIM_PINGPONG2, "pingpong 2" },
+ { -1, NULL }
+};
+
static struct
{
int x, y;
&custom_element.current_change_page,
NULL, NULL, "element config page"
},
+
+ /* ---------- element settings: configure (group elements) --------------- */
+
+ {
+ ED_SETTINGS_XPOS(0), ED_SETTINGS_YPOS(10),
+ GADGET_ID_GROUP_CHOICE_MODE, GADGET_ID_NONE,
+ -1,
+ options_group_choice_mode,
+ &group_element_info.choice_mode,
+ "choice type:", NULL, "type of group element choice"
+ },
};
static struct
/* draw counter gadgets */
MapCounterButtons(ED_COUNTER_ID_GROUP_CONTENT);
+ /* draw selectbox gadgets */
+ MapSelectboxGadget(ED_SELECTBOX_ID_GROUP_CHOICE_MODE);
+
/* draw drawing area gadgets */
DrawGroupElementArea(properties_element);
else if ((type_id >= ED_SELECTBOX_ID_CUSTOM_FIRST &&
type_id <= ED_SELECTBOX_ID_CUSTOM_LAST) ||
(type_id >= ED_SELECTBOX_ID_CHANGE_FIRST &&
- type_id <= ED_SELECTBOX_ID_CHANGE_LAST))
+ type_id <= ED_SELECTBOX_ID_CHANGE_LAST) ||
+ (type_id == ED_SELECTBOX_ID_GROUP_CHOICE_MODE))
CopyElementPropertiesToGame(properties_element);
}
/* default: only one element in group */
element_info[element].group->num_elements = 1;
+
+ element_info[element].group->choice_mode = ANIM_RANDOM;
}
}
ei->use_gfx_element = getFile8Bit(file);
ei->gfx_element = getMappedElement(getFile16BitBE(file));
+ group->choice_mode = getFile8Bit(file);
+
/* some free bytes for future values and padding */
- ReadUnusedBytesFromFile(file, 4);
+ ReadUnusedBytesFromFile(file, 3);
for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++)
group->element[i] = getMappedElement(getFile16BitBE(file));
putFile8Bit(file, ei->use_gfx_element);
putFile16BitBE(file, ei->gfx_element);
+ putFile8Bit(file, group->choice_mode);
+
/* some free bytes for future values and padding */
- WriteUnusedBytesToFile(file, 4);
+ WriteUnusedBytesToFile(file, 3);
for (i = 0; i < MAX_ELEMENTS_IN_GROUP; i++)
putFile16BitBE(file, group->element[i]);
else if (IS_GROUP_ELEMENT(element))
{
struct ElementGroupInfo *group = element_info[element].group;
- int random_pos = RND(group->num_elements_resolved);
+ int last_anim_random_frame = gfx.anim_random_frame;
+ int element_pos;
- Feld[x][y] = group->element_resolved[random_pos];
+ if (group->choice_mode == ANIM_RANDOM)
+ gfx.anim_random_frame = RND(group->num_elements_resolved);
+
+ element_pos = getAnimationFrame(group->num_elements_resolved, 1,
+ group->choice_mode, 0,
+ group->choice_pos);
+
+ if (group->choice_mode == ANIM_RANDOM)
+ gfx.anim_random_frame = last_anim_random_frame;
+
+ group->choice_pos++;
+
+ Feld[x][y] = group->element_resolved[element_pos];
InitField(x, y, init_game);
}
if (recursion_depth == 0) /* initialization */
{
group = element_info[group_element].group;
- group->num_elements_resolved = 0;
group_nr = group_element - EL_GROUP_START;
+
+ group->num_elements_resolved = 0;
+ group->choice_pos = 0;
}
for (i = 0; i < actual_group->num_elements; i++)
{
player->present = TRUE;
player->active = TRUE;
+
some_player->present = FALSE;
+ some_player->active = FALSE;
StorePlayer[jx][jy] = player->element_nr;
player->jx = player->last_jx = jx;
if (tape.playing)
{
- /* when playing a tape, eliminate all players who do not participate */
+ /* when playing a tape, eliminate all players which do not participate */
for (i = 0; i < MAX_PLAYERS; i++)
{
int jx = player->jx, jy = player->jy;
player->active = FALSE;
+ player->present = FALSE;
+
StorePlayer[jx][jy] = 0;
Feld[jx][jy] = EL_EMPTY;
}
return;
}
}
- else if ((element == EL_SP_INFOTRON ||
- element == EL_SP_ZONK) &&
- (smashed == EL_SP_SNIKSNAK ||
- smashed == EL_SP_ELECTRON ||
- smashed == EL_SP_DISK_ORANGE))
+ else if (((element == EL_SP_INFOTRON ||
+ element == EL_SP_ZONK) &&
+ (smashed == EL_SP_SNIKSNAK ||
+ smashed == EL_SP_ELECTRON ||
+ smashed == EL_SP_DISK_ORANGE)) ||
+ (element == EL_SP_INFOTRON &&
+ smashed == EL_SP_DISK_YELLOW))
{
Bang(x, y + 1);
return;
ResetGfxAnimation(x, y); /* reset animation values for old field */
#if 1
+ /* some elements can leave other elements behind after moving */
if (IS_CUSTOM_ELEMENT(element) && !IS_PLAYER(x, y) &&
ei->move_leave_element != EL_EMPTY &&
(ei->move_leave_type == LEAVE_TYPE_UNLIMITED ||
redraw_mask |= REDRAW_FIELD;
}
+static boolean canEnterSupaplexPort(int x, int y, int move_dir)
+{
+ int dx = (move_dir & MV_LEFT ? -1 : move_dir & MV_RIGHT ? +1 : 0);
+ int dy = (move_dir & MV_UP ? -1 : move_dir & MV_DOWN ? +1 : 0);
+ int nextx = x + dx, nexty = y + dy;
+ int element = Feld[x][y];
+
+ if ((dx == -1 &&
+ element != EL_SP_PORT_LEFT &&
+ element != EL_SP_GRAVITY_PORT_LEFT &&
+ element != EL_SP_PORT_HORIZONTAL &&
+ element != EL_SP_PORT_ANY) ||
+ (dx == +1 &&
+ element != EL_SP_PORT_RIGHT &&
+ element != EL_SP_GRAVITY_PORT_RIGHT &&
+ element != EL_SP_PORT_HORIZONTAL &&
+ element != EL_SP_PORT_ANY) ||
+ (dy == -1 &&
+ element != EL_SP_PORT_UP &&
+ element != EL_SP_GRAVITY_PORT_UP &&
+ element != EL_SP_PORT_VERTICAL &&
+ element != EL_SP_PORT_ANY) ||
+ (dy == +1 &&
+ element != EL_SP_PORT_DOWN &&
+ element != EL_SP_GRAVITY_PORT_DOWN &&
+ element != EL_SP_PORT_VERTICAL &&
+ element != EL_SP_PORT_ANY) ||
+ !IN_LEV_FIELD(nextx, nexty) ||
+ !IS_FREE(nextx, nexty))
+ return FALSE;
+
+ return TRUE;
+}
+
static void CheckGravityMovement(struct PlayerInfo *player)
{
if (game.gravity && !player->programmed_action)
#define SETUP_FILENAME "setup.cnf"
#define LEVELSETUP_FILENAME "lvlsetup.cnf"
#define EDITORSETUP_FILENAME "edsetup.cnf"
-#define HELPANIM_FILENAME "helpanim.conf"
-#define HELPTEXT_FILENAME "helptext.conf"
+#define HELPANIM_FILENAME "helpanim.cnf"
+#define HELPTEXT_FILENAME "helptext.cnf"
#define LEVELINFO_FILENAME "lvlinfo.cnf"
#define GRAPHICSINFO_FILENAME "gfxinfo.cnf"
#define SOUNDSINFO_FILENAME "sndinfo.cnf"
int num_elements; /* number of elements in this group */
short element[MAX_ELEMENTS_IN_GROUP]; /* list of elements in this group */
+ int choice_mode; /* how to choose element from group */
+
/* ---------- internal values used at runtime when playing ---------- */
/* the following is the same as above, but with recursively resolved group
elements (group elements may also contain further group elements!) */
int num_elements_resolved;
short element_resolved[NUM_FILE_ELEMENTS];
+
+ int choice_pos; /* current element choice position */
};
struct ElementInfo