X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=7e5350234b25ac6bffbcd0e09fceaa3460a89954;hb=ed9b77daec8c9dbddc04f08c6f2de24135415e44;hp=1079966e2d26079c20bbf2dbc6bda86a0c212009;hpb=b33f14a8bdad5e3c9547c37b3854025daba761c7;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 1079966e..7e535023 100644 --- a/src/game.c +++ b/src/game.c @@ -161,90 +161,91 @@ #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 { @@ -419,6 +420,11 @@ static struct GamePanelControlInfo game_panel_controls[] = &game.panel.score, TYPE_INTEGER, }, + { + GAME_PANEL_HIGHSCORE, + &game.panel.highscore, + TYPE_INTEGER, + }, { GAME_PANEL_TIME, &game.panel.time, @@ -896,6 +902,9 @@ static struct GamePanelControlInfo game_panel_controls[] = (be) + (e) - EL_SELF > EL_CUSTOM_END ? EL_CUSTOM_END : \ (be) + (e) - EL_SELF) +#define GET_PLAYER_FROM_BITS(p) \ + (EL_PLAYER_1 + ((p) != PLAYER_BITS_ANY ? log_2(p) : 0)) + #define GET_TARGET_ELEMENT(be, e, ch, cv, cs) \ ((e) == EL_TRIGGER_PLAYER ? (ch)->actual_trigger_player : \ (e) == EL_TRIGGER_ELEMENT ? (ch)->actual_trigger_element : \ @@ -1024,7 +1033,10 @@ static boolean MovePlayer(struct PlayerInfo *, int, int); 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); @@ -1096,9 +1108,6 @@ void KillPlayer(struct PlayerInfo *); 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); @@ -1934,6 +1943,34 @@ static void InitField(int x, int y, boolean init_game) 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)) { @@ -2075,7 +2112,7 @@ void InitGameControlValues() 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"); } @@ -2108,8 +2145,17 @@ void InitGameControlValues() void UpdatePlayfieldElementCount() { + boolean use_element_count = FALSE; int i, j, x, y; + /* first check if it is needed at all to calculate playfield element count */ + for (i = GAME_PANEL_ELEMENT_COUNT_1; i <= GAME_PANEL_ELEMENT_COUNT_8; i++) + if (!PANEL_DEACTIVATED(game_panel_controls[i].pos)) + use_element_count = TRUE; + + if (!use_element_count) + return; + for (i = 0; i < MAX_NUM_ELEMENTS; i++) element_info[i].element_count = 0; @@ -2232,6 +2278,7 @@ void UpdateGameControlValues() } 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; @@ -2339,8 +2386,7 @@ void UpdateGameControlValues() for (i = 0; i < NUM_PANEL_ELEMENTS; i++) game_panel_controls[GAME_PANEL_ELEMENT_COUNT_1 + i].value = (IS_VALID_ELEMENT(game.panel.element_count[i].id) ? - element_info[game.panel.element_count[i].id].element_count : - EL_UNDEFINED); + element_info[game.panel.element_count[i].id].element_count : 0); for (i = 0; i < NUM_PANEL_CE_SCORE; i++) game_panel_controls[GAME_PANEL_CE_SCORE_1 + i].value = @@ -2651,6 +2697,15 @@ void DisplayGameControlValues() 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; @@ -3286,7 +3341,7 @@ static void InitGameEngine() 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++) { @@ -3324,6 +3379,27 @@ static void InitGameEngine() } } +#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++) @@ -3334,6 +3410,7 @@ static void InitGameEngine() { ei->change_page[j].actual_trigger_element = EL_EMPTY; ei->change_page[j].actual_trigger_player = EL_PLAYER_1; + ei->change_page[j].actual_trigger_player_bits = CH_PLAYER_1; ei->change_page[j].actual_trigger_side = CH_SIDE_NONE; ei->change_page[j].actual_trigger_ce_value = 0; ei->change_page[j].actual_trigger_ce_score = 0; @@ -4201,8 +4278,12 @@ void InitGame() SetPanelBackground(); SetDrawBackgroundMask(REDRAW_DOOR_1); +#if 1 + UpdateAndDisplayGameControlValues(); +#else UpdateGameDoorValues(); DrawGameDoorValues(); +#endif if (!game.restart_level) { @@ -7533,10 +7614,18 @@ void StartMoving(int x, int y) 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; @@ -7547,6 +7636,33 @@ void StartMoving(int x, int y) 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); } } @@ -7570,10 +7686,18 @@ void StartMoving(int x, int y) 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; @@ -7584,6 +7708,33 @@ void StartMoving(int x, int y) 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); } } @@ -8226,6 +8377,10 @@ void StartMoving(int x, int y) 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)) @@ -8264,6 +8419,7 @@ void StartMoving(int x, int y) } 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))) @@ -8277,6 +8433,8 @@ void StartMoving(int x, int y) Store[newx][newy] = (move_leave_element == EL_TRIGGER_ELEMENT ? new_element : move_leave_element); } +#endif + #endif if (move_pattern & MV_MAZE_RUNNER_STYLE) @@ -8630,7 +8788,7 @@ void ContinueMoving(int x, int y) } #if USE_NEW_CUSTOM_VALUE - CustomValue[newx][newy] = CustomValue[x][y]; + CustomValue[newx][newy] = CustomValue[x][y]; #endif ChangeDelay[x][y] = 0; @@ -9501,9 +9659,6 @@ void DrawTwinkleOnField(int x, int y) { MovDelay[x][y]--; - if (setup.direct_draw && MovDelay[x][y]) - SetDrawtoField(DRAW_BUFFERED); - DrawLevelElementAnimation(x, y, Feld[x][y]); if (MovDelay[x][y] != 0) @@ -9512,18 +9667,6 @@ void DrawTwinkleOnField(int x, int y) 10 - MovDelay[x][y]); DrawGraphicThruMask(SCREENX(x), SCREENY(y), IMG_TWINKLE_WHITE, frame); - - if (setup.direct_draw) - { - int dest_x, dest_y; - - dest_x = FX + SCREENX(x) * TILEX; - dest_y = FY + SCREENY(y) * TILEY; - - BlitBitmap(drawto_field, window, - dest_x, dest_y, TILEX, TILEY, dest_x, dest_y); - SetDrawtoField(DRAW_DIRECT); - } } } } @@ -9782,7 +9925,7 @@ void MauerAblegerStahl(int ax, int ay) 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); @@ -10017,11 +10160,15 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) action_mode, action_arg_number, action_arg_number_min, action_arg_number_max); +#if 1 + int trigger_player_bits = change->actual_trigger_player_bits; +#else int trigger_player_bits = (change->actual_trigger_player >= EL_PLAYER_1 && change->actual_trigger_player <= EL_PLAYER_4 ? (1 << (change->actual_trigger_player - EL_PLAYER_1)) : PLAYER_BITS_ANY); +#endif int action_arg_player_bits = (action_arg >= CA_ARG_PLAYER_1 && @@ -10527,6 +10674,7 @@ static boolean ChangeElement(int x, int y, int element, int page) /* reset actual trigger element, trigger player and action element */ change->actual_trigger_element = EL_EMPTY; change->actual_trigger_player = EL_PLAYER_1; + change->actual_trigger_player_bits = CH_PLAYER_1; change->actual_trigger_side = CH_SIDE_NONE; change->actual_trigger_ce_value = 0; change->actual_trigger_ce_score = 0; @@ -10907,7 +11055,8 @@ static boolean CheckTriggeredElementChangeExt(int trigger_x, int trigger_y, IS_EQUAL_OR_IN_GROUP(trigger_element, change->trigger_element)) { change->actual_trigger_element = trigger_element; - change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player); + change->actual_trigger_player = GET_PLAYER_FROM_BITS(trigger_player); + change->actual_trigger_player_bits = trigger_player; change->actual_trigger_side = trigger_side; change->actual_trigger_ce_value = CustomValue[trigger_x][trigger_y]; change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element); @@ -11026,7 +11175,8 @@ static boolean CheckElementChangeExt(int x, int y, IS_EQUAL_OR_IN_GROUP(trigger_element, change->trigger_element))) { change->actual_trigger_element = trigger_element; - change->actual_trigger_player = EL_PLAYER_1 + log_2(trigger_player); + change->actual_trigger_player = GET_PLAYER_FROM_BITS(trigger_player); + change->actual_trigger_player_bits = trigger_player; change->actual_trigger_side = trigger_side; change->actual_trigger_ce_value = CustomValue[x][y]; change->actual_trigger_ce_score = GET_CE_SCORE(trigger_element); @@ -11417,8 +11567,12 @@ static void CheckLevelTime() DrawVideoDisplay(VIDEO_STATE_TIME_ON, TapeTime); } +#if 1 + UpdateAndDisplayGameControlValues(); +#else UpdateGameDoorValues(); DrawGameDoorValues(); +#endif } void AdvanceFrameAndPlayerCounters(int player_nr) @@ -12484,7 +12638,7 @@ void ScrollLevel(int dx, int dy) #else -#if 1 +#if 0 /* !!! DOES NOT WORK FOR DIAGONAL PLAYER RELOCATION !!! */ int xsize = (BX2 - BX1 + 1); int ysize = (BY2 - BY1 + 1); @@ -13893,9 +14047,9 @@ static boolean checkDiagonalPushing(struct PlayerInfo *player, ============================================================================= */ -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; @@ -14374,8 +14528,10 @@ int DigField(struct PlayerInfo *player, 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)) @@ -14395,6 +14551,13 @@ int DigField(struct PlayerInfo *player, 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) @@ -14637,7 +14800,66 @@ int DigField(struct PlayerInfo *player, 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; @@ -14717,7 +14939,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int 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;