X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=bac83725cb81b334bd9511d71ef56a865744b23d;hb=4b1b5a2a67227d3023ff6da4596be31eae8eaefc;hp=5466f2d82ac30d6be5e764d730bc7485d895c2ba;hpb=ec36fe263402351ac67b70400f11096a044365fe;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 5466f2d8..bac83725 100644 --- a/src/game.c +++ b/src/game.c @@ -28,16 +28,20 @@ #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_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 +1066,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 +1117,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 +1591,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 +2548,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 +2618,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 +2654,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 +4228,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 +4241,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 +4294,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 +5032,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 +5147,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 +6463,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 +6490,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 +6510,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 +6544,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 +9484,9 @@ static boolean canFallDown(struct PlayerInfo *player) return (IN_LEV_FIELD(jx, jy + 1) && (IS_FREE(jx, jy + 1) || +#if USE_NEW_BLOCK_STYLE + Feld[jx][jy + 1] == EL_PLAYER_IS_LEAVING || +#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])); @@ -11358,14 +11429,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 +11499,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 +11615,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); @@ -12462,17 +12529,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 +12553,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 +12573,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 +12598,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 +12617,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 +12638,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 +12728,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: