X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=b6c1a51872114124e34b4d2d6a6779bf1a66cddb;hb=6890bb7cb72e140f4b82f35217655ae6c5213fec;hp=5466f2d82ac30d6be5e764d730bc7485d895c2ba;hpb=ec36fe263402351ac67b70400f11096a044365fe;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 5466f2d8..b6c1a518 100644 --- a/src/game.c +++ b/src/game.c @@ -28,16 +28,23 @@ #define USE_NEW_AMOEBA_CODE FALSE /* EXPERIMENTAL STUFF */ -#define USE_NEW_STUFF TRUE * 1 +#define USE_NEW_STUFF (TRUE * 1) -#define USE_NEW_MOVE_STYLE TRUE * USE_NEW_STUFF * 1 -#define USE_NEW_MOVE_DELAY TRUE * USE_NEW_STUFF * 1 -#define USE_NEW_PUSH_DELAY TRUE * USE_NEW_STUFF * 1 -#define USE_NEW_BLOCK_STYLE TRUE * USE_NEW_STUFF * 1 * 1 -#define USE_NEW_SP_SLIPPERY TRUE * USE_NEW_STUFF * 1 -#define USE_NEW_RANDOMIZE TRUE * USE_NEW_STUFF * 1 +#define USE_NEW_MOVE_STYLE (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_MOVE_DELAY (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_PUSH_DELAY (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_BLOCK_STYLE (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_SP_SLIPPERY (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_RANDOMIZE (TRUE * USE_NEW_STUFF * 1) + +#define USE_PUSH_BUGFIX (TRUE * USE_NEW_STUFF * 1) +#define USE_BLOCK_DELAY_BUGFIX (TRUE * USE_NEW_STUFF * 1) +#define USE_GRAVITY_BUGFIX (TRUE * USE_NEW_STUFF * 0) +#define USE_GRAVITY_BUGFIX_2 (TRUE * USE_NEW_STUFF * 1) + +#define USE_CAN_MOVE_NOT_MOVING (TRUE * USE_NEW_STUFF * 1) +#define USE_PREVIOUS_MOVE_DIR (TRUE * USE_NEW_STUFF * 1) -#define USE_PUSH_BUGFIX TRUE * USE_NEW_STUFF * 1 /* for DigField() */ #define DF_NO_PUSH 0 @@ -1062,11 +1069,12 @@ inline void DrawGameValue_Dynamite(int value) DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2); } -inline void DrawGameValue_Keys(int key[4]) +inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS]) { int i; - for (i = 0; i < MAX_KEYS; i++) + /* currently only 4 of 8 possible keys are displayed */ + for (i = 0; i < STD_NUM_KEYS; i++) if (key[i]) DrawMiniGraphicExt(drawto, DX_KEYS + i * MINI_TILEX, DY_KEYS, el2edimg(EL_KEY_1 + i)); @@ -1112,12 +1120,14 @@ inline void DrawGameValue_Level(int value) void DrawAllGameValues(int emeralds, int dynamite, int score, int time, int key_bits) { - int key[4]; + int key[MAX_NUM_KEYS]; int i; - for (i = 0; i < MAX_KEYS; i++) + for (i = 0; i < MAX_NUM_KEYS; i++) key[i] = key_bits & (1 << i); + DrawGameValue_Level(level_nr); + DrawGameValue_Emeralds(emeralds); DrawGameValue_Dynamite(dynamite); DrawGameValue_Score(score); @@ -1584,7 +1594,7 @@ void InitGame() player->lights_still_needed = 0; player->friends_still_needed = 0; - for (j = 0; j < MAX_KEYS; j++) + for (j = 0; j < MAX_NUM_KEYS; j++) player->key[j] = FALSE; player->dynabomb_count = 0; @@ -2541,6 +2551,37 @@ int NewHiScore() return position; } +inline static int getElementMoveStepsize(int x, int y) +{ + int element = Feld[x][y]; + int direction = MovDir[x][y]; + int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0); + int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0); + int horiz_move = (dx != 0); + int sign = (horiz_move ? dx : dy); + int step = sign * element_info[element].move_stepsize; + + /* special values for move stepsize for spring and things on conveyor belt */ + if (horiz_move) + { +#if 0 + if (element == EL_SPRING) + step = sign * MOVE_STEPSIZE_NORMAL * 2; + else if (CAN_FALL(element) && !CAN_MOVE(element) && + y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1])) + step = sign * MOVE_STEPSIZE_NORMAL / 2; +#else + if (CAN_FALL(element) && + y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1])) + step = sign * MOVE_STEPSIZE_NORMAL / 2; + else if (element == EL_SPRING) + step = sign * MOVE_STEPSIZE_NORMAL * 2; +#endif + } + + return step; +} + void InitPlayerGfxAnimation(struct PlayerInfo *player, int action, int dir) { if (player->GfxAction != action || player->GfxDir != dir) @@ -2580,6 +2621,27 @@ void InitMovingField(int x, int y, int direction) if (!WasJustMoving[x][y] || direction != MovDir[x][y]) ResetGfxAnimation(x, y); +#if USE_CAN_MOVE_NOT_MOVING + + MovDir[x][y] = direction; + GfxDir[x][y] = direction; + GfxAction[x][y] = (direction == MV_DOWN && CAN_FALL(element) ? + ACTION_FALLING : ACTION_MOVING); + + if (getElementMoveStepsize(x, y) != 0) /* moving or being moved */ + { + if (Feld[newx][newy] == EL_EMPTY) + Feld[newx][newy] = EL_BLOCKED; + + MovDir[newx][newy] = MovDir[x][y]; + GfxFrame[newx][newy] = GfxFrame[x][y]; + GfxRandom[newx][newy] = GfxRandom[x][y]; + GfxAction[newx][newy] = GfxAction[x][y]; + GfxDir[newx][newy] = GfxDir[x][y]; + } + +#else + MovDir[newx][newy] = MovDir[x][y] = direction; GfxDir[x][y] = direction; @@ -2595,6 +2657,7 @@ void InitMovingField(int x, int y, int direction) GfxRandom[newx][newy] = GfxRandom[x][y]; GfxAction[newx][newy] = GfxAction[x][y]; GfxDir[newx][newy] = GfxDir[x][y]; +#endif } void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y) @@ -4168,6 +4231,10 @@ static void RedrawAllLightSwitchesAndInvisibleElements() Feld[x][y] = getInvisibleActiveFromInvisibleElement(element); DrawLevelField(x, y); + + /* uncrumble neighbour fields, if needed */ + if (element == EL_INVISIBLE_SAND) + DrawLevelFieldCrumbledSandNeighbours(x, y); } else if (element == EL_INVISIBLE_STEELWALL_ACTIVE || element == EL_INVISIBLE_WALL_ACTIVE || @@ -4177,6 +4244,10 @@ static void RedrawAllLightSwitchesAndInvisibleElements() Feld[x][y] = getInvisibleFromInvisibleActiveElement(element); DrawLevelField(x, y); + + /* re-crumble neighbour fields, if needed */ + if (element == EL_INVISIBLE_SAND) + DrawLevelFieldCrumbledSandNeighbours(x, y); } } } @@ -4226,37 +4297,6 @@ static void ActivateTimegateSwitch(int x, int y) Feld[x][y] = EL_TIMEGATE_SWITCH_ACTIVE; } -inline static int getElementMoveStepsize(int x, int y) -{ - int element = Feld[x][y]; - int direction = MovDir[x][y]; - int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0); - int dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0); - int horiz_move = (dx != 0); - int sign = (horiz_move ? dx : dy); - int step = sign * element_info[element].move_stepsize; - - /* special values for move stepsize for spring and things on conveyor belt */ - if (horiz_move) - { -#if 0 - if (element == EL_SPRING) - step = sign * MOVE_STEPSIZE_NORMAL * 2; - else if (CAN_FALL(element) && !CAN_MOVE(element) && - y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1])) - step = sign * MOVE_STEPSIZE_NORMAL / 2; -#else - if (CAN_FALL(element) && - y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1])) - step = sign * MOVE_STEPSIZE_NORMAL / 2; - else if (element == EL_SPRING) - step = sign * MOVE_STEPSIZE_NORMAL * 2; -#endif - } - - return step; -} - void Impact(int x, int y) { boolean lastline = (y == lev_fieldy-1); @@ -4995,6 +5035,11 @@ inline static void TurnRoundExt(int x, int y) boolean can_turn_right = CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, right_x,right_y); +#if USE_CAN_MOVE_NOT_MOVING + if (element_info[element].move_stepsize == 0) /* not moving */ + return; +#endif + if (move_pattern == MV_TURNING_LEFT) MovDir[x][y] = left_dir; else if (move_pattern == MV_TURNING_RIGHT) @@ -5105,6 +5150,16 @@ inline static void TurnRoundExt(int x, int y) boolean first_horiz = RND(2); int new_move_dir = MovDir[x][y]; +#if USE_CAN_MOVE_NOT_MOVING + if (element_info[element].move_stepsize == 0) /* not moving */ + { + first_horiz = (ABS(attr_x - x) >= ABS(attr_y - y)); + MovDir[x][y] &= (first_horiz ? MV_HORIZONTAL : MV_VERTICAL); + + return; + } +#endif + MovDir[x][y] = new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL); Moving2Blocked(x, y, &newx, &newy); @@ -6411,7 +6466,9 @@ void ContinueMoving(int x, int y) #endif Store[x][y] = EL_EMPTY; - MovPos[x][y] = MovDir[x][y] = MovDelay[x][y] = 0; + MovPos[x][y] = 0; + MovDir[x][y] = 0; + MovDelay[x][y] = 0; MovDelay[newx][newy] = 0; if (CAN_CHANGE(element)) @@ -6436,7 +6493,10 @@ void ContinueMoving(int x, int y) Pushed[x][y] = Pushed[newx][newy] = FALSE; +#if 0 + /* do this after checking for left-behind element */ ResetGfxAnimation(x, y); /* reset animation values for old field */ +#endif #if 1 /* some elements can leave other elements behind after moving */ @@ -6453,6 +6513,12 @@ void ContinueMoving(int x, int y) int move_leave_element = ei->move_leave_element; Feld[x][y] = move_leave_element; + +#if USE_PREVIOUS_MOVE_DIR + if (element_info[Feld[x][y]].move_direction_initial == MV_START_PREVIOUS) + MovDir[x][y] = direction; +#endif + InitField(x, y, FALSE); if (GFX_CRUMBLED(Feld[x][y])) @@ -6481,6 +6547,11 @@ void ContinueMoving(int x, int y) ei->can_leave_element = FALSE; #endif +#if 1 + /* do this after checking for left-behind element */ + ResetGfxAnimation(x, y); /* reset animation values for old field */ +#endif + #if 0 /* 2.1.1 (does not work correctly for spring) */ if (!CAN_MOVE(element)) @@ -9416,6 +9487,11 @@ static boolean canFallDown(struct PlayerInfo *player) return (IN_LEV_FIELD(jx, jy + 1) && (IS_FREE(jx, jy + 1) || +#if USE_NEW_BLOCK_STYLE +#if USE_GRAVITY_BUGFIX + Feld[jx][jy + 1] == EL_PLAYER_IS_LEAVING || +#endif +#endif (Feld[jx][jy + 1] == EL_ACID && player->can_fall_into_acid)) && IS_WALKABLE_FROM(Feld[jx][jy], MV_DOWN) && !IS_WALKABLE_INSIDE(Feld[jx][jy])); @@ -10083,8 +10159,24 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) if (player->block_delay > 0 && Feld[last_jx][last_jy] == EL_EMPTY) { + int last_field_block_delay = player->block_delay; + +#if USE_BLOCK_DELAY_BUGFIX + /* when blocking enabled, correct block delay for fast movement */ + if (player->block_delay > 1 && + player->move_delay_value < MOVE_DELAY_NORMAL_SPEED) + last_field_block_delay = player->move_delay_value; +#endif + +#if USE_GRAVITY_BUGFIX_2 + /* when blocking enabled, correct block delay for gravity movement */ + if (player->block_delay > 1 && + game.gravity && player->MovDir == MV_UP) + last_field_block_delay = player->move_delay_value - 1; +#endif + Feld[last_jx][last_jy] = EL_PLAYER_IS_LEAVING; - MovDelay[last_jx][last_jy] = player->block_delay + 1; + MovDelay[last_jx][last_jy] = last_field_block_delay + 1; } #else #if USE_NEW_MOVE_STYLE @@ -11358,14 +11450,14 @@ int DigField(struct PlayerInfo *player, return MF_NO_ACTION; /* player cannot walk here due to gravity */ #endif - if (IS_GATE(element)) + if (IS_RND_GATE(element)) { - if (!player->key[element - EL_GATE_1]) + if (!player->key[RND_GATE_NR(element)]) return MF_NO_ACTION; } - else if (IS_GATE_GRAY(element)) + else if (IS_RND_GATE_GRAY(element)) { - if (!player->key[element - EL_GATE_1_GRAY]) + if (!player->key[RND_GATE_GRAY_NR(element)]) return MF_NO_ACTION; } else if (element == EL_EXIT_OPEN || @@ -11428,12 +11520,12 @@ int DigField(struct PlayerInfo *player, if (IS_EM_GATE(element)) { - if (!player->key[element - EL_EM_GATE_1]) + if (!player->key[EM_GATE_NR(element)]) return MF_NO_ACTION; } else if (IS_EM_GATE_GRAY(element)) { - if (!player->key[element - EL_EM_GATE_1_GRAY]) + if (!player->key[EM_GATE_GRAY_NR(element)]) return MF_NO_ACTION; } else if (IS_SP_PORT(element)) @@ -11544,13 +11636,9 @@ int DigField(struct PlayerInfo *player, { player->dynabomb_xl = TRUE; } - else if ((element >= EL_KEY_1 && element <= EL_KEY_4) || - (element >= EL_EM_KEY_1 && element <= EL_EM_KEY_4)) + else if (IS_KEY(element)) { - int key_nr = (element >= EL_KEY_1 && element <= EL_KEY_4 ? - element - EL_KEY_1 : element - EL_EM_KEY_1); - - player->key[key_nr] = TRUE; + player->key[KEY_NR(element)] = TRUE; DrawGameValue_Keys(player->key); @@ -11926,6 +12014,7 @@ int DigField(struct PlayerInfo *player, Feld[x][y] = EL_LAMP_ACTIVE; local_player->lights_still_needed--; + ResetGfxAnimation(x, y); DrawLevelField(x, y); } else if (element == EL_TIME_ORB_FULL) @@ -11934,6 +12023,7 @@ int DigField(struct PlayerInfo *player, TimeLeft += 10; DrawGameValue_Time(TimeLeft); + ResetGfxAnimation(x, y); DrawLevelField(x, y); #if 0 @@ -12462,17 +12552,21 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample) break; case SAMPLE_bug: - PlayLevelSoundElementAction(x, y, EL_BUG, ACTION_MOVING); + PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); break; case SAMPLE_tank: - PlayLevelSoundElementAction(x, y, EL_SPACESHIP, ACTION_MOVING); + PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); break; - case SAMPLE_android: + case SAMPLE_android_clone: PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING); break; + case SAMPLE_android_move: + PlayLevelSoundElementAction(x, y, element, ACTION_MOVING); + break; + case SAMPLE_spring: PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT); break; @@ -12482,7 +12576,11 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample) break; case SAMPLE_eater: - PlayLevelSoundElementAction(x, y, EL_YAMYAM, ACTION_WAITING); + PlayLevelSoundElementAction(x, y, element, ACTION_WAITING); + break; + + case SAMPLE_eater_eat: + PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING); break; case SAMPLE_alien: @@ -12498,11 +12596,16 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample) break; case SAMPLE_squash: + /* !!! CHECK THIS !!! */ +#if 1 + PlayLevelSoundElementAction(x, y, element, ACTION_BREAKING); +#else PlayLevelSoundElementAction(x, y, element, ACTION_SMASHED_BY_ROCK); +#endif break; case SAMPLE_wonderfall: - PlayLevelSoundElementAction(x, y, EL_MAGIC_WALL, ACTION_FILLING); + PlayLevelSoundElementAction(x, y, element, ACTION_FILLING); break; case SAMPLE_drip: @@ -12518,7 +12621,7 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample) break; case SAMPLE_acid: - PlayLevelSound(x, y, SND_ACID_SPLASHING); + PlayLevelSoundElementAction(x, y, element, ACTION_SPLASHING); break; case SAMPLE_ball: @@ -12537,7 +12640,11 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample) PlayLevelSoundElementAction(x, y, element, ACTION_PASSING); break; - case SAMPLE_exit: + case SAMPLE_exit_open: + PlayLevelSoundElementAction(x, y, element, ACTION_OPENING); + break; + + case SAMPLE_exit_leave: PlayLevelSoundElementAction(x, y, element, ACTION_PASSING); break; @@ -12554,21 +12661,21 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample) break; case SAMPLE_wheel: - PlayLevelSound(x, y, SND_ROBOT_WHEEL_ACTIVE); + PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE); break; case SAMPLE_boom: PlayLevelSoundElementAction(x, y, element, ACTION_EXPLODING); break; - case SAMPLE_time: - PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE); - break; - case SAMPLE_die: PlayLevelSoundElementAction(x, y, element, ACTION_DYING); break; + case SAMPLE_time: + PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE); + break; + default: PlayLevelSoundElementAction(x, y, element, ACTION_DEFAULT); break; @@ -12644,6 +12751,14 @@ void RaiseScoreElement(int element) case EL_KEY_2: case EL_KEY_3: case EL_KEY_4: + case EL_EM_KEY_1: + case EL_EM_KEY_2: + case EL_EM_KEY_3: + case EL_EM_KEY_4: + case EL_EMC_KEY_5: + case EL_EMC_KEY_6: + case EL_EMC_KEY_7: + case EL_EMC_KEY_8: RaiseScore(level.score[SC_KEY]); break; default: