projects
/
rocksndiamonds.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
fixed unexpected behaviour with solving levels with Sokoban elements
[rocksndiamonds.git]
/
src
/
game.c
diff --git
a/src/game.c
b/src/game.c
index 0d8c032e84028895eb27bfae62a633ce15c52251..4a3d1eef4d4e63bbe088da3b3209f31ce03088ad 100644
(file)
--- a/
src/game.c
+++ b/
src/game.c
@@
-1792,7
+1792,11
@@
static void InitField(int x, int y, boolean init_game)
break;
case EL_SOKOBAN_FIELD_EMPTY:
break;
case EL_SOKOBAN_FIELD_EMPTY:
- local_player->sokobanfields_still_needed++;
+ local_player->sokoban_fields_still_needed++;
+ break;
+
+ case EL_SOKOBAN_OBJECT:
+ local_player->sokoban_objects_still_needed++;
break;
case EL_STONEBLOCK:
break;
case EL_STONEBLOCK:
@@
-2046,8
+2050,8
@@
static int get_next_dropped_element(struct PlayerInfo *player)
static int get_inventory_element_from_pos(struct PlayerInfo *player, int pos)
{
static int get_inventory_element_from_pos(struct PlayerInfo *player, int pos)
{
- /
*
pos >= 0: get element from bottom of the stack;
- pos < 0: get element from top of the stack */
+ /
/
pos >= 0: get element from bottom of the stack;
+ // pos < 0: get element from top of the stack
if (pos < 0)
{
if (pos < 0)
{
@@
-2212,7
+2216,8
@@
static void UpdateGameControlValues(void)
game_mm.kettles_still_needed > 0 ||
game_mm.lights_still_needed > 0 :
local_player->gems_still_needed > 0 ||
game_mm.kettles_still_needed > 0 ||
game_mm.lights_still_needed > 0 :
local_player->gems_still_needed > 0 ||
- local_player->sokobanfields_still_needed > 0 ||
+ local_player->sokoban_fields_still_needed > 0 ||
+ local_player->sokoban_objects_still_needed > 0 ||
local_player->lights_still_needed > 0);
int health = (local_player->LevelSolved ?
local_player->LevelSolved_CountingHealth :
local_player->lights_still_needed > 0);
int health = (local_player->LevelSolved ?
local_player->LevelSolved_CountingHealth :
@@
-2381,9
+2386,9
@@
static void UpdateGameControlValues(void)
local_player->friends_still_needed;
game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
local_player->friends_still_needed;
game_panel_controls[GAME_PANEL_SOKOBAN_OBJECTS].value =
- local_player->sokoban
field
s_still_needed;
+ local_player->sokoban
_object
s_still_needed;
game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
game_panel_controls[GAME_PANEL_SOKOBAN_FIELDS].value =
- local_player->sokobanfields_still_needed;
+ local_player->sokoban
_
fields_still_needed;
game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
(game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
game_panel_controls[GAME_PANEL_ROBOT_WHEEL].value =
(game.robot_wheel_active ? EL_ROBOT_WHEEL_ACTIVE : EL_ROBOT_WHEEL);
@@
-2780,13
+2785,11
@@
void DrawGameDoorValues(void)
}
}
-/*
- =============================================================================
- InitGameEngine()
- -----------------------------------------------------------------------------
- initialize game engine due to level / tape version number
- =============================================================================
-*/
+// ============================================================================
+// InitGameEngine()
+// ----------------------------------------------------------------------------
+// initialize game engine due to level / tape version number
+// ============================================================================
static void InitGameEngine(void)
{
static void InitGameEngine(void)
{
@@
-3270,13
+3273,11
@@
static int get_num_special_action(int element, int action_first,
}
}
-/*
- =============================================================================
- InitGame()
- -----------------------------------------------------------------------------
- initialize and start new game
- =============================================================================
-*/
+// ============================================================================
+// InitGame()
+// ----------------------------------------------------------------------------
+// initialize and start new game
+// ============================================================================
#if DEBUG_INIT_PLAYER
static void DebugPrintPlayerStatus(char *message)
#if DEBUG_INIT_PLAYER
static void DebugPrintPlayerStatus(char *message)
@@
-3393,7
+3394,8
@@
void InitGame(void)
player->health_final = MAX_HEALTH;
player->gems_still_needed = level.gems_needed;
player->health_final = MAX_HEALTH;
player->gems_still_needed = level.gems_needed;
- player->sokobanfields_still_needed = 0;
+ player->sokoban_fields_still_needed = 0;
+ player->sokoban_objects_still_needed = 0;
player->lights_still_needed = 0;
player->players_still_needed = 0;
player->friends_still_needed = 0;
player->lights_still_needed = 0;
player->players_still_needed = 0;
player->friends_still_needed = 0;
@@
-3724,8
+3726,8
@@
void InitGame(void)
}
else if (network.enabled)
{
}
else if (network.enabled)
{
- /
*
add team mode players connected over the network (needed for correct
- assignment of player figures from level to locally playing players) */
+ /
/
add team mode players connected over the network (needed for correct
+ // assignment of player figures from level to locally playing players)
for (i = 0; i < MAX_PLAYERS; i++)
if (stored_player[i].connected_network)
for (i = 0; i < MAX_PLAYERS; i++)
if (stored_player[i].connected_network)
@@
-3733,8
+3735,8
@@
void InitGame(void)
}
else if (game.team_mode)
{
}
else if (game.team_mode)
{
- /
*
try to guess locally connected team mode players (needed for correct
- assignment of player figures from level to locally playing players) */
+ /
/
try to guess locally connected team mode players (needed for correct
+ // assignment of player figures from level to locally playing players)
for (i = 0; i < MAX_PLAYERS; i++)
if (setup.input[i].use_joystick ||
for (i = 0; i < MAX_PLAYERS; i++)
if (setup.input[i].use_joystick ||
@@
-4006,8
+4008,8
@@
void InitGame(void)
if (EVEN(SCR_FIELDY) && full_lev_fieldy > SCR_FIELDY)
SBY_Upper--;
if (EVEN(SCR_FIELDY) && full_lev_fieldy > SCR_FIELDY)
SBY_Upper--;
- /
*
if local player not found, look for custom element that might create
- the player (make some assumptions about the right custom element) */
+ /
/
if local player not found, look for custom element that might create
+ // the player (make some assumptions about the right custom element)
if (!local_player->present)
{
int start_x = 0, start_y = 0;
if (!local_player->present)
{
int start_x = 0, start_y = 0;
@@
-4893,9
+4895,9
@@
static void InitMovingField(int x, int y, int direction)
is_moving_before = (WasJustMoving[x][y] != 0);
is_moving_after = (getElementMoveStepsizeExt(x, y, direction) != 0);
is_moving_before = (WasJustMoving[x][y] != 0);
is_moving_after = (getElementMoveStepsizeExt(x, y, direction) != 0);
- /
*
reset animation only for moving elements which change direction of moving
-
or which just started or stopped moving
- (else CEs with property "can move" / "not moving" are reset each frame) */
+ /
/
reset animation only for moving elements which change direction of moving
+
//
or which just started or stopped moving
+ // (else CEs with property "can move" / "not moving" are reset each frame)
if (is_moving_before != is_moving_after ||
direction != MovDir[x][y])
ResetGfxAnimation(x, y);
if (is_moving_before != is_moving_after ||
direction != MovDir[x][y])
ResetGfxAnimation(x, y);
@@
-4970,9
+4972,9
@@
static int MovingOrBlocked2Element(int x, int y)
static int MovingOrBlocked2ElementIfNotLeaving(int x, int y)
{
static int MovingOrBlocked2ElementIfNotLeaving(int x, int y)
{
- /
*
like MovingOrBlocked2Element(), but if element is moving
-
and (x,y) is the field the moving element is just leaving,
- return EL_BLOCKED instead of the element value */
+ /
/
like MovingOrBlocked2Element(), but if element is moving
+
//
and (x,y) is the field the moving element is just leaving,
+ // return EL_BLOCKED instead of the element value
int element = Feld[x][y];
if (IS_MOVING(x, y))
int element = Feld[x][y];
if (IS_MOVING(x, y))
@@
-5026,9
+5028,9
@@
static void RemoveMovingField(int x, int y)
if (Feld[newx][newy] != EL_BLOCKED)
{
if (Feld[newx][newy] != EL_BLOCKED)
{
- /
*
element is moving, but target field is not free (blocked), but
-
already occupied by something different (example: acid pool);
- in this case, only remove the moving field, but not the target */
+ /
/
element is moving, but target field is not free (blocked), but
+
//
already occupied by something different (example: acid pool);
+ // in this case, only remove the moving field, but not the target
RemoveField(oldx, oldy);
RemoveField(oldx, oldy);
@@
-5493,8
+5495,8
@@
static void Explode(int ex, int ey, int phase, int mode)
Store[x][y] = EL_EMPTY;
}
Store[x][y] = EL_EMPTY;
}
- /
*
!!! check this case -- currently needed for rnd_rado_negundo_v,
- !!! levels 015 018 019 020 021 022 023 026 027 028 !!! */
+ /
/
!!! check this case -- currently needed for rnd_rado_negundo_v,
+ // !!! levels 015 018 019 020 021 022 023 026 027 028 !!!
else if (ELEM_IS_PLAYER(center_element))
Store[x][y] = EL_EMPTY;
else if (center_element == EL_YAMYAM)
else if (ELEM_IS_PLAYER(center_element))
Store[x][y] = EL_EMPTY;
else if (center_element == EL_YAMYAM)
@@
-5502,9
+5504,9
@@
static void Explode(int ex, int ey, int phase, int mode)
else if (element_info[center_element].content.e[xx][yy] != EL_EMPTY)
Store[x][y] = element_info[center_element].content.e[xx][yy];
#if 1
else if (element_info[center_element].content.e[xx][yy] != EL_EMPTY)
Store[x][y] = element_info[center_element].content.e[xx][yy];
#if 1
- /
*
needed because EL_BD_BUTTERFLY is not defined as "CAN_EXPLODE"
-
(killing EL_BD_BUTTERFLY with dynamite would result in BD diamond
- otherwise) -- FIX THIS !!! */
+ /
/
needed because EL_BD_BUTTERFLY is not defined as "CAN_EXPLODE"
+
//
(killing EL_BD_BUTTERFLY with dynamite would result in BD diamond
+ // otherwise) -- FIX THIS !!!
else if (!CAN_EXPLODE(element) && element != EL_BD_BUTTERFLY)
Store[x][y] = element_info[element].content.e[1][1];
#else
else if (!CAN_EXPLODE(element) && element != EL_BD_BUTTERFLY)
Store[x][y] = element_info[element].content.e[1][1];
#else
@@
-5580,9
+5582,9
@@
static void Explode(int ex, int ey, int phase, int mode)
border_explosion = TRUE;
}
border_explosion = TRUE;
}
- /
*
if an element just explodes due to another explosion (chain-reaction),
-
do not immediately end the new explosion when it was the last frame of
- the explosion (as it would be done in the following "if"-statement!) */
+ /
/
if an element just explodes due to another explosion (chain-reaction),
+
//
do not immediately end the new explosion when it was the last frame of
+ // the explosion (as it would be done in the following "if"-statement!)
if (border_explosion && phase == last_phase)
return;
}
if (border_explosion && phase == last_phase)
return;
}
@@
-7781,8
+7783,8
@@
static void StartMoving(int x, int y)
if (!MovDelay[x][y]) // start new movement phase
{
if (!MovDelay[x][y]) // start new movement phase
{
- /
*
all objects that can change their move direction after each step
- (YAMYAM, DARK_YAMYAM and PACMAN go straight until they hit a wall */
+ /
/
all objects that can change their move direction after each step
+ // (YAMYAM, DARK_YAMYAM and PACMAN go straight until they hit a wall
if (element != EL_YAMYAM &&
element != EL_DARK_YAMYAM &&
if (element != EL_YAMYAM &&
element != EL_DARK_YAMYAM &&
@@
-8729,8
+8731,8
@@
static void AmoebaDisappearing(int x, int y)
Feld[x][y] = EL_EMPTY;
TEST_DrawLevelField(x, y);
Feld[x][y] = EL_EMPTY;
TEST_DrawLevelField(x, y);
- /
*
don't let mole enter this field in this cycle;
- (give priority to objects falling to this field from above) */
+ /
/
don't let mole enter this field in this cycle;
+ // (give priority to objects falling to this field from above)
Stop[x][y] = TRUE;
}
}
Stop[x][y] = TRUE;
}
}
@@
-9057,7
+9059,8
@@
static void ActivateMagicBall(int bx, int by)
static void CheckExit(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
static void CheckExit(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
- local_player->sokobanfields_still_needed > 0 ||
+ local_player->sokoban_fields_still_needed > 0 ||
+ local_player->sokoban_objects_still_needed > 0 ||
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
@@
-9080,7
+9083,8
@@
static void CheckExit(int x, int y)
static void CheckExitEM(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
static void CheckExitEM(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
- local_player->sokobanfields_still_needed > 0 ||
+ local_player->sokoban_fields_still_needed > 0 ||
+ local_player->sokoban_objects_still_needed > 0 ||
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
@@
-9103,7
+9107,8
@@
static void CheckExitEM(int x, int y)
static void CheckExitSteel(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
static void CheckExitSteel(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
- local_player->sokobanfields_still_needed > 0 ||
+ local_player->sokoban_fields_still_needed > 0 ||
+ local_player->sokoban_objects_still_needed > 0 ||
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
@@
-9126,7
+9131,8
@@
static void CheckExitSteel(int x, int y)
static void CheckExitSteelEM(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
static void CheckExitSteelEM(int x, int y)
{
if (local_player->gems_still_needed > 0 ||
- local_player->sokobanfields_still_needed > 0 ||
+ local_player->sokoban_fields_still_needed > 0 ||
+ local_player->sokoban_objects_still_needed > 0 ||
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
local_player->lights_still_needed > 0)
{
int element = Feld[x][y];
@@
-10217,8
+10223,8
@@
static void CreateFieldExt(int x, int y, int element, boolean is_change)
TEST_DrawLevelFieldCrumbledNeighbours(x, y);
}
TEST_DrawLevelFieldCrumbledNeighbours(x, y);
}
- /
*
check if element under the player changes from accessible to unaccessible
- (needed for special case of dropping element which then changes) */
+ /
/
check if element under the player changes from accessible to unaccessible
+ // (needed for special case of dropping element which then changes)
// (must be checked after creating new element for walkable group elements)
if (IS_PLAYER(x, y) && !player_explosion_protected &&
IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element))
// (must be checked after creating new element for walkable group elements)
if (IS_PLAYER(x, y) && !player_explosion_protected &&
IS_ACCESSIBLE(old_element) && !IS_ACCESSIBLE(new_element))
@@
-10253,8
+10259,8
@@
static void CreateElementFromChange(int x, int y, int element)
{
int old_element = Feld[x][y];
{
int old_element = Feld[x][y];
- /
*
prevent changed element from moving in same engine frame
- unless both old and new element can either fall or move */
+ /
/
prevent changed element from moving in same engine frame
+ // unless both old and new element can either fall or move
if ((!CAN_FALL(old_element) || !CAN_FALL(element)) &&
(!CAN_MOVE(old_element) || !CAN_MOVE(element)))
Stop[x][y] = TRUE;
if ((!CAN_FALL(old_element) || !CAN_FALL(element)) &&
(!CAN_MOVE(old_element) || !CAN_MOVE(element)))
Stop[x][y] = TRUE;
@@
-10507,8
+10513,8
@@
static void HandleElementChange(int x, int y, int page)
This can also be seen from the debug output for this test element.)
*/
This can also be seen from the debug output for this test element.)
*/
- /
*
when a custom element is about to change (for example by change delay),
- do not reset graphic animation when the custom element is moving */
+ /
/
when a custom element is about to change (for example by change delay),
+ // do not reset graphic animation when the custom element is moving
if (game.graphics_engine_version < 4 &&
!IS_MOVING(x, y))
{
if (game.graphics_engine_version < 4 &&
!IS_MOVING(x, y))
{
@@
-10629,9
+10635,9
@@
static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
{
if (change->can_change && !change_done)
{
{
if (change->can_change && !change_done)
{
- /
*
if element already changed in this frame, not only prevent
-
another element change (checked in ChangeElement()), but
- also prevent additional element actions for this element */
+ /
/
if element already changed in this frame, not only prevent
+
//
another element change (checked in ChangeElement()), but
+ // also prevent additional element actions for this element
if (ChangeCount[x][y] >= game.max_num_changes_per_frame &&
!level.use_action_after_change_bug)
if (ChangeCount[x][y] >= game.max_num_changes_per_frame &&
!level.use_action_after_change_bug)
@@
-10644,9
+10650,9
@@
static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y,
}
else if (change->has_action)
{
}
else if (change->has_action)
{
- /
*
if element already changed in this frame, not only prevent
-
another element change (checked in ChangeElement()), but
- also prevent additional element actions for this element */
+ /
/
if element already changed in this frame, not only prevent
+
//
another element change (checked in ChangeElement()), but
+ // also prevent additional element actions for this element
if (ChangeCount[x][y] >= game.max_num_changes_per_frame &&
!level.use_action_after_change_bug)
if (ChangeCount[x][y] >= game.max_num_changes_per_frame &&
!level.use_action_after_change_bug)
@@
-13937,16
+13943,24
@@
static int DigField(struct PlayerInfo *player,
if (IS_SB_ELEMENT(element))
{
if (IS_SB_ELEMENT(element))
{
+ boolean sokoban_task_solved = FALSE;
+
if (element == EL_SOKOBAN_FIELD_FULL)
{
Back[x][y] = EL_SOKOBAN_FIELD_EMPTY;
if (element == EL_SOKOBAN_FIELD_FULL)
{
Back[x][y] = EL_SOKOBAN_FIELD_EMPTY;
- local_player->sokobanfields_still_needed++;
+ local_player->sokoban_fields_still_needed++;
+ local_player->sokoban_objects_still_needed++;
}
if (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY)
{
Back[nextx][nexty] = EL_SOKOBAN_FIELD_EMPTY;
}
if (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY)
{
Back[nextx][nexty] = EL_SOKOBAN_FIELD_EMPTY;
- local_player->sokobanfields_still_needed--;
+ local_player->sokoban_fields_still_needed--;
+ local_player->sokoban_objects_still_needed--;
+
+ // sokoban object was pushed from empty field to sokoban field
+ if (Back[x][y] == EL_EMPTY)
+ sokoban_task_solved = TRUE;
}
Feld[x][y] = EL_SOKOBAN_OBJECT;
}
Feld[x][y] = EL_SOKOBAN_OBJECT;
@@
-13960,12
+13974,14
@@
static int DigField(struct PlayerInfo *player,
PlayLevelSoundElementAction(nextx, nexty, EL_SOKOBAN_FIELD_EMPTY,
ACTION_FILLING);
PlayLevelSoundElementAction(nextx, nexty, EL_SOKOBAN_FIELD_EMPTY,
ACTION_FILLING);
- if (local_player->sokobanfields_still_needed == 0 &&
+ if (sokoban_task_solved &&
+ local_player->sokoban_fields_still_needed == 0 &&
+ local_player->sokoban_objects_still_needed == 0 &&
(game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban))
{
local_player->players_still_needed = 0;
(game.emulation == EMU_SOKOBAN || level.auto_exit_sokoban))
{
local_player->players_still_needed = 0;
- PlayerWins(player);
+ PlayerWins(
local_
player);
PlayLevelSound(x, y, SND_GAME_SOKOBAN_SOLVING);
}
PlayLevelSound(x, y, SND_GAME_SOKOBAN_SOLVING);
}