X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=d837dad2089889148c108b72a294c71476dcc17d;hb=a3bc2ca4c0acf21291d20b5affed89f149b85862;hp=c321c01297597ea07e7e7a588717c5d616d361f7;hpb=750338586791fbdc6d34ab20b5bd659573faf111;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index c321c012..d837dad2 100644 --- a/src/game.c +++ b/src/game.c @@ -165,7 +165,7 @@ static void KillHeroUnlessProtected(int, int); static void CheckTriggeredElementChange(int, int); static void CheckPlayerElementChange(int, int, int, int); -static void ChangeElementDoIt(int, int, int); +static void ChangeElementNow(int, int, int); static void PlaySoundLevel(int, int, int); static void PlaySoundLevelNearest(int, int, int); @@ -202,8 +202,8 @@ static void RunTimegateWheel(int x, int y); struct ChangingElementInfo { - int base_element; - int next_element; + int element; + int target_element; int change_delay; void (*pre_change_function)(int x, int y); void (*change_function)(int x, int y); @@ -390,11 +390,10 @@ gem_count_list[] = { EL_UNDEFINED, 0 }, }; -static struct ChangingElementInfo changing_element[MAX_NUM_ELEMENTS]; +static boolean changing_element[MAX_NUM_ELEMENTS]; static unsigned long trigger_events[MAX_NUM_ELEMENTS]; -static int gem_count[MAX_NUM_ELEMENTS]; -#define IS_AUTO_CHANGING(e) (changing_element[e].base_element != EL_UNDEFINED) +#define IS_AUTO_CHANGING(e) (changing_element[e]) #define IS_JUST_CHANGING(x, y) (ChangeDelay[x][y] != 0) #define IS_CHANGING(x, y) (IS_AUTO_CHANGING(Feld[x][y]) || \ IS_JUST_CHANGING(x, y)) @@ -743,42 +742,75 @@ static void InitGameEngine() /* initialize changing elements information */ for (i=0; ibase_element; + struct ElementChangeInfo *change = &element_info[element].change; + +#if 1 + change->target_element = ce->target_element; + change->delay_fixed = ce->change_delay; + change->pre_change_function = ce->pre_change_function; + change->change_function = ce->change_function; + change->post_change_function = ce->post_change_function; + changing_element[element] = TRUE; +#else changing_element[element].base_element = ce->base_element; changing_element[element].next_element = ce->next_element; changing_element[element].change_delay = ce->change_delay; changing_element[element].pre_change_function = ce->pre_change_function; changing_element[element].change_function = ce->change_function; changing_element[element].post_change_function = ce->post_change_function; +#endif } /* add changing elements from custom element configuration */ for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) { int element = EL_CUSTOM_START + i; +#if 0 struct ElementChangeInfo *change = &element_info[element].change; +#endif /* only add custom elements that change after fixed/random frame delay */ if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, CE_DELAY)) continue; +#if 1 + changing_element[element] = TRUE; +#else changing_element[element].base_element = element; - changing_element[element].next_element = change->successor; + changing_element[element].next_element = change->target_element; changing_element[element].change_delay = (change->delay_fixed * change->delay_frames); +#endif } /* ---------- initialize trigger events ---------------------------------- */ @@ -818,11 +850,13 @@ static void InitGameEngine() /* initialize gem count values for each element */ for (i=0; iexplode) + { + Bang(x, y); + return; + } + + if (change->use_content) + { + boolean complete_change = TRUE; + boolean can_change[3][3]; + int xx, yy; + + for (yy = 0; yy < 3; yy++) for(xx = 0; xx < 3 ; xx++) + { + boolean half_destructible; + int ex = x + xx - 1; + int ey = y + yy - 1; + int e; + + can_change[xx][yy] = TRUE; + + if (ex == x && ey == y) /* do not check changing element itself */ + continue; + + if (change->content[xx][yy] == EL_EMPTY_SPACE) + { + can_change[xx][yy] = FALSE; /* do not change empty borders */ + + continue; + } + + if (!IN_LEV_FIELD(ex, ey)) + { + can_change[xx][yy] = FALSE; + complete_change = FALSE; + + continue; + } + + e = Feld[ex][ey]; + + half_destructible = (IS_FREE(ex, ey) || IS_DIGGABLE(e)); + + if ((change->power <= CP_NON_DESTRUCTIVE && !IS_FREE(ex, ey)) || + (change->power <= CP_HALF_DESTRUCTIVE && !half_destructible) || + (change->power <= CP_FULL_DESTRUCTIVE && IS_INDESTRUCTIBLE(e))) + { + can_change[xx][yy] = FALSE; + complete_change = FALSE; + } + } + + if (!change->only_complete || complete_change) + { + for (yy = 0; yy < 3; yy++) for(xx = 0; xx < 3 ; xx++) + { + int ex = x + xx - 1; + int ey = y + yy - 1; + + if (can_change[xx][yy]) + { + ChangeElementNowExt(ex, ey, change->content[xx][yy]); + + /* for symmetry reasons, stop newly created border elements */ + if (ex != x || ey != y) + Stop[ex][ey] = TRUE; + } + } + + return; + } + } + + ChangeElementNowExt(x, y, change->target_element); +} + static void ChangeElement(int x, int y) { int element = Feld[x][y]; + struct ElementChangeInfo *change = &element_info[element].change; if (ChangeDelay[x][y] == 0) /* initialize element change */ { +#if 1 + ChangeDelay[x][y] = ( change->delay_fixed * change->delay_frames + + RND(change->delay_random * change->delay_frames)) + 1; +#else ChangeDelay[x][y] = changing_element[element].change_delay + 1; if (IS_CUSTOM_ELEMENT(element) && HAS_CHANGE_EVENT(element, CE_DELAY)) @@ -5063,12 +5245,18 @@ static void ChangeElement(int x, int y) ChangeDelay[x][y] += RND(max_random_delay * delay_frames); } +#endif ResetGfxAnimation(x, y); ResetRandomAnimationValue(x, y); +#if 1 + if (change->pre_change_function) + change->pre_change_function(x, y); +#else if (changing_element[element].pre_change_function) changing_element[element].pre_change_function(x, y); +#endif } ChangeDelay[x][y]--; @@ -5080,12 +5268,19 @@ static void ChangeElement(int x, int y) if (IS_ANIMATED(graphic)) DrawLevelGraphicAnimationIfNeeded(x, y, graphic); +#if 1 + if (change->change_function) + change->change_function(x, y); +#else if (changing_element[element].change_function) changing_element[element].change_function(x, y); +#endif } else /* finish element change */ { +#if 0 int next_element = changing_element[element].next_element; +#endif if (IS_MOVING(x, y)) /* never change a running system ;-) */ { @@ -5094,13 +5289,20 @@ static void ChangeElement(int x, int y) return; } +#if 1 + ChangeElementNow(x, y, element); + + if (change->post_change_function) + change->post_change_function(x, y); +#else if (next_element != EL_UNDEFINED) - ChangeElementDoIt(x, y, next_element); + ChangeElementNow(x, y, next_element); else - ChangeElementDoIt(x, y, element_info[element].change.successor); + ChangeElementNow(x, y, element_info[element].change.target_element); if (changing_element[element].post_change_function) changing_element[element].post_change_function(x, y); +#endif } } @@ -5134,12 +5336,8 @@ static void CheckPlayerElementChange(int x, int y, int element, if (!CAN_CHANGE(element) || !HAS_CHANGE_EVENT(element, trigger_event)) return; -#if 1 ChangeDelay[x][y] = 1; ChangeElement(x, y); -#else - ChangeElementDoIt(x, y, element_info[element].change.successor); -#endif } static void PlayerActions(struct PlayerInfo *player, byte player_action) @@ -6460,10 +6658,12 @@ void RemoveHero(struct PlayerInfo *player) } /* + ============================================================================= checkDiagonalPushing() ----------------------------------------------------------------------------- check if diagonal input device direction results in pushing of object (by checking if the alternative direction is walkable, diggable, ...) + ============================================================================= */ static boolean checkDiagonalPushing(struct PlayerInfo *player, @@ -6486,10 +6686,12 @@ static boolean checkDiagonalPushing(struct PlayerInfo *player, } /* + ============================================================================= DigField() ----------------------------------------------------------------------------- x, y: field next to player (non-diagonal) to try to dig to real_dx, real_dy: direction as read from input device (can be diagonal) + ============================================================================= */ int DigField(struct PlayerInfo *player, @@ -6498,6 +6700,7 @@ int DigField(struct PlayerInfo *player, boolean use_spring_bug = (game.engine_version < VERSION_IDENT(2,2,0)); int jx = player->jx, jy = player->jy; int dx = x - jx, dy = y - jy; + int nextx = x + dx, nexty = y + dy; int move_direction = (dx == -1 ? MV_LEFT : dx == +1 ? MV_RIGHT : dy == -1 ? MV_UP : @@ -6522,14 +6725,7 @@ int DigField(struct PlayerInfo *player, } if (IS_MOVING(x, y) || IS_PLAYER(x, y)) - { -#if 0 - if (FrameCounter == 437) - printf("::: ---> IS_MOVING %d\n", MovDir[x][y]); -#endif - return MF_NO_ACTION; - } #if 0 if (IS_TUBE(Feld[jx][jy]) || IS_TUBE(Back[jx][jy])) @@ -6569,248 +6765,12 @@ int DigField(struct PlayerInfo *player, element = Feld[x][y]; -#if 1 if (mode == DF_SNAP && !IS_SNAPPABLE(element) && game.engine_version >= VERSION_IDENT(2,2,0)) return MF_NO_ACTION; -#endif switch (element) { -#if 0 - case EL_EMPTY: - PlaySoundLevelElementAction(x, y, player->element_nr, ACTION_MOVING); - break; -#endif - -#if 0 - case EL_SAND: - case EL_INVISIBLE_SAND: - case EL_INVISIBLE_SAND_ACTIVE: - case EL_TRAP: - case EL_SP_BASE: - case EL_SP_BUGGY_BASE: - case EL_SP_BUGGY_BASE_ACTIVATING: - RemoveField(x, y); - - if (mode != DF_SNAP && element != EL_EMPTY) - { - GfxElement[x][y] = (CAN_BE_CRUMBLED(element) ? EL_SAND : element); - player->is_digging = TRUE; - } - - PlaySoundLevelElementAction(x, y, element, ACTION_DIGGING); - break; -#endif - -#if 0 - - case EL_EMERALD: - case EL_BD_DIAMOND: - case EL_EMERALD_YELLOW: - case EL_EMERALD_RED: - case EL_EMERALD_PURPLE: - case EL_DIAMOND: - case EL_SP_INFOTRON: - case EL_PEARL: - case EL_CRYSTAL: - RemoveField(x, y); - - if (mode != DF_SNAP) - { - GfxElement[x][y] = element; - player->is_collecting = TRUE; - } - - local_player->gems_still_needed -= (element == EL_DIAMOND ? 3 : - element == EL_PEARL ? 5 : - element == EL_CRYSTAL ? 8 : 1); - if (local_player->gems_still_needed < 0) - local_player->gems_still_needed = 0; - RaiseScoreElement(element); - DrawText(DX_EMERALDS, DY_EMERALDS, - int2str(local_player->gems_still_needed, 3), FONT_TEXT_2); - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - -#endif - -#if 0 - - case EL_SPEED_PILL: - RemoveField(x, y); - player->move_delay_value = MOVE_DELAY_HIGH_SPEED; -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_SPEED_PILL_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - -#endif - - -#if 0 - case EL_ENVELOPE: - Feld[x][y] = EL_EMPTY; -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_ENVELOPE_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; -#endif - -#if 0 - - case EL_EXTRA_TIME: - RemoveField(x, y); - if (level.time > 0) - { - TimeLeft += 10; - DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_TEXT_2); - } -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MIDDLE); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - -#endif - -#if 0 - case EL_SHIELD_NORMAL: - RemoveField(x, y); - player->shield_normal_time_left += 10; -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_SHIELD_NORMAL_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_SHIELD_DEADLY: - RemoveField(x, y); - player->shield_normal_time_left += 10; - player->shield_deadly_time_left += 10; -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_SHIELD_DEADLY_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; -#endif - -#if 0 - case EL_DYNAMITE: - case EL_SP_DISK_RED: - RemoveField(x, y); - player->dynamite++; - player->use_disk_red_graphic = (element == EL_SP_DISK_RED); - RaiseScoreElement(EL_DYNAMITE); - DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3), - FONT_TEXT_2); - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; -#endif - -#if 0 - case EL_DYNABOMB_INCREASE_NUMBER: - RemoveField(x, y); - player->dynabomb_count++; - player->dynabombs_left++; - RaiseScoreElement(EL_DYNAMITE); -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_NUMBER_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_DYNABOMB_INCREASE_SIZE: - RemoveField(x, y); - player->dynabomb_size++; - RaiseScoreElement(EL_DYNAMITE); -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_SIZE_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - - case EL_DYNABOMB_INCREASE_POWER: - RemoveField(x, y); - player->dynabomb_xl = TRUE; - RaiseScoreElement(EL_DYNAMITE); -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_DYNABOMB_INCREASE_POWER_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; -#endif - -#if 0 - case EL_KEY_1: - case EL_KEY_2: - case EL_KEY_3: - case EL_KEY_4: - { - int key_nr = element - EL_KEY_1; - int graphic = el2edimg(element); - - RemoveField(x, y); - player->key[key_nr] = TRUE; - RaiseScoreElement(element); - DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - graphic); - DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - graphic); -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_CLASS_KEY_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - } - - case EL_EM_KEY_1: - case EL_EM_KEY_2: - case EL_EM_KEY_3: - case EL_EM_KEY_4: - { - int key_nr = element - EL_EM_KEY_1; - int graphic = el2edimg(EL_KEY_1 + key_nr); - - RemoveField(x, y); - player->key[key_nr] = TRUE; - RaiseScoreElement(element); - DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - graphic); - DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS, - graphic); -#if 1 - PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING); -#else - PlaySoundLevel(x, y, SND_CLASS_KEY_COLLECTING); -#endif - CheckTriggeredElementChange(element, CE_OTHER_COLLECTING); - break; - } -#endif - case EL_ROBOT_WHEEL: Feld[x][y] = EL_ROBOT_WHEEL_ACTIVE; ZX = x; @@ -6911,175 +6871,6 @@ int DigField(struct PlayerInfo *player, return MF_ACTION; break; -#if 0 - - /* the following elements cannot be pushed by "snapping" */ - case EL_ROCK: - case EL_BOMB: - case EL_DX_SUPABOMB: - case EL_NUT: - case EL_TIME_ORB_EMPTY: - case EL_SP_ZONK: - case EL_SP_DISK_ORANGE: - case EL_SPRING: - if (mode == DF_SNAP) - return MF_NO_ACTION; - - /* no "break" -- fall through to next case */ - - /* the following elements can be pushed by "snapping" */ - case EL_BD_ROCK: - if (dy) - return MF_NO_ACTION; - - if (CAN_FALL(element) && IN_LEV_FIELD(x, y + 1) && IS_FREE(x, y + 1) && - !(element == EL_SPRING && use_spring_bug)) - return MF_NO_ACTION; - - player->Pushing = TRUE; - -#if 0 - if (element == EL_ROCK) - printf("::: wanna push [%d] [%d]\n", - FrameCounter, player->push_delay_value); -#endif - - if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy)) - return MF_NO_ACTION; - - if (!checkDiagonalPushing(player, x, y, real_dx, real_dy)) - return MF_NO_ACTION; - - - if (player->push_delay == 0) - player->push_delay = FrameCounter; - -#if 0 - printf("want push... %d [%d]\n", FrameCounter, player->push_delay_value); -#endif - -#if 0 - if (!FrameReached(&player->push_delay, player->push_delay_value) && - !tape.playing && - element != EL_SPRING) - return MF_NO_ACTION; -#else - if (!FrameReached(&player->push_delay, player->push_delay_value) && - !(tape.playing && tape.file_version < FILE_VERSION_2_0) && - element != EL_SPRING) - return MF_NO_ACTION; -#endif - - if (mode == DF_SNAP) - { - InitMovingField(x, y, move_direction); - ContinueMoving(x, y); - } - else - { -#if 1 - InitMovingField(x, y, (dx < 0 ? MV_LEFT : - dx > 0 ? MV_RIGHT : - dy < 0 ? MV_UP : MV_DOWN)); - MovPos[x][y] = (dx != 0 ? dx : dy); -#else - RemoveField(x, y); - Feld[x + dx][y + dy] = element; -#endif - } - -#if 0 - printf("pushing %d/%d ... %d [%d]\n", dx, dy, - FrameCounter, player->push_delay_value); -#endif - -#if 0 - if (element == EL_SPRING) - { - Feld[x + dx][y + dy] = EL_SPRING; - MovDir[x + dx][y + dy] = move_direction; - } -#endif - - player->push_delay_value = (element == EL_SPRING ? 0 : 2 + RND(8)); - - DrawLevelField(x + dx, y + dy); - PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING); - - CheckTriggeredElementChange(element, CE_OTHER_PUSHING); - - break; - -#endif - -#if 0 - case EL_GATE_1: - case EL_GATE_2: - case EL_GATE_3: - case EL_GATE_4: - if (!player->key[element - EL_GATE_1]) - return MF_NO_ACTION; - break; - - case EL_GATE_1_GRAY: - case EL_GATE_2_GRAY: - case EL_GATE_3_GRAY: - case EL_GATE_4_GRAY: - if (!player->key[element - EL_GATE_1_GRAY]) - return MF_NO_ACTION; - break; - - case EL_EM_GATE_1: - case EL_EM_GATE_2: - case EL_EM_GATE_3: - case EL_EM_GATE_4: - if (!player->key[element - EL_EM_GATE_1]) - return MF_NO_ACTION; - if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) - return MF_NO_ACTION; - - /* automatically move to the next field with double speed */ - player->programmed_action = move_direction; - DOUBLE_PLAYER_SPEED(player); - - PlaySoundLevel(x, y, SND_CLASS_GATE_PASSING); - break; - - case EL_EM_GATE_1_GRAY: - case EL_EM_GATE_2_GRAY: - case EL_EM_GATE_3_GRAY: - case EL_EM_GATE_4_GRAY: - if (!player->key[element - EL_EM_GATE_1_GRAY]) - return MF_NO_ACTION; - if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) - return MF_NO_ACTION; - - /* automatically move to the next field with double speed */ - player->programmed_action = move_direction; - DOUBLE_PLAYER_SPEED(player); - -#if 1 - PlaySoundLevelAction(x, y, ACTION_PASSING); -#else - PlaySoundLevel(x, y, SND_GATE_PASSING); -#endif - break; -#endif - -#if 0 - case EL_SWITCHGATE_OPEN: - case EL_TIMEGATE_OPEN: - if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) - return MF_NO_ACTION; - - /* automatically move to the next field with double speed */ - player->programmed_action = move_direction; - DOUBLE_PLAYER_SPEED(player); - - PlaySoundLevelElementAction(x, y, element, ACTION_PASSING); - break; -#endif - case EL_SP_PORT_LEFT: case EL_SP_PORT_RIGHT: case EL_SP_PORT_UP: @@ -7111,8 +6902,8 @@ int DigField(struct PlayerInfo *player, element != EL_SP_GRAVITY_PORT_DOWN && element != EL_SP_PORT_VERTICAL && element != EL_SP_PORT_ANY) || - !IN_LEV_FIELD(x + dx, y + dy) || - !IS_FREE(x + dx, y + dy)) + !IN_LEV_FIELD(nextx, nexty) || + !IS_FREE(nextx, nexty)) return MF_NO_ACTION; /* automatically move to the next field with double speed */ @@ -7165,28 +6956,6 @@ int DigField(struct PlayerInfo *player, } break; -#if 0 - case EL_EXIT_CLOSED: - case EL_SP_EXIT_CLOSED: - case EL_EXIT_OPENING: - return MF_NO_ACTION; - break; -#endif - -#if 0 - case EL_EXIT_OPEN: - case EL_SP_EXIT_OPEN: - if (mode == DF_SNAP) - return MF_NO_ACTION; - - if (element == EL_EXIT_OPEN) - PlaySoundLevel(x, y, SND_CLASS_EXIT_PASSING); - else - PlaySoundLevel(x, y, SND_CLASS_SP_EXIT_PASSING); - - break; -#endif - case EL_LAMP: Feld[x][y] = EL_LAMP_ACTIVE; local_player->lights_still_needed--; @@ -7204,168 +6973,6 @@ int DigField(struct PlayerInfo *player, return MF_ACTION; break; -#if 0 - -#if 0 - case EL_SOKOBAN_FIELD_EMPTY: - break; -#endif - - case EL_SOKOBAN_OBJECT: - case EL_SOKOBAN_FIELD_FULL: - case EL_SATELLITE: - case EL_SP_DISK_YELLOW: - case EL_BALLOON: - if (mode == DF_SNAP) - return MF_NO_ACTION; - - player->Pushing = TRUE; - - if (!IN_LEV_FIELD(x+dx, y+dy) - || (!IS_FREE(x+dx, y+dy) - && (Feld[x+dx][y+dy] != EL_SOKOBAN_FIELD_EMPTY - || !IS_SB_ELEMENT(element)))) - return MF_NO_ACTION; - - if (!checkDiagonalPushing(player, x, y, real_dx, real_dy)) - return MF_NO_ACTION; - - if (player->push_delay == 0) - player->push_delay = FrameCounter; -#if 0 - if (!FrameReached(&player->push_delay, player->push_delay_value) && - !tape.playing && element != EL_BALLOON) - return MF_NO_ACTION; -#else - if (!FrameReached(&player->push_delay, player->push_delay_value) && - !(tape.playing && tape.file_version < FILE_VERSION_2_0) && - element != EL_BALLOON) - return MF_NO_ACTION; -#endif - - if (IS_SB_ELEMENT(element)) - { -#if 1 - if (element == EL_SOKOBAN_FIELD_FULL) - { - Back[x][y] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokobanfields_still_needed++; - } - - if (Feld[x + dx][y + dy] == EL_SOKOBAN_FIELD_EMPTY) - { - Back[x + dx][y + dy] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokobanfields_still_needed--; - } - - Feld[x][y] = EL_SOKOBAN_OBJECT; - - if (Back[x][y] == Back[x + dx][y + dy]) - PlaySoundLevelAction(x, y, ACTION_PUSHING); - else if (Back[x][y] != 0) - PlaySoundLevelElementAction(x, y, EL_SOKOBAN_FIELD_FULL, - ACTION_EMPTYING); - else - PlaySoundLevelElementAction(x + dx, y + dy, EL_SOKOBAN_FIELD_EMPTY, - ACTION_FILLING); - - InitMovingField(x, y, (dx < 0 ? MV_LEFT : - dx > 0 ? MV_RIGHT : - dy < 0 ? MV_UP : MV_DOWN)); - MovPos[x][y] = (dx != 0 ? dx : dy); - -#if 0 - printf("::: %s -> %s [%s -> %s]\n", - element_info[Feld[x][y]].token_name, - element_info[Feld[x + dx][y + dy]].token_name, - element_info[Back[x][y]].token_name, - element_info[Back[x + dx][y + dy]].token_name); -#endif - -#else - if (element == EL_SOKOBAN_FIELD_FULL) - { - Feld[x][y] = EL_SOKOBAN_FIELD_EMPTY; - local_player->sokobanfields_still_needed++; - } - else - RemoveField(x, y); - - if (Feld[x+dx][y+dy] == EL_SOKOBAN_FIELD_EMPTY) - { - Feld[x+dx][y+dy] = EL_SOKOBAN_FIELD_FULL; - local_player->sokobanfields_still_needed--; - if (element == EL_SOKOBAN_OBJECT) -#if 1 - PlaySoundLevelAction(x+dx, y+dy, ACTION_FILLING); -#else - PlaySoundLevel(x, y, SND_CLASS_SOKOBAN_FIELD_FILLING); -#endif - else -#if 1 - PlaySoundLevelAction(x+dx, y+dy, ACTION_PUSHING); -#else - PlaySoundLevel(x, y, SND_SOKOBAN_OBJECT_PUSHING); -#endif - } - else - { - Feld[x+dx][y+dy] = EL_SOKOBAN_OBJECT; - if (element == EL_SOKOBAN_FIELD_FULL) -#if 1 - PlaySoundLevelAction(x+dx, y+dy, ACTION_EMPTYING); -#else - PlaySoundLevel(x, y, SND_SOKOBAN_FIELD_EMPTYING); -#endif - else -#if 1 - PlaySoundLevelAction(x+dx, y+dy, ACTION_PUSHING); -#else - PlaySoundLevel(x, y, SND_SOKOBAN_OBJECT_PUSHING); -#endif - } -#endif - } - else - { -#if 1 - InitMovingField(x, y, (dx < 0 ? MV_LEFT : - dx > 0 ? MV_RIGHT : - dy < 0 ? MV_UP : MV_DOWN)); - MovPos[x][y] = (dx != 0 ? dx : dy); -#else - RemoveField(x, y); - Feld[x + dx][y + dy] = element; -#endif - PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING); - } - - player->push_delay_value = (element == EL_BALLOON ? 0 : 2); - - DrawLevelField(x, y); - DrawLevelField(x + dx, y + dy); - - if (IS_SB_ELEMENT(element) && - local_player->sokobanfields_still_needed == 0 && - game.emulation == EMU_SOKOBAN) - { - player->LevelSolved = player->GameOver = TRUE; - PlaySoundLevel(x, y, SND_GAME_SOKOBAN_SOLVING); - } - - CheckTriggeredElementChange(element, CE_OTHER_PUSHING); - - break; - -#endif - -#if 0 - case EL_PENGUIN: - case EL_PIG: - case EL_DRAGON: - break; -#endif - default: if (IS_WALKABLE(element)) @@ -7401,7 +7008,7 @@ int DigField(struct PlayerInfo *player, } else if (IS_PASSABLE(element)) { - if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) + if (!IN_LEV_FIELD(nextx, nexty) || !IS_FREE(nextx, nexty)) return MF_NO_ACTION; if (element >= EL_EM_GATE_1 && element <= EL_EM_GATE_4) @@ -7494,9 +7101,10 @@ int DigField(struct PlayerInfo *player, el2edimg(EL_KEY_1 + key_nr)); redraw_mask |= REDRAW_DOOR_1; } - else if (gem_count[element] > 0) + else if (element_info[element].gem_count > 0) { - local_player->gems_still_needed -= gem_count[element]; + local_player->gems_still_needed -= + element_info[element].gem_count; if (local_player->gems_still_needed < 0) local_player->gems_still_needed = 0; @@ -7532,9 +7140,9 @@ int DigField(struct PlayerInfo *player, player->Pushing = TRUE; - if (!(IN_LEV_FIELD(x + dx, y + dy) && - (IS_FREE(x + dx, y + dy) || - (Feld[x + dx][y + dy] == EL_SOKOBAN_FIELD_EMPTY && + if (!(IN_LEV_FIELD(nextx, nexty) && + (IS_FREE(nextx, nexty) || + (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY && IS_SB_ELEMENT(element))))) return MF_NO_ACTION; @@ -7557,21 +7165,21 @@ int DigField(struct PlayerInfo *player, local_player->sokobanfields_still_needed++; } - if (Feld[x + dx][y + dy] == EL_SOKOBAN_FIELD_EMPTY) + if (Feld[nextx][nexty] == EL_SOKOBAN_FIELD_EMPTY) { - Back[x + dx][y + dy] = EL_SOKOBAN_FIELD_EMPTY; + Back[nextx][nexty] = EL_SOKOBAN_FIELD_EMPTY; local_player->sokobanfields_still_needed--; } Feld[x][y] = EL_SOKOBAN_OBJECT; - if (Back[x][y] == Back[x + dx][y + dy]) + if (Back[x][y] == Back[nextx][nexty]) PlaySoundLevelAction(x, y, ACTION_PUSHING); else if (Back[x][y] != 0) PlaySoundLevelElementAction(x, y, EL_SOKOBAN_FIELD_FULL, ACTION_EMPTYING); else - PlaySoundLevelElementAction(x + dx, y + dy, EL_SOKOBAN_FIELD_EMPTY, + PlaySoundLevelElementAction(nextx, nexty, EL_SOKOBAN_FIELD_EMPTY, ACTION_FILLING); if (local_player->sokobanfields_still_needed == 0 && @@ -7592,7 +7200,7 @@ int DigField(struct PlayerInfo *player, MovPos[x][y] = (dx != 0 ? dx : dy); Pushed[x][y] = TRUE; - Pushed[x + dx][y + dy] = TRUE; + Pushed[nextx][nexty] = TRUE; if (game.engine_version < RELEASE_IDENT(2,2,0,7)) player->push_delay_value = GET_NEW_PUSH_DELAY(element); @@ -7622,6 +7230,10 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) { int jx = player->jx, jy = player->jy; int x = jx + dx, y = jy + dy; + int snap_direction = (dx == -1 ? MV_LEFT : + dx == +1 ? MV_RIGHT : + dy == -1 ? MV_UP : + dy == +1 ? MV_DOWN : MV_NO_MOVING); if (player->MovPos && game.engine_version >= VERSION_IDENT(2,2,0)) return FALSE; @@ -7651,10 +7263,7 @@ boolean SnapField(struct PlayerInfo *player, int dx, int dy) if (player->snapped) return FALSE; - player->MovDir = (dx < 0 ? MV_LEFT : - dx > 0 ? MV_RIGHT : - dy < 0 ? MV_UP : - dy > 0 ? MV_DOWN : MV_NO_MOVING); + player->MovDir = snap_direction; if (DigField(player, x, y, 0, 0, DF_SNAP) == MF_NO_ACTION) return FALSE;