The previous support for wrap-around levels in the EM game engine was
some sort of "idealized" implementation that lets the player wrap
around by moving horizontally on the same vertical level position
forever (which results in truely infinite wrap-around levels).
This may be nice and perfect, but has the disadvantage that the
original Emerald Mine Club engine did not work that way, making
existing EMC levels unplayable and/or unsolvable. (Examples are
level 80 of "Ruppelmine 3" or level 34 of "The Exception 2".)
Instead, the original game engine caused the player to step one
vertical position up or down when leaving the playfield at the left
or right border, which is required by the mentioned example levels.
This correction adds a flag that is set by default to use the original
behaviour.
cav.testmode = FALSE;
cav.teamwork = FALSE;
cav.infinite = TRUE;
cav.testmode = FALSE;
cav.teamwork = FALSE;
cav.infinite = TRUE;
+ cav.infinite_true = FALSE; // default: use original EMC behaviour
cav.ball_random = FALSE;
cav.ball_active = FALSE;
cav.ball_random = FALSE;
cav.ball_active = FALSE;
boolean testmode; /* flag for test mode */
boolean teamwork; /* flag for two player mode */
boolean infinite; /* flag for infinitely wide cave */
boolean testmode; /* flag for test mode */
boolean teamwork; /* flag for two player mode */
boolean infinite; /* flag for infinitely wide cave */
+ boolean infinite_true; /* flag for truely infinitely wide cave */
boolean ball_random; /* flag if ball is random */
boolean ball_active; /* flag if ball is already active */
boolean ball_random; /* flag if ball is random */
boolean ball_active; /* flag if ball is already active */
lev.bottom = lev.top + lev.height;
lev.infinite = game_em.use_wrap_around;
lev.bottom = lev.top + lev.height;
lev.infinite = game_em.use_wrap_around;
+ lev.infinite_true = cav.infinite_true;
if (lev.infinite)
{
/* add linked cave buffer columns for wrap-around movement */
for (x = 0; x < lev.left; x++)
{
if (lev.infinite)
{
/* add linked cave buffer columns for wrap-around movement */
for (x = 0; x < lev.left; x++)
{
- lev.cavecol[x] = lev.cavecol[lev.width + x];
- lev.nextcol[x] = lev.nextcol[lev.width + x];
- lev.drawcol[x] = lev.drawcol[lev.width + x];
- lev.boomcol[x] = lev.boomcol[lev.width + x];
-
- lev.cavecol[lev.right + x] = lev.cavecol[lev.left + x];
- lev.nextcol[lev.right + x] = lev.nextcol[lev.left + x];
- lev.drawcol[lev.right + x] = lev.drawcol[lev.left + x];
- lev.boomcol[lev.right + x] = lev.boomcol[lev.left + x];
+ int offset = (lev.infinite_true ? 0 : 1);
+
+ lev.cavecol[x] = &lev.cavecol[lev.width + x][-offset];
+ lev.nextcol[x] = &lev.nextcol[lev.width + x][-offset];
+ lev.drawcol[x] = &lev.drawcol[lev.width + x][-offset];
+ lev.boomcol[x] = &lev.boomcol[lev.width + x][-offset];
+
+ lev.cavecol[lev.right + x] = &lev.cavecol[lev.left + x][offset];
+ lev.nextcol[lev.right + x] = &lev.nextcol[lev.left + x][offset];
+ lev.drawcol[lev.right + x] = &lev.drawcol[lev.left + x][offset];
+ lev.boomcol[lev.right + x] = &lev.boomcol[lev.left + x][offset];
boolean testmode; /* test mode */
boolean infinite; /* flag for infinitely wide cave */
boolean testmode; /* test mode */
boolean infinite; /* flag for infinitely wide cave */
+ boolean infinite_true; /* flag for truely infinitely wide cave */
boolean killed_out_of_time; /* kill player due to time out */
int exit_x, exit_y; /* kludge for playing player exit sound */
boolean killed_out_of_time; /* kill player due to time out */
int exit_x, exit_y; /* kludge for playing player exit sound */
ply[nr].x = (ply[nr].x < lev.left ? lev.right - 1 : lev.left);
ply[nr].prev_x = ply[nr].x - dx;
ply[nr].x = (ply[nr].x < lev.left ? lev.right - 1 : lev.left);
ply[nr].prev_x = ply[nr].x - dx;
+ if (!lev.infinite_true)
+ {
+ int dy = ply[nr].y - ply[nr].prev_y;
+
+ ply[nr].y += (ply[nr].x == lev.left ? 1 : -1);
+ ply[nr].prev_y = ply[nr].y - dy;
+ }
+
/* draw player entering playfield from the opposite side */
blitplayer_ext(nr);
/* draw player entering playfield from the opposite side */
blitplayer_ext(nr);
if (draw_new_player_location_wrap)
{
if (draw_new_player_location_wrap)
{
- // when wrapping around (horizontally), keep vertical player position
- screen_yy = screen_y;
+ if (lev.infinite_true)
+ {
+ // when wrapping around (horizontally), keep vertical player position
+ screen_yy = screen_y;
+ }
// scrolling for wrapping should be faster than for switching players
wait_delay_value /= 4;
// scrolling for wrapping should be faster than for switching players
wait_delay_value /= 4;
{
ply[i].x = (ply[i].x < lev.left ? lev.right - 1 : lev.left);
{
ply[i].x = (ply[i].x < lev.left ? lev.right - 1 : lev.left);
+ if (!lev.infinite_true)
+ ply[i].y += (ply[i].x == lev.left ? 1 : -1);
+
game.centered_player_nr_next = i;
game.set_centered_player = TRUE;
game.set_centered_player_wrap = TRUE;
game.centered_player_nr_next = i;
game.set_centered_player = TRUE;
game.set_centered_player_wrap = TRUE;