#define GAME_PANEL_KEY_WHITE 27
#define GAME_PANEL_KEY_WHITE_COUNT 28
#define GAME_PANEL_SCORE 29
-#define GAME_PANEL_TIME 30
-#define GAME_PANEL_TIME_HH 31
-#define GAME_PANEL_TIME_MM 32
-#define GAME_PANEL_TIME_SS 33
-#define GAME_PANEL_SHIELD_NORMAL 34
-#define GAME_PANEL_SHIELD_NORMAL_TIME 35
-#define GAME_PANEL_SHIELD_DEADLY 36
-#define GAME_PANEL_SHIELD_DEADLY_TIME 37
-#define GAME_PANEL_EXIT 38
-#define GAME_PANEL_EMC_MAGIC_BALL 39
-#define GAME_PANEL_EMC_MAGIC_BALL_SWITCH 40
-#define GAME_PANEL_LIGHT_SWITCH 41
-#define GAME_PANEL_LIGHT_SWITCH_TIME 42
-#define GAME_PANEL_TIMEGATE_SWITCH 43
-#define GAME_PANEL_TIMEGATE_SWITCH_TIME 44
-#define GAME_PANEL_SWITCHGATE_SWITCH 45
-#define GAME_PANEL_EMC_LENSES 46
-#define GAME_PANEL_EMC_LENSES_TIME 47
-#define GAME_PANEL_EMC_MAGNIFIER 48
-#define GAME_PANEL_EMC_MAGNIFIER_TIME 49
-#define GAME_PANEL_BALLOON_SWITCH 50
-#define GAME_PANEL_DYNABOMB_NUMBER 51
-#define GAME_PANEL_DYNABOMB_SIZE 52
-#define GAME_PANEL_DYNABOMB_POWER 53
-#define GAME_PANEL_PENGUINS 54
-#define GAME_PANEL_SOKOBAN_OBJECTS 55
-#define GAME_PANEL_SOKOBAN_FIELDS 56
-#define GAME_PANEL_ROBOT_WHEEL 57
-#define GAME_PANEL_CONVEYOR_BELT_1 58
-#define GAME_PANEL_CONVEYOR_BELT_2 59
-#define GAME_PANEL_CONVEYOR_BELT_3 60
-#define GAME_PANEL_CONVEYOR_BELT_4 61
-#define GAME_PANEL_CONVEYOR_BELT_1_SWITCH 62
-#define GAME_PANEL_CONVEYOR_BELT_2_SWITCH 63
-#define GAME_PANEL_CONVEYOR_BELT_3_SWITCH 64
-#define GAME_PANEL_CONVEYOR_BELT_4_SWITCH 65
-#define GAME_PANEL_MAGIC_WALL 66
-#define GAME_PANEL_MAGIC_WALL_TIME 67
-#define GAME_PANEL_GRAVITY_STATE 68
-#define GAME_PANEL_GRAPHIC_1 69
-#define GAME_PANEL_GRAPHIC_2 70
-#define GAME_PANEL_GRAPHIC_3 71
-#define GAME_PANEL_GRAPHIC_4 72
-#define GAME_PANEL_GRAPHIC_5 73
-#define GAME_PANEL_GRAPHIC_6 74
-#define GAME_PANEL_GRAPHIC_7 75
-#define GAME_PANEL_GRAPHIC_8 76
-#define GAME_PANEL_ELEMENT_1 77
-#define GAME_PANEL_ELEMENT_2 78
-#define GAME_PANEL_ELEMENT_3 79
-#define GAME_PANEL_ELEMENT_4 80
-#define GAME_PANEL_ELEMENT_5 81
-#define GAME_PANEL_ELEMENT_6 82
-#define GAME_PANEL_ELEMENT_7 83
-#define GAME_PANEL_ELEMENT_8 84
-#define GAME_PANEL_ELEMENT_COUNT_1 85
-#define GAME_PANEL_ELEMENT_COUNT_2 86
-#define GAME_PANEL_ELEMENT_COUNT_3 87
-#define GAME_PANEL_ELEMENT_COUNT_4 88
-#define GAME_PANEL_ELEMENT_COUNT_5 89
-#define GAME_PANEL_ELEMENT_COUNT_6 90
-#define GAME_PANEL_ELEMENT_COUNT_7 91
-#define GAME_PANEL_ELEMENT_COUNT_8 92
-#define GAME_PANEL_CE_SCORE_1 93
-#define GAME_PANEL_CE_SCORE_2 94
-#define GAME_PANEL_CE_SCORE_3 95
-#define GAME_PANEL_CE_SCORE_4 96
-#define GAME_PANEL_CE_SCORE_5 97
-#define GAME_PANEL_CE_SCORE_6 98
-#define GAME_PANEL_CE_SCORE_7 99
-#define GAME_PANEL_CE_SCORE_8 100
-#define GAME_PANEL_CE_SCORE_1_ELEMENT 101
-#define GAME_PANEL_CE_SCORE_2_ELEMENT 102
-#define GAME_PANEL_CE_SCORE_3_ELEMENT 103
-#define GAME_PANEL_CE_SCORE_4_ELEMENT 104
-#define GAME_PANEL_CE_SCORE_5_ELEMENT 105
-#define GAME_PANEL_CE_SCORE_6_ELEMENT 106
-#define GAME_PANEL_CE_SCORE_7_ELEMENT 107
-#define GAME_PANEL_CE_SCORE_8_ELEMENT 108
-#define GAME_PANEL_PLAYER_NAME 109
-#define GAME_PANEL_LEVEL_NAME 110
-#define GAME_PANEL_LEVEL_AUTHOR 111
-
-#define NUM_GAME_PANEL_CONTROLS 112
+#define GAME_PANEL_HIGHSCORE 30
+#define GAME_PANEL_TIME 31
+#define GAME_PANEL_TIME_HH 32
+#define GAME_PANEL_TIME_MM 33
+#define GAME_PANEL_TIME_SS 34
+#define GAME_PANEL_SHIELD_NORMAL 35
+#define GAME_PANEL_SHIELD_NORMAL_TIME 36
+#define GAME_PANEL_SHIELD_DEADLY 37
+#define GAME_PANEL_SHIELD_DEADLY_TIME 38
+#define GAME_PANEL_EXIT 39
+#define GAME_PANEL_EMC_MAGIC_BALL 40
+#define GAME_PANEL_EMC_MAGIC_BALL_SWITCH 41
+#define GAME_PANEL_LIGHT_SWITCH 42
+#define GAME_PANEL_LIGHT_SWITCH_TIME 43
+#define GAME_PANEL_TIMEGATE_SWITCH 44
+#define GAME_PANEL_TIMEGATE_SWITCH_TIME 45
+#define GAME_PANEL_SWITCHGATE_SWITCH 46
+#define GAME_PANEL_EMC_LENSES 47
+#define GAME_PANEL_EMC_LENSES_TIME 48
+#define GAME_PANEL_EMC_MAGNIFIER 49
+#define GAME_PANEL_EMC_MAGNIFIER_TIME 50
+#define GAME_PANEL_BALLOON_SWITCH 51
+#define GAME_PANEL_DYNABOMB_NUMBER 52
+#define GAME_PANEL_DYNABOMB_SIZE 53
+#define GAME_PANEL_DYNABOMB_POWER 54
+#define GAME_PANEL_PENGUINS 55
+#define GAME_PANEL_SOKOBAN_OBJECTS 56
+#define GAME_PANEL_SOKOBAN_FIELDS 57
+#define GAME_PANEL_ROBOT_WHEEL 58
+#define GAME_PANEL_CONVEYOR_BELT_1 59
+#define GAME_PANEL_CONVEYOR_BELT_2 60
+#define GAME_PANEL_CONVEYOR_BELT_3 61
+#define GAME_PANEL_CONVEYOR_BELT_4 62
+#define GAME_PANEL_CONVEYOR_BELT_1_SWITCH 63
+#define GAME_PANEL_CONVEYOR_BELT_2_SWITCH 64
+#define GAME_PANEL_CONVEYOR_BELT_3_SWITCH 65
+#define GAME_PANEL_CONVEYOR_BELT_4_SWITCH 66
+#define GAME_PANEL_MAGIC_WALL 67
+#define GAME_PANEL_MAGIC_WALL_TIME 68
+#define GAME_PANEL_GRAVITY_STATE 69
+#define GAME_PANEL_GRAPHIC_1 70
+#define GAME_PANEL_GRAPHIC_2 71
+#define GAME_PANEL_GRAPHIC_3 72
+#define GAME_PANEL_GRAPHIC_4 73
+#define GAME_PANEL_GRAPHIC_5 74
+#define GAME_PANEL_GRAPHIC_6 75
+#define GAME_PANEL_GRAPHIC_7 76
+#define GAME_PANEL_GRAPHIC_8 77
+#define GAME_PANEL_ELEMENT_1 78
+#define GAME_PANEL_ELEMENT_2 79
+#define GAME_PANEL_ELEMENT_3 80
+#define GAME_PANEL_ELEMENT_4 81
+#define GAME_PANEL_ELEMENT_5 82
+#define GAME_PANEL_ELEMENT_6 83
+#define GAME_PANEL_ELEMENT_7 84
+#define GAME_PANEL_ELEMENT_8 85
+#define GAME_PANEL_ELEMENT_COUNT_1 86
+#define GAME_PANEL_ELEMENT_COUNT_2 87
+#define GAME_PANEL_ELEMENT_COUNT_3 88
+#define GAME_PANEL_ELEMENT_COUNT_4 89
+#define GAME_PANEL_ELEMENT_COUNT_5 90
+#define GAME_PANEL_ELEMENT_COUNT_6 91
+#define GAME_PANEL_ELEMENT_COUNT_7 92
+#define GAME_PANEL_ELEMENT_COUNT_8 93
+#define GAME_PANEL_CE_SCORE_1 94
+#define GAME_PANEL_CE_SCORE_2 95
+#define GAME_PANEL_CE_SCORE_3 96
+#define GAME_PANEL_CE_SCORE_4 97
+#define GAME_PANEL_CE_SCORE_5 98
+#define GAME_PANEL_CE_SCORE_6 99
+#define GAME_PANEL_CE_SCORE_7 100
+#define GAME_PANEL_CE_SCORE_8 101
+#define GAME_PANEL_CE_SCORE_1_ELEMENT 102
+#define GAME_PANEL_CE_SCORE_2_ELEMENT 103
+#define GAME_PANEL_CE_SCORE_3_ELEMENT 104
+#define GAME_PANEL_CE_SCORE_4_ELEMENT 105
+#define GAME_PANEL_CE_SCORE_5_ELEMENT 106
+#define GAME_PANEL_CE_SCORE_6_ELEMENT 107
+#define GAME_PANEL_CE_SCORE_7_ELEMENT 108
+#define GAME_PANEL_CE_SCORE_8_ELEMENT 109
+#define GAME_PANEL_PLAYER_NAME 110
+#define GAME_PANEL_LEVEL_NAME 111
+#define GAME_PANEL_LEVEL_AUTHOR 112
+
+#define NUM_GAME_PANEL_CONTROLS 113
struct GamePanelOrderInfo
{
&game.panel.score,
TYPE_INTEGER,
},
+ {
+ GAME_PANEL_HIGHSCORE,
+ &game.panel.highscore,
+ TYPE_INTEGER,
+ },
{
GAME_PANEL_TIME,
&game.panel.time,
static void ScrollPlayer(struct PlayerInfo *, int);
static void ScrollScreen(struct PlayerInfo *, int);
-int DigField(struct PlayerInfo *, int, int, int, int, int, int, int);
+static int DigField(struct PlayerInfo *, int, int, int, int, int, int, int);
+static boolean DigFieldByCE(int, int, int);
+static boolean SnapField(struct PlayerInfo *, int, int);
+static boolean DropElement(struct PlayerInfo *);
static void InitBeltMovement(void);
static void CloseAllOpenTimegates(void);
void BuryPlayer(struct PlayerInfo *);
void RemovePlayer(struct PlayerInfo *);
-boolean SnapField(struct PlayerInfo *, int, int);
-boolean DropElement(struct PlayerInfo *);
-
static int getInvisibleActiveFromInvisibleElement(int);
static int getInvisibleFromInvisibleActiveElement(int);
Feld[x][y] = EL_EMC_MAGIC_BALL_SWITCH_ACTIVE;
break;
+ case EL_TRIGGER_PLAYER:
+ case EL_TRIGGER_ELEMENT:
+ case EL_TRIGGER_CE_VALUE:
+ case EL_TRIGGER_CE_SCORE:
+ case EL_SELF:
+ case EL_ANY_ELEMENT:
+ case EL_CURRENT_CE_VALUE:
+ case EL_CURRENT_CE_SCORE:
+ case EL_PREV_CE_1:
+ case EL_PREV_CE_2:
+ case EL_PREV_CE_3:
+ case EL_PREV_CE_4:
+ case EL_PREV_CE_5:
+ case EL_PREV_CE_6:
+ case EL_PREV_CE_7:
+ case EL_PREV_CE_8:
+ case EL_NEXT_CE_1:
+ case EL_NEXT_CE_2:
+ case EL_NEXT_CE_3:
+ case EL_NEXT_CE_4:
+ case EL_NEXT_CE_5:
+ case EL_NEXT_CE_6:
+ case EL_NEXT_CE_7:
+ case EL_NEXT_CE_8:
+ /* reference elements should not be used on the playfield */
+ Feld[x][y] = EL_EMPTY;
+ break;
+
default:
if (IS_CUSTOM_ELEMENT(element))
{
if (nr != i)
{
- Error(ERR_INFO, "'game_panel_controls' structure corrupted");
+ Error(ERR_INFO, "'game_panel_controls' structure corrupted at %d", i);
Error(ERR_EXIT, "this should not happen -- please debug");
}
}
game_panel_controls[GAME_PANEL_SCORE].value = score;
+ game_panel_controls[GAME_PANEL_HIGHSCORE].value = highscore[0].Score;
game_panel_controls[GAME_PANEL_TIME].value = time;
game_status = GAME_MODE_PLAYING;
}
+void UpdateAndDisplayGameControlValues()
+{
+ if (tape.warp_forward)
+ return;
+
+ UpdateGameControlValues();
+ DisplayGameControlValues();
+}
+
void DrawGameValue_Emeralds(int value)
{
struct TextPosInfo *pos = &game.panel.gems;
SET_PROPERTY(ch_delay->element, EP_CAN_CHANGE_OR_HAS_ACTION, TRUE);
}
- /* ---------- initialize internal run-time variables ------------- */
+ /* ---------- initialize internal run-time variables --------------------- */
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
{
}
}
+#if 1
+ /* ---------- initialize reference elements in change conditions --------- */
+
+ for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
+ {
+ int element = EL_CUSTOM_START + i;
+ struct ElementInfo *ei = &element_info[element];
+
+ for (j = 0; j < ei->num_change_pages; j++)
+ {
+ int trigger_element = ei->change_page[j].initial_trigger_element;
+
+ if (trigger_element >= EL_PREV_CE_8 &&
+ trigger_element <= EL_NEXT_CE_8)
+ trigger_element = RESOLVED_REFERENCE_ELEMENT(element, trigger_element);
+
+ ei->change_page[j].trigger_element = trigger_element;
+ }
+ }
+#endif
+
/* ---------- initialize run-time trigger player and element ------------- */
for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++)
SetPanelBackground();
SetDrawBackgroundMask(REDRAW_DOOR_1);
+#if 1
+ UpdateAndDisplayGameControlValues();
+#else
UpdateGameDoorValues();
DrawGameDoorValues();
+#endif
if (!game.restart_level)
{
else if (Feld[x][y + 1] == EL_QUICKSAND_EMPTY)
{
if (!MovDelay[x][y])
+ {
MovDelay[x][y] = TILEY + 1;
+ ResetGfxAnimation(x, y);
+ ResetGfxAnimation(x, y + 1);
+ }
+
if (MovDelay[x][y])
{
+ DrawLevelElement(x, y, EL_QUICKSAND_EMPTYING);
+ DrawLevelElement(x, y + 1, EL_QUICKSAND_FILLING);
+
MovDelay[x][y]--;
if (MovDelay[x][y])
return;
Store[x][y + 1] = Store[x][y];
Store[x][y] = 0;
+ PlayLevelSoundAction(x, y, ACTION_FILLING);
+ }
+ else if (Feld[x][y + 1] == EL_QUICKSAND_FAST_EMPTY)
+ {
+ if (!MovDelay[x][y])
+ {
+ MovDelay[x][y] = TILEY + 1;
+
+ ResetGfxAnimation(x, y);
+ ResetGfxAnimation(x, y + 1);
+ }
+
+ if (MovDelay[x][y])
+ {
+ DrawLevelElement(x, y, EL_QUICKSAND_EMPTYING);
+ DrawLevelElement(x, y + 1, EL_QUICKSAND_FAST_FILLING);
+
+ MovDelay[x][y]--;
+ if (MovDelay[x][y])
+ return;
+ }
+
+ Feld[x][y] = EL_QUICKSAND_EMPTY;
+ Feld[x][y + 1] = EL_QUICKSAND_FAST_FULL;
+ Store[x][y + 1] = Store[x][y];
+ Store[x][y] = 0;
+
PlayLevelSoundAction(x, y, ACTION_FILLING);
}
}
else if (Feld[x][y + 1] == EL_QUICKSAND_FAST_EMPTY)
{
if (!MovDelay[x][y])
+ {
MovDelay[x][y] = TILEY + 1;
+ ResetGfxAnimation(x, y);
+ ResetGfxAnimation(x, y + 1);
+ }
+
if (MovDelay[x][y])
{
+ DrawLevelElement(x, y, EL_QUICKSAND_FAST_EMPTYING);
+ DrawLevelElement(x, y + 1, EL_QUICKSAND_FAST_FILLING);
+
MovDelay[x][y]--;
if (MovDelay[x][y])
return;
Store[x][y + 1] = Store[x][y];
Store[x][y] = 0;
+ PlayLevelSoundAction(x, y, ACTION_FILLING);
+ }
+ else if (Feld[x][y + 1] == EL_QUICKSAND_EMPTY)
+ {
+ if (!MovDelay[x][y])
+ {
+ MovDelay[x][y] = TILEY + 1;
+
+ ResetGfxAnimation(x, y);
+ ResetGfxAnimation(x, y + 1);
+ }
+
+ if (MovDelay[x][y])
+ {
+ DrawLevelElement(x, y, EL_QUICKSAND_FAST_EMPTYING);
+ DrawLevelElement(x, y + 1, EL_QUICKSAND_FILLING);
+
+ MovDelay[x][y]--;
+ if (MovDelay[x][y])
+ return;
+ }
+
+ Feld[x][y] = EL_QUICKSAND_FAST_EMPTY;
+ Feld[x][y + 1] = EL_QUICKSAND_FULL;
+ Store[x][y + 1] = Store[x][y];
+ Store[x][y] = 0;
+
PlayLevelSoundAction(x, y, ACTION_FILLING);
}
}
else if (IS_CUSTOM_ELEMENT(element) &&
CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, newx, newy))
{
+#if 1
+ if (!DigFieldByCE(newx, newy, element))
+ return;
+#else
int new_element = Feld[newx][newy];
if (!IS_FREE(newx, newy))
}
Store[newx][newy] = EL_EMPTY;
+
#if 1
/* this makes it possible to leave the removed element again */
if (IS_EQUAL_OR_IN_GROUP(new_element, MOVE_ENTER_EL(element)))
Store[newx][newy] = (move_leave_element == EL_TRIGGER_ELEMENT ?
new_element : move_leave_element);
}
+#endif
+
#endif
if (move_pattern & MV_MAZE_RUNNER_STYLE)
}
#if USE_NEW_CUSTOM_VALUE
- CustomValue[newx][newy] = CustomValue[x][y];
+ CustomValue[newx][newy] = CustomValue[x][y];
#endif
ChangeDelay[x][y] = 0;
element == EL_EXPANDABLE_STEELWALL_HORIZONTAL) &&
((links_massiv && rechts_massiv) ||
element == EL_EXPANDABLE_STEELWALL_VERTICAL))
- Feld[ax][ay] = EL_WALL;
+ Feld[ax][ay] = EL_STEELWALL;
if (new_wall)
PlayLevelSoundAction(ax, ay, ACTION_GROWING);
DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime);
}
+#if 1
+ UpdateAndDisplayGameControlValues();
+#else
UpdateGameDoorValues();
DrawGameDoorValues();
+#endif
}
void AdvanceFrameAndPlayerCounters(int player_nr)
=============================================================================
*/
-int DigField(struct PlayerInfo *player,
- int oldx, int oldy, int x, int y,
- int real_dx, int real_dy, int mode)
+static int DigField(struct PlayerInfo *player,
+ int oldx, int oldy, int x, int y,
+ int real_dx, int real_dy, int mode)
{
boolean is_player = (IS_PLAYER(oldx, oldy) || mode != DF_DIG);
boolean player_was_pushing = player->is_pushing;
if (!(IN_LEV_FIELD(nextx, nexty) &&
(IS_FREE(nextx, nexty) ||
- (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY &&
- IS_SB_ELEMENT(element)))))
+ (IS_SB_ELEMENT(element) &&
+ Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY) ||
+ (IS_CUSTOM_ELEMENT(element) &&
+ CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, nextx, nexty)))))
return MP_NO_ACTION;
if (!checkDiagonalPushing(player, x, y, real_dx, real_dy))
return MP_NO_ACTION;
}
+ if (IS_CUSTOM_ELEMENT(element) &&
+ CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, nextx, nexty))
+ {
+ if (!DigFieldByCE(nextx, nexty, element))
+ return MP_NO_ACTION;
+ }
+
if (IS_SB_ELEMENT(element))
{
if (element == EL_SOKOBAN_FIELD_FULL)
return MP_MOVING;
}
-boolean SnapField(struct PlayerInfo *player, int dx, int dy)
+static boolean DigFieldByCE(int x, int y, int digging_element)
+{
+ int element = Feld[x][y];
+
+ if (!IS_FREE(x, y))
+ {
+ int action = (IS_DIGGABLE(element) ? ACTION_DIGGING :
+ IS_COLLECTIBLE(element) ? ACTION_COLLECTING :
+ ACTION_BREAKING);
+
+ /* no element can dig solid indestructible elements */
+ if (IS_INDESTRUCTIBLE(element) &&
+ !IS_DIGGABLE(element) &&
+ !IS_COLLECTIBLE(element))
+ return FALSE;
+
+ if (AmoebaNr[x][y] &&
+ (element == EL_AMOEBA_FULL ||
+ element == EL_BD_AMOEBA ||
+ element == EL_AMOEBA_GROWING))
+ {
+ AmoebaCnt[AmoebaNr[x][y]]--;
+ AmoebaCnt2[AmoebaNr[x][y]]--;
+ }
+
+ if (IS_MOVING(x, y))
+ RemoveMovingField(x, y);
+ else
+ {
+ RemoveField(x, y);
+ DrawLevelField(x, y);
+ }
+
+ /* if digged element was about to explode, prevent the explosion */
+ ExplodeField[x][y] = EX_TYPE_NONE;
+
+ PlayLevelSoundAction(x, y, action);
+ }
+
+ Store[x][y] = EL_EMPTY;
+
+#if 1
+ /* this makes it possible to leave the removed element again */
+ if (IS_EQUAL_OR_IN_GROUP(element, MOVE_ENTER_EL(digging_element)))
+ Store[x][y] = element;
+#else
+ if (IS_EQUAL_OR_IN_GROUP(element, MOVE_ENTER_EL(digging_element)))
+ {
+ int move_leave_element = element_info[digging_element].move_leave_element;
+
+ /* this makes it possible to leave the removed element again */
+ Store[x][y] = (move_leave_element == EL_TRIGGER_ELEMENT ?
+ element : move_leave_element);
+ }
+#endif
+
+ return TRUE;
+}
+
+static boolean SnapField(struct PlayerInfo *player, int dx, int dy)
{
int jx = player->jx, jy = player->jy;
int x = jx + dx, y = jy + dy;
return TRUE;
}
-boolean DropElement(struct PlayerInfo *player)
+static boolean DropElement(struct PlayerInfo *player)
{
int old_element, new_element;
int dropx = player->jx, dropy = player->jy;