X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=a78e341f983a3e429518c8e8bff1647f0a96983b;hb=05be30e0b291803b5d1947ad04ff4c3be546ed4a;hp=08fee26493a335478bbff0302e66a297c0d5d788;hpb=174df2f6abf5f72b5539176a2591a3c1ee83f045;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 08fee264..a78e341f 100644 --- a/src/game.c +++ b/src/game.c @@ -25,10 +25,13 @@ #define USE_NEW_AMOEBA_CODE FALSE /* EXPERIMENTAL STUFF */ -#define USE_NEW_STUFF (TRUE * 1) +#define USE_NEW_STUFF ( * 1) -#define USE_NEW_SP_SLIPPERY (TRUE * USE_NEW_STUFF * 1) -#define USE_NEW_COLLECT_COUNT (TRUE * USE_NEW_STUFF * 1) +#define USE_NEW_SP_SLIPPERY (USE_NEW_STUFF * 1) +#define USE_NEW_COLLECT_COUNT (USE_NEW_STUFF * 1) +#define USE_NEW_PLAYER_ANIM (USE_NEW_STUFF * 1) +#define USE_NEW_ALL_SLIPPERY (USE_NEW_STUFF * 1) +#define USE_NEW_PLAYER_SPEED (USE_NEW_STUFF * 1) /* for DigField() */ @@ -89,16 +92,25 @@ #define INITIAL_MOVE_DELAY_ON 0 /* values for player movement speed (which is in fact a delay value) */ +#define MOVE_DELAY_MIN_SPEED 32 #define MOVE_DELAY_NORMAL_SPEED 8 #define MOVE_DELAY_HIGH_SPEED 4 +#define MOVE_DELAY_MAX_SPEED 1 +#if 0 #define DOUBLE_MOVE_DELAY(x) (x = (x <= MOVE_DELAY_HIGH_SPEED ? x * 2 : x)) #define HALVE_MOVE_DELAY(x) (x = (x >= MOVE_DELAY_HIGH_SPEED ? x / 2 : x)) +#else +#define DOUBLE_MOVE_DELAY(x) (x = (x < MOVE_DELAY_MIN_SPEED ? x * 2 : x)) +#define HALVE_MOVE_DELAY(x) (x = (x > MOVE_DELAY_MAX_SPEED ? x / 2 : x)) +#endif #define DOUBLE_PLAYER_SPEED(p) (HALVE_MOVE_DELAY((p)->move_delay_value)) #define HALVE_PLAYER_SPEED(p) (DOUBLE_MOVE_DELAY((p)->move_delay_value)) /* values for other actions */ #define MOVE_STEPSIZE_NORMAL (TILEX / MOVE_DELAY_NORMAL_SPEED) +#define MOVE_STEPSIZE_MIN (1) +#define MOVE_STEPSIZE_MAX (TILEX) #define GET_DX_FROM_DIR(d) ((d) == MV_LEFT ? -1 : (d) == MV_RIGHT ? 1 : 0) #define GET_DY_FROM_DIR(d) ((d) == MV_UP ? -1 : (d) == MV_DOWN ? 1 : 0) @@ -1699,6 +1711,26 @@ void InitGame() emulate_sb ? EMU_SOKOBAN : emulate_sp ? EMU_SUPAPLEX : EMU_NONE); +#if USE_NEW_ALL_SLIPPERY + /* initialize type of slippery elements */ + for (i = 0; i < MAX_NUM_ELEMENTS; i++) + { + if (!IS_CUSTOM_ELEMENT(i)) + { + /* default: elements slip down either to the left or right randomly */ + element_info[i].slippery_type = SLIPPERY_ANY_RANDOM; + + /* SP style elements prefer to slip down on the left side */ + if (game.engine_version >= VERSION_IDENT(3,1,1,0) && IS_SP_ELEMENT(i)) + element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT; + + /* BD style elements prefer to slip down on the left side */ + if (game.emulation == EMU_BOULDERDASH) + element_info[i].slippery_type = SLIPPERY_ANY_LEFT_RIGHT; + } + } +#endif + /* initialize explosion and ignition delay */ for (i = 0; i < MAX_NUM_ELEMENTS; i++) { @@ -4757,11 +4789,26 @@ void StartMoving(int x, int y) Feld[x + 1][y + 1] == EL_ACID)); boolean can_fall_any = (can_fall_left || can_fall_right); boolean can_fall_both = (can_fall_left && can_fall_right); + int slippery_type = element_info[Feld[x][y + 1]].slippery_type; - if (can_fall_any && IS_CUSTOM_ELEMENT(Feld[x][y + 1])) +#if USE_NEW_ALL_SLIPPERY + if (can_fall_any && slippery_type != SLIPPERY_ANY_RANDOM) { - int slippery_type = element_info[Feld[x][y + 1]].slippery_type; + if (slippery_type == SLIPPERY_ANY_LEFT_RIGHT && can_fall_both) + can_fall_right = FALSE; + else if (slippery_type == SLIPPERY_ANY_RIGHT_LEFT && can_fall_both) + can_fall_left = FALSE; + else if (slippery_type == SLIPPERY_ONLY_LEFT) + can_fall_right = FALSE; + else if (slippery_type == SLIPPERY_ONLY_RIGHT) + can_fall_left = FALSE; + can_fall_any = (can_fall_left || can_fall_right); + can_fall_both = FALSE; + } +#else + if (can_fall_any && IS_CUSTOM_ELEMENT(Feld[x][y + 1])) + { if (slippery_type == SLIPPERY_ONLY_LEFT) can_fall_right = FALSE; else if (slippery_type == SLIPPERY_ONLY_RIGHT) @@ -4774,7 +4821,10 @@ void StartMoving(int x, int y) can_fall_any = (can_fall_left || can_fall_right); can_fall_both = (can_fall_left && can_fall_right); } +#endif +#if USE_NEW_ALL_SLIPPERY +#else #if USE_NEW_SP_SLIPPERY /* !!! better use the same properties as for custom elements here !!! */ else if (game.engine_version >= VERSION_IDENT(3,1,1,0) && @@ -4784,7 +4834,19 @@ void StartMoving(int x, int y) can_fall_both = FALSE; } #endif +#endif + +#if USE_NEW_ALL_SLIPPERY + if (can_fall_both) + { + if (element == EL_BD_ROCK || element == EL_BD_DIAMOND) + can_fall_right = FALSE; /* slip down on left side */ + else + can_fall_left = !(can_fall_right = RND(2)); + can_fall_both = FALSE; + } +#else if (can_fall_both) { if (game.emulation == EMU_BOULDERDASH || @@ -4795,6 +4857,7 @@ void StartMoving(int x, int y) can_fall_both = FALSE; } +#endif if (can_fall_any) { @@ -5312,11 +5375,6 @@ void StartMoving(int x, int y) ContinueMoving(x, y); } -/* (emacs is confused here for some reason; this makes it happy again ;-) ) */ -void dummy() -{ -} - void ContinueMoving(int x, int y) { int element = Feld[x][y]; @@ -6441,8 +6499,8 @@ static int getSpecialActionElement(int element, int number, int base_element) EL_EMPTY); } -static int getModifiedActionNumber(int value_old, int value_min, int value_max, - int operator, int operand) +static int getModifiedActionNumber(int value_old, int operator, int operand, + int value_min, int value_max) { int value_new = (operator == CA_MODE_ADD ? value_old + operand : operator == CA_MODE_SUBTRACT ? value_old - operand : @@ -6476,10 +6534,38 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) action_arg == CA_ARG_ELEMENT_TARGET ? change->target_element : EL_EMPTY); + int action_arg_number_min = + (action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_MIN : + CA_ARG_MIN); + + int action_arg_number_max = + (action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_MAX : + action_type == CA_SET_GEMS ? 999 : + action_type == CA_SET_TIME ? 9999 : + action_type == CA_SET_SCORE ? 99999 : + action_type == CA_SET_CE_SCORE ? 9999 : + action_type == CA_SET_CE_COUNT ? 9999 : + CA_ARG_MAX); + + int action_arg_number_reset = + (action_type == CA_SET_PLAYER_SPEED ? TILEX/game.initial_move_delay_value : + action_type == CA_SET_GEMS ? level.gems_needed : + action_type == CA_SET_TIME ? level.time : + action_type == CA_SET_SCORE ? 0 : + action_type == CA_SET_CE_SCORE ? 0 : + action_type == CA_SET_CE_COUNT ? ei->collect_count_initial : + 0); + + int action_arg_number_normal = + (action_type == CA_SET_PLAYER_SPEED ? MOVE_STEPSIZE_NORMAL : + action_arg_number_reset); + int action_arg_number = (action_arg <= CA_ARG_MAX ? action_arg : - action_arg == CA_ARG_NUMBER_MIN ? CA_ARG_MIN : - action_arg == CA_ARG_NUMBER_MAX ? CA_ARG_MAX : + action_arg == CA_ARG_NUMBER_MIN ? action_arg_number_min : + action_arg == CA_ARG_NUMBER_MAX ? action_arg_number_max : + action_arg == CA_ARG_NUMBER_RESET ? action_arg_number_reset : + action_arg == CA_ARG_NUMBER_NORMAL ? action_arg_number_normal : action_arg == CA_ARG_NUMBER_CE_SCORE ? ei->collect_score : #if USE_NEW_COLLECT_COUNT action_arg == CA_ARG_NUMBER_CE_COUNT ? Count[x][y] : @@ -6489,6 +6575,19 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) action_arg == CA_ARG_NUMBER_CE_DELAY ? GET_CHANGE_DELAY(change) : -1); + int action_arg_number_old = + (action_type == CA_SET_GEMS ? local_player->gems_still_needed : + action_type == CA_SET_TIME ? TimeLeft : + action_type == CA_SET_SCORE ? local_player->score : + action_type == CA_SET_CE_SCORE ? ei->collect_score : + action_type == CA_SET_CE_COUNT ? Count[x][y] : + 0); + + int action_arg_number_new = + getModifiedActionNumber(action_arg_number_old, + action_mode, action_arg_number, + action_arg_number_min, action_arg_number_max); + /* (for explicit player choice, set invalid value to "no player") */ int action_arg_player_bits = (action_arg == CA_ARG_PLAYER_ANY ? action_arg - CA_ARG_PLAYER : @@ -6605,38 +6704,32 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) { if (trigger_player_bits & (1 << i)) { - if (action_arg == CA_ARG_NUMBER_RESET) - stored_player[i].move_delay_value = game.initial_move_delay_value; - else if (action_arg == CA_ARG_NUMBER_NORMAL) - stored_player[i].move_delay_value = MOVE_DELAY_NORMAL_SPEED; - else if (action_arg == CA_ARG_NUMBER_MIN) - stored_player[i].move_delay_value = 16; - else if (action_arg == CA_ARG_NUMBER_MAX) - stored_player[i].move_delay_value = MOVE_DELAY_HIGH_SPEED; - else + int move_stepsize = TILEX / stored_player[i].move_delay_value; + + if (action_mode == CA_MODE_ADD || action_mode == CA_MODE_SUBTRACT) { -#if 0 - if (action_mode == CA_MODE_ADD) - { - action_mode = CA_MODE_DIVIDE; - action_arg_number = (1 << action_arg_number); - } - else if (action_mode == CA_MODE_SUBTRACT) - { - action_mode = CA_MODE_MULTIPLY; - action_arg_number = (1 << action_arg_number); - } + /* translate "+" and "-" to "*" and "/" with powers of two */ + action_arg_number = 1 << action_arg_number; + action_mode = (action_mode == CA_MODE_ADD ? CA_MODE_MULTIPLY : + CA_MODE_DIVIDE); + } + + move_stepsize = + getModifiedActionNumber(move_stepsize, + action_mode, + action_arg_number, + action_arg_number_min, + action_arg_number_max); - int mode = (action_mode == CA_MODE_MULTIPLY ? CA_MODE_DIVIDE : - action_mode == CA_MODE_DIVIDE ? CA_MODE_MULTIPLY : - action_mode); + /* make sure that value is power of 2 */ + move_stepsize = (1 << log_2(move_stepsize)); - stored_player[i].move_delay_value = - getModifiedActionNumber(stored_player[i].move_delay_value, - 1, 16, - action_mode, action_arg_number); + stored_player[i].move_delay_value = TILEX / move_stepsize; + +#if 0 + printf("::: move_delay_value == %d [%d]\n", + stored_player[i].move_delay_value, action_arg_number); #endif - } } } @@ -6645,9 +6738,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) case CA_SET_GEMS: { - local_player->gems_still_needed = - getModifiedActionNumber(local_player->gems_still_needed, 0, 999, - action_mode, action_arg_number); + local_player->gems_still_needed = action_arg_number_new; DrawGameValue_Emeralds(local_player->gems_still_needed); @@ -6658,10 +6749,13 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) { if (level.time > 0) /* only modify limited time value */ { - TimeLeft = getModifiedActionNumber(TimeLeft, 0, 9999, - action_mode, action_arg_number); + TimeLeft = action_arg_number_new; DrawGameValue_Time(TimeLeft); + + if (!TimeLeft && setup.time_limit) + for (i = 0; i < MAX_PLAYERS; i++) + KillHero(&stored_player[i]); } break; @@ -6669,9 +6763,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) case CA_SET_SCORE: { - local_player->score = - getModifiedActionNumber(local_player->score, 0, 9999, - action_mode, action_arg_number); + local_player->score = action_arg_number_new; DrawGameValue_Score(local_player->score); @@ -6680,9 +6772,8 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) case CA_SET_CE_SCORE: { - ei->collect_score = - getModifiedActionNumber(ei->collect_score, 0, 9999, - action_mode, action_arg_number); + ei->collect_score = action_arg_number_new; + break; } @@ -6691,8 +6782,7 @@ static void ExecuteCustomElementAction(int x, int y, int element, int page) #if USE_NEW_COLLECT_COUNT int count_last = Count[x][y]; - Count[x][y] = getModifiedActionNumber(Count[x][y], 0, 9999, - action_mode, action_arg_number); + Count[x][y] = action_arg_number_new; #if 0 printf("::: Count == %d\n", Count[x][y]); @@ -7413,12 +7503,25 @@ void AdvanceFrameAndPlayerCounters(int player_nr) for (i = 0; i < MAX_PLAYERS; i++) { boolean advance_player_counters = (player_nr == -1 || player_nr == i); - int move_frames = - MOVE_DELAY_NORMAL_SPEED / stored_player[i].move_delay_value; + int move_delay_value = stored_player[i].move_delay_value; + int move_frames = MOVE_DELAY_NORMAL_SPEED / move_delay_value; if (!advance_player_counters) /* not all players may be affected */ continue; +#if USE_NEW_PLAYER_ANIM + if (move_frames == 0) /* less than one move per game frame */ + { + int stepsize = TILEX / move_delay_value; + int delay = move_delay_value / MOVE_DELAY_NORMAL_SPEED; + int count = (stored_player[i].is_moving ? + ABS(stored_player[i].MovPos) / stepsize : FrameCounter); + + if (count % delay == 0) + move_frames = 1; + } +#endif + stored_player[i].Frame += move_frames; if (stored_player[i].MovPos != 0) @@ -7672,11 +7775,20 @@ void GameActions() if (IS_CHANGING(x, y) && (game.engine_version < VERSION_IDENT(3,0,7,1) || !Stop[x][y])) { + int page = element_info[element].event_page_nr[CE_DELAY]; #if 0 - ChangeElement(x, y, ChangePage[x][y] != -1 ? ChangePage[x][y] : - element_info[element].event_page_nr[CE_DELAY]); + ChangeElement(x, y, ChangePage[x][y] != -1 ? ChangePage[x][y] : page); #else - ChangeElement(x, y, element_info[element].event_page_nr[CE_DELAY]); + +#if 0 + printf("::: ChangeDelay == %d\n", ChangeDelay[x][y]); +#endif + + if (CAN_CHANGE(element)) + ChangeElement(x, y, page); + + if (HAS_ACTION(element) && ChangeDelay[x][y] == 0) + ExecuteCustomElementAction(x, y, element, page); #endif element = Feld[x][y]; @@ -8390,8 +8502,16 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) int last_jx = player->last_jx, last_jy = player->last_jy; int move_stepsize = TILEX / player->move_delay_value; - if (!player->active || !player->MovPos) +#if USE_NEW_PLAYER_SPEED + if (!player->active) + return; + + if (player->MovPos == 0 && mode == SCROLL_GO_ON) /* player not moving */ + return; +#else + if (!player->active || player->MovPos == 0) return; +#endif if (mode == SCROLL_INIT) { @@ -8421,20 +8541,47 @@ void ScrollPlayer(struct PlayerInfo *player, int mode) MovDelay[last_jx][last_jy] = last_field_block_delay + 1; } +#if USE_NEW_PLAYER_SPEED + if (player->MovPos != 0) /* player has not yet reached destination */ + return; +#else return; +#endif } else if (!FrameReached(&player->actual_frame_counter, 1)) return; +#if 0 + printf("::: player->MovPos: %d -> %d\n", + player->MovPos, + player->MovPos + (player->MovPos > 0 ? -1 : 1) * move_stepsize); +#endif + +#if USE_NEW_PLAYER_SPEED + if (player->MovPos != 0) + { + player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize; + player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); + + /* before DrawPlayer() to draw correct player graphic for this case */ + if (player->MovPos == 0) + CheckGravityMovement(player); + } +#else player->MovPos += (player->MovPos > 0 ? -1 : 1) * move_stepsize; player->GfxPos = move_stepsize * (player->MovPos / move_stepsize); /* before DrawPlayer() to draw correct player graphic for this case */ if (player->MovPos == 0) CheckGravityMovement(player); +#endif if (player->MovPos == 0) /* player reached destination field */ { +#if 0 + printf("::: player reached destination field\n"); +#endif + if (player->move_delay_reset_counter > 0) { player->move_delay_reset_counter--;