X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=af65d866d449ce9a7b4537fd7efe451832546e1f;hb=bf1e4db1ffa9a313b8d1b68e55633ace682fef96;hp=1ddc793700ca7baa57e99ad01ce242fa9fc44420;hpb=92989af5d5884cbc8a1a9a62c9d05e109eaf78d0;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 1ddc7937..af65d866 100644 --- a/src/game.c +++ b/src/game.c @@ -144,6 +144,15 @@ Feld[x][y] == EL_EXIT_OPEN || \ Feld[x][y] == EL_ACID)) +#if 1 +#define MAZE_RUNNER_CAN_ENTER_FIELD(x, y) \ + (IN_LEV_FIELD(x, y) && IS_FREE(x, y)) +#else +#define MAZE_RUNNER_CAN_ENTER_FIELD(x, y) \ + (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || \ + IS_FOOD_DARK_YAMYAM(Feld[x][y]))) +#endif + #define MOLE_CAN_ENTER_FIELD(x, y, condition) \ (IN_LEV_FIELD(x, y) && (IS_FREE(x, y) || (condition))) @@ -186,6 +195,7 @@ static void PlayLevelSound(int, int, int); static void PlayLevelSoundNearest(int, int, int); static void PlayLevelSoundAction(int, int, int); static void PlayLevelSoundElementAction(int, int, int, int); +static void PlayLevelSoundElementActionIfLoop(int, int, int, int); static void PlayLevelSoundActionIfLoop(int, int, int); static void StopLevelSoundActionIfLoop(int, int, int); static void PlayLevelMusic(); @@ -755,8 +765,8 @@ void DrawGameDoorValues() { int i, j; - for (i=0; ichange_events = CE_BITMASK_DEFAULT; - for (j=0; j < NUM_CHANGE_EVENTS; j++) + for (j = 0; j < NUM_CHANGE_EVENTS; j++) { ei->event_page_nr[j] = 0; ei->event_page[j] = &ei->change_page[0]; @@ -843,7 +853,7 @@ static void InitGameEngine() } /* add changing elements from pre-defined list */ - for (i=0; change_delay_list[i].element != EL_UNDEFINED; i++) + for (i = 0; change_delay_list[i].element != EL_UNDEFINED; i++) { struct ChangingElementInfo *ch_delay = &change_delay_list[i]; struct ElementInfo *ei = &element_info[ch_delay->element]; @@ -860,16 +870,16 @@ static void InitGameEngine() #if 1 /* add change events from custom element configuration */ - for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) + for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) { struct ElementInfo *ei = &element_info[EL_CUSTOM_START + i]; - for (j=0; j < ei->num_change_pages; j++) + for (j = 0; j < ei->num_change_pages; j++) { if (!ei->change_page[j].can_change) continue; - for (k=0; k < NUM_CHANGE_EVENTS; k++) + for (k = 0; k < NUM_CHANGE_EVENTS; k++) { /* only add event page for the first page found with this event */ if (ei->change_page[j].events & CH_EVENT_BIT(k) && @@ -886,7 +896,7 @@ static void InitGameEngine() #else /* add change events from custom element configuration */ - for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) + for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) { int element = EL_CUSTOM_START + i; @@ -899,16 +909,16 @@ static void InitGameEngine() /* ---------- initialize trigger events ---------------------------------- */ /* initialize trigger events information */ - for (i=0; inum_change_pages; j++) + for (j = 0; j < ei->num_change_pages; j++) { if (!ei->change_page[j].can_change) continue; @@ -923,7 +933,7 @@ static void InitGameEngine() } #else /* add trigger events from element change event properties */ - for (i=0; itrigger_element] |= element_info[i].change->events; @@ -932,7 +942,7 @@ static void InitGameEngine() /* ---------- initialize push delay -------------------------------------- */ /* initialize push delay values to default */ - for (i=0; ilights_still_needed = 0; player->friends_still_needed = 0; - for (j=0; j<4; j++) + for (j = 0; j < 4; j++) player->key[j] = FALSE; player->dynabomb_count = 0; @@ -1049,6 +1059,8 @@ void InitGame() player->actual_frame_counter = 0; + player->step_counter = 0; + player->last_move_dir = MV_NO_MOVING; player->is_waiting = FALSE; @@ -1059,6 +1071,53 @@ void InitGame() player->is_pushing = FALSE; player->is_switching = FALSE; + player->is_bored = FALSE; + player->is_sleeping = FALSE; + + player->frame_counter_bored = -1; + player->frame_counter_sleeping = -1; + + player->anim_delay_counter = 0; + player->post_delay_counter = 0; + + player->action_waiting = ACTION_DEFAULT; + player->last_action_waiting = ACTION_DEFAULT; + player->special_action_bored = ACTION_DEFAULT; + player->special_action_sleeping = ACTION_DEFAULT; + + player->num_special_action_bored = 0; + player->num_special_action_sleeping = 0; + + /* determine number of special actions for bored and sleeping animation */ + for (j = ACTION_BORING_1; j <= ACTION_BORING_LAST; j++) + { + boolean found = FALSE; + + for (k = 0; k < NUM_DIRECTIONS; k++) + if (el_act_dir2img(player->element_nr, j, k) != + el_act_dir2img(player->element_nr, ACTION_DEFAULT, k)) + found = TRUE; + + if (found) + player->num_special_action_bored++; + else + break; + } + for (j = ACTION_SLEEPING_1; j <= ACTION_SLEEPING_LAST; j++) + { + boolean found = FALSE; + + for (k = 0; k < NUM_DIRECTIONS; k++) + if (el_act_dir2img(player->element_nr, j, k) != + el_act_dir2img(player->element_nr, ACTION_DEFAULT, k)) + found = TRUE; + + if (found) + player->num_special_action_sleeping++; + else + break; + } + player->switch_x = -1; player->switch_y = -1; @@ -1070,6 +1129,8 @@ void InitGame() player->push_delay = 0; player->push_delay_value = game.initial_push_delay_value; + player->drop_delay = 0; + player->last_jx = player->last_jy = 0; player->jx = player->jy = 0; @@ -1120,18 +1181,18 @@ void InitGame() game.envelope_active = FALSE; - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { game.belt_dir[i] = MV_NO_MOVING; game.belt_dir_nr[i] = 3; /* not moving, next moving left */ } - for (i=0; iconnected && !player->present) { - for (j=0; jjx, jy = some_player->jy; @@ -1217,7 +1281,7 @@ void InitGame() { /* when playing a tape, eliminate all players who do not participate */ - for (i=0; iscore < highscore[MAX_SCORE_ENTRIES - 1].Score) return -1; - for (k=0; kscore > highscore[k].Score) { @@ -1794,14 +1861,14 @@ int NewHiScore() int m = MAX_SCORE_ENTRIES - 1; #ifdef ONE_PER_NAME - for (l=k; lk; l--) + for (l = m; l > k; l--) { strcpy(highscore[l].Name, highscore[l - 1].Name); highscore[l].Score = highscore[l - 1].Score; @@ -2079,6 +2146,9 @@ void RelocatePlayer(int x, int y, int element) { struct PlayerInfo *player = &stored_player[element - EL_PLAYER_1]; + if (player->GameOver) /* do not reanimate dead player */ + return; + #if 1 RemoveField(x, y); /* temporarily remove newly placed player */ DrawLevelField(x, y); @@ -2190,7 +2260,7 @@ void Explode(int ex, int ey, int phase, int mode) Feld[ex][ey] = center_element; } - for (y = ey - 1; y <= ey + 1; y++) for(x = ex - 1; x <= ex + 1; x++) + for (y = ey - 1; y <= ey + 1; y++) for (x = ex - 1; x <= ex + 1; x++) { int xx = x - ex + 1; int yy = y - ey + 1; @@ -2468,6 +2538,12 @@ void Explode(int ex, int ey, int phase, int mode) #endif int frame = getGraphicAnimationFrame(graphic, phase - delay); +#if 0 + printf("::: %d ['%s'] -> %d\n", GfxElement[x][y], + element_info[GfxElement[x][y]].token_name, + graphic); +#endif + if (phase == delay) DrawLevelFieldCrumbledSand(x, y); @@ -2510,9 +2586,9 @@ void DynaExplode(int ex, int ey) Explode(ex, ey, EX_PHASE_START, EX_CENTER); - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { - for (j=1; j<=dynabomb_size; j++) + for (j = 1; j <= dynabomb_size; j++) { int x = ex + j * xy[i % 4][0]; int y = ey + j * xy[i % 4][1]; @@ -2658,11 +2734,11 @@ static void InitBeltMovement() int x, y, i, j; /* set frame order for belt animation graphic according to belt direction */ - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { int belt_nr = i; - for (j=0; j<3; j++) + for (j = 0; j < 3; j++) { int element = belt_base_active_element[belt_nr] + j; int graphic = el2img(element); @@ -2674,13 +2750,13 @@ static void InitBeltMovement() } } - for(y=0; yjx, jy = player->jy; @@ -3525,7 +3603,7 @@ inline static void TurnRoundExt(int x, int y) { 0, +1 } }; - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { int ex = x + xy[i % 4][0]; int ey = y + xy[i % 4][1]; @@ -3621,17 +3699,28 @@ inline static void TurnRoundExt(int x, int y) } } } - else if (element_info[element].move_pattern == MV_ALL_DIRECTIONS || - element_info[element].move_pattern == MV_TURNING_LEFT || - element_info[element].move_pattern == MV_TURNING_RIGHT) + else if (move_pattern == MV_TURNING_LEFT || + move_pattern == MV_TURNING_RIGHT || + move_pattern == MV_TURNING_LEFT_RIGHT || + move_pattern == MV_TURNING_RIGHT_LEFT || + move_pattern == MV_TURNING_RANDOM || + move_pattern == MV_ALL_DIRECTIONS) { boolean can_turn_left = ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y); boolean can_turn_right = ELEMENT_CAN_ENTER_FIELD(element, right_x,right_y); - if (element_info[element].move_pattern == MV_TURNING_LEFT) + if (move_pattern == MV_TURNING_LEFT) MovDir[x][y] = left_dir; - else if (element_info[element].move_pattern == MV_TURNING_RIGHT) + else if (move_pattern == MV_TURNING_RIGHT) MovDir[x][y] = right_dir; + else if (move_pattern == MV_TURNING_LEFT_RIGHT) + MovDir[x][y] = (can_turn_left || !can_turn_right ? left_dir : right_dir); + else if (move_pattern == MV_TURNING_RIGHT_LEFT) + MovDir[x][y] = (can_turn_right || !can_turn_left ? right_dir : left_dir); + else if (move_pattern == MV_TURNING_RANDOM) + MovDir[x][y] = (can_turn_left && !can_turn_right ? left_dir : + can_turn_right && !can_turn_left ? right_dir : + RND(2) ? left_dir : right_dir); else if (can_turn_left && can_turn_right) MovDir[x][y] = (RND(3) ? (RND(2) ? left_dir : right_dir) : back_dir); else if (can_turn_left) @@ -3643,24 +3732,24 @@ inline static void TurnRoundExt(int x, int y) MovDelay[x][y] = GET_NEW_MOVE_DELAY(element); } - else if (element_info[element].move_pattern == MV_HORIZONTAL || - element_info[element].move_pattern == MV_VERTICAL) + else if (move_pattern == MV_HORIZONTAL || + move_pattern == MV_VERTICAL) { - if (element_info[element].move_pattern & old_move_dir) + if (move_pattern & old_move_dir) MovDir[x][y] = back_dir; - else if (element_info[element].move_pattern == MV_HORIZONTAL) + else if (move_pattern == MV_HORIZONTAL) MovDir[x][y] = (RND(2) ? MV_LEFT : MV_RIGHT); - else if (element_info[element].move_pattern == MV_VERTICAL) + else if (move_pattern == MV_VERTICAL) MovDir[x][y] = (RND(2) ? MV_UP : MV_DOWN); MovDelay[x][y] = GET_NEW_MOVE_DELAY(element); } - else if (element_info[element].move_pattern & MV_ANY_DIRECTION) + else if (move_pattern & MV_ANY_DIRECTION) { - MovDir[x][y] = element_info[element].move_pattern; + MovDir[x][y] = move_pattern; MovDelay[x][y] = GET_NEW_MOVE_DELAY(element); } - else if (element_info[element].move_pattern == MV_ALONG_LEFT_SIDE) + else if (move_pattern == MV_ALONG_LEFT_SIDE) { if (ELEMENT_CAN_ENTER_FIELD(element, left_x, left_y)) MovDir[x][y] = left_dir; @@ -3670,7 +3759,7 @@ inline static void TurnRoundExt(int x, int y) if (MovDir[x][y] != old_move_dir) MovDelay[x][y] = GET_NEW_MOVE_DELAY(element); } - else if (element_info[element].move_pattern == MV_ALONG_RIGHT_SIDE) + else if (move_pattern == MV_ALONG_RIGHT_SIDE) { if (ELEMENT_CAN_ENTER_FIELD(element, right_x, right_y)) MovDir[x][y] = right_dir; @@ -3680,13 +3769,12 @@ inline static void TurnRoundExt(int x, int y) if (MovDir[x][y] != old_move_dir) MovDelay[x][y] = GET_NEW_MOVE_DELAY(element); } - else if (element_info[element].move_pattern == MV_TOWARDS_PLAYER || - element_info[element].move_pattern == MV_AWAY_FROM_PLAYER) + else if (move_pattern == MV_TOWARDS_PLAYER || + move_pattern == MV_AWAY_FROM_PLAYER) { int attr_x = -1, attr_y = -1; int newx, newy; - boolean move_away = - (element_info[element].move_pattern == MV_AWAY_FROM_PLAYER); + boolean move_away = (move_pattern == MV_AWAY_FROM_PLAYER); if (AllPlayersGone) { @@ -3697,7 +3785,7 @@ inline static void TurnRoundExt(int x, int y) { int i; - for (i=0; ijx, jy = player->jy; @@ -3748,13 +3836,84 @@ inline static void TurnRoundExt(int x, int y) MovDir[x][y] = old_move_dir; } } - else if (element_info[element].move_pattern == MV_WHEN_PUSHED) + else if (move_pattern == MV_WHEN_PUSHED) { if (!IN_LEV_FIELD_AND_IS_FREE(move_x, move_y)) MovDir[x][y] = MV_NO_MOVING; MovDelay[x][y] = 0; } + else if (move_pattern & MV_MAZE_RUNNER_STYLE || + element == EL_MAZE_RUNNER) + { + static int test_xy[7][2] = + { + { 0, -1 }, + { -1, 0 }, + { +1, 0 }, + { 0, +1 }, + { 0, -1 }, + { -1, 0 }, + { +1, 0 }, + }; + static int test_dir[7] = + { + MV_UP, + MV_LEFT, + MV_RIGHT, + MV_DOWN, + MV_UP, + MV_LEFT, + MV_RIGHT, + }; + boolean hunter_mode = (move_pattern == MV_MAZE_HUNTER); + int move_preference = -1000000; /* start with very low preference */ + int new_move_dir = MV_NO_MOVING; + int start_test = RND(4); + int i; + + for (i = 0; i < 4; i++) + { + int move_dir = test_dir[start_test + i]; + int move_dir_preference; + + xx = x + test_xy[start_test + i][0]; + yy = y + test_xy[start_test + i][1]; + + if (hunter_mode && IN_LEV_FIELD(xx, yy) && + (IS_PLAYER(xx, yy) || Feld[xx][yy] == EL_PLAYER_IS_LEAVING)) + { + new_move_dir = move_dir; + + break; + } + + if (!MAZE_RUNNER_CAN_ENTER_FIELD(xx, yy)) + continue; + + move_dir_preference = -1 * RunnerVisit[xx][yy]; + if (hunter_mode && PlayerVisit[xx][yy] > 0) + move_dir_preference = PlayerVisit[xx][yy]; + + if (move_dir_preference > move_preference) + { + /* prefer field that has not been visited for the longest time */ + move_preference = move_dir_preference; + new_move_dir = move_dir; + } + else if (move_dir_preference == move_preference && + move_dir == old_move_dir) + { + /* prefer last direction when all directions are preferred equally */ + move_preference = move_dir_preference; + new_move_dir = move_dir; + } + } + + MovDir[x][y] = new_move_dir; + if (old_move_dir != new_move_dir) + MovDelay[x][y] = 9; + } } static void TurnRound(int x, int y) @@ -3787,7 +3946,7 @@ static boolean JustBeingPushed(int x, int y) { int i; - for (i=0; ican_change && + change->events & CH_EVENT_BIT(CE_OTHER_IS_COLL_ACTIVE) && + change->sides & touched_side && + change->trigger_element == touched_element) + { + CheckElementSideChange(newx, newy, hitting_element, + CH_SIDE_ANY, CE_OTHER_IS_COLL_ACTIVE, i); + break; + } + } + } + + if (IS_CUSTOM_ELEMENT(touched_element) && + HAS_ANY_CHANGE_EVENT(touched_element, CE_OTHER_IS_COLL_PASSIVE)) + { + for (i = 0; i < element_info[touched_element].num_change_pages; i++) + { + struct ElementChangeInfo *change = + &element_info[touched_element].change_page[i]; + + if (change->can_change && + change->events & CH_EVENT_BIT(CE_OTHER_IS_COLL_PASSIVE) && + change->sides & hitting_side && + change->trigger_element == hitting_element) + { + CheckElementSideChange(nextx, nexty, touched_element, + CH_SIDE_ANY, CE_OTHER_IS_COLL_PASSIVE, i); + break; + } + } + } + } + } +#endif + } TestIfPlayerTouchesCustomElement(newx, newy); TestIfElementTouchesCustomElement(newx, newy); @@ -4736,7 +5011,7 @@ int AmoebeNachbarNr(int ax, int ay) { 0, +1 } }; - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { int x = ax + xy[i][0]; int y = ay + xy[i][1]; @@ -4766,7 +5041,7 @@ void AmoebenVereinigen(int ax, int ay) if (new_group_nr == 0) return; - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { x = ax + xy[i][0]; y = ay + xy[i][1]; @@ -4789,9 +5064,9 @@ void AmoebenVereinigen(int ax, int ay) AmoebaCnt2[new_group_nr] += AmoebaCnt2[old_group_nr]; AmoebaCnt2[old_group_nr] = 0; - for (yy=0; yyrandom) return FALSE; - for (yy = 0; yy < 3; yy++) for(xx = 0; xx < 3 ; xx++) + for (yy = 0; yy < 3; yy++) for (xx = 0; xx < 3 ; xx++) { int ex = x + xx - 1; int ey = y + yy - 1; @@ -5851,7 +6126,7 @@ static boolean CheckTriggeredElementSideChange(int lx, int ly, if (!(trigger_events[trigger_element] & CH_EVENT_BIT(trigger_event))) return FALSE; - for (i=0; i < NUM_CUSTOM_ELEMENTS; i++) + for (i = 0; i < NUM_CUSTOM_ELEMENTS; i++) { int element = EL_CUSTOM_START + i; @@ -5861,7 +6136,7 @@ static boolean CheckTriggeredElementSideChange(int lx, int ly, if (!CAN_CHANGE(element) || !HAS_ANY_CHANGE_EVENT(element, trigger_event)) continue; - for (j=0; j < element_info[element].num_change_pages; j++) + for (j = 0; j < element_info[element].num_change_pages; j++) { struct ElementChangeInfo *change = &element_info[element].change_page[j]; @@ -5888,7 +6163,7 @@ static boolean CheckTriggeredElementSideChange(int lx, int ly, if (!change_element) continue; - for (y=0; yjx, jy = player->jy; + int element = player->element_nr; + int last_action = player->last_action_waiting; + int action = player->action_waiting; + + if (player->is_waiting) + { + if (action != last_action) + PlayLevelSoundElementAction(jx, jy, element, action); + else + PlayLevelSoundElementActionIfLoop(jx, jy, element, action); + } + else + { + if (action != last_action) + StopSound(element_info[element].sound[last_action]); + + if (last_action == ACTION_SLEEPING) + PlayLevelSoundElementAction(jx, jy, element, ACTION_AWAKENING); + } +} + +static void PlayAllPlayersSound() +{ + int i; + + for (i = 0; i < MAX_PLAYERS; i++) + if (stored_player[i].active) + PlayPlayerSound(&stored_player[i]); +} + +static void SetPlayerWaiting(struct PlayerInfo *player, boolean is_waiting) +{ + boolean last_waiting = player->is_waiting; + int move_dir = player->MovDir; + + player->last_action_waiting = player->action_waiting; + + if (is_waiting) + { + if (!last_waiting) /* not waiting -> waiting */ + { + player->is_waiting = TRUE; + + player->frame_counter_bored = + FrameCounter + + game.player_boring_delay_fixed + + SimpleRND(game.player_boring_delay_random); + player->frame_counter_sleeping = + FrameCounter + + game.player_sleeping_delay_fixed + + SimpleRND(game.player_sleeping_delay_random); + + InitPlayerGfxAnimation(player, ACTION_WAITING, player->MovDir); + } + + if (game.player_sleeping_delay_fixed + + game.player_sleeping_delay_random > 0 && + player->anim_delay_counter == 0 && + player->post_delay_counter == 0 && + FrameCounter >= player->frame_counter_sleeping) + player->is_sleeping = TRUE; + else if (game.player_boring_delay_fixed + + game.player_boring_delay_random > 0 && + FrameCounter >= player->frame_counter_bored) + player->is_bored = TRUE; + + player->action_waiting = (player->is_sleeping ? ACTION_SLEEPING : + player->is_bored ? ACTION_BORING : + ACTION_WAITING); + + if (player->is_sleeping) + { + if (player->num_special_action_sleeping > 0) + { + if (player->anim_delay_counter == 0 && player->post_delay_counter == 0) + { + int last_special_action = player->special_action_sleeping; + int num_special_action = player->num_special_action_sleeping; + int special_action = + (last_special_action == ACTION_DEFAULT ? ACTION_SLEEPING_1 : + last_special_action == ACTION_SLEEPING ? ACTION_SLEEPING : + last_special_action < ACTION_SLEEPING_1 + num_special_action - 1 ? + last_special_action + 1 : ACTION_SLEEPING); + int special_graphic = + el_act_dir2img(player->element_nr, special_action, move_dir); + + player->anim_delay_counter = + graphic_info[special_graphic].anim_delay_fixed + + SimpleRND(graphic_info[special_graphic].anim_delay_random); + player->post_delay_counter = + graphic_info[special_graphic].post_delay_fixed + + SimpleRND(graphic_info[special_graphic].post_delay_random); + + player->special_action_sleeping = special_action; + } + + if (player->anim_delay_counter > 0) + { + player->action_waiting = player->special_action_sleeping; + player->anim_delay_counter--; + } + else if (player->post_delay_counter > 0) + { + player->post_delay_counter--; + } + } + } + else if (player->is_bored) + { + if (player->num_special_action_bored > 0) + { + if (player->anim_delay_counter == 0 && player->post_delay_counter == 0) + { + int special_action = + ACTION_BORING_1 + SimpleRND(player->num_special_action_bored); + int special_graphic = + el_act_dir2img(player->element_nr, special_action, move_dir); + + player->anim_delay_counter = + graphic_info[special_graphic].anim_delay_fixed + + SimpleRND(graphic_info[special_graphic].anim_delay_random); + player->post_delay_counter = + graphic_info[special_graphic].post_delay_fixed + + SimpleRND(graphic_info[special_graphic].post_delay_random); + + player->special_action_bored = special_action; + } + + if (player->anim_delay_counter > 0) + { + player->action_waiting = player->special_action_bored; + player->anim_delay_counter--; + } + else if (player->post_delay_counter > 0) + { + player->post_delay_counter--; + } + } + } + } + else if (last_waiting) /* waiting -> not waiting */ + { + player->is_waiting = FALSE; + player->is_bored = FALSE; + player->is_sleeping = FALSE; + + player->frame_counter_bored = -1; + player->frame_counter_sleeping = -1; + + player->anim_delay_counter = 0; + player->post_delay_counter = 0; + + player->action_waiting = ACTION_DEFAULT; + + player->special_action_bored = ACTION_DEFAULT; + player->special_action_sleeping = ACTION_DEFAULT; + } +} + #if 1 static byte PlayerActions(struct PlayerInfo *player, byte player_action) { @@ -5998,6 +6435,8 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action) } } + SetPlayerWaiting(player, FALSE); + #if 1 return player_action; #else @@ -6017,7 +6456,7 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action) CheckGravityMovement(player); if (player->MovPos == 0) - InitPlayerGfxAnimation(player, ACTION_DEFAULT, player->MovDir); + SetPlayerWaiting(player, TRUE); if (player->MovPos == 0) /* needed for tape.playing */ player->is_moving = FALSE; @@ -6173,7 +6612,7 @@ void GameActions() recorded_player_action = (tape.playing ? TapePlayAction() : NULL); - for (i=0; ieffective_action = summarized_player_action; - for (i=0; i < MAX_PLAYERS; i++) + for (i = 0; i < MAX_PLAYERS; i++) { int actual_player_action = stored_player[i].effective_action; @@ -6201,6 +6640,9 @@ void GameActions() tape_action[i] = PlayerActions(&stored_player[i], actual_player_action); + if (tape.recording && tape_action[i] && !tape.player_participates[i]) + tape.player_participates[i] = TRUE; /* player just appeared from CE */ + ScrollPlayer(&stored_player[i], SCROLL_GO_ON); } @@ -6217,14 +6659,14 @@ void GameActions() FrameCounter++; TimeFrames++; - for (i=0; ijx; @@ -6245,7 +6687,7 @@ void GameActions() } #endif - for (y=0; y 0) + stored_player[i].drop_delay--; } #endif @@ -6706,7 +7153,7 @@ static boolean AllPlayersInSight(struct PlayerInfo *player, int x, int y) int min_x = x, min_y = y, max_x = x, max_y = y; int i; - for (i=0; iMovPos = (dx > 0 || dy > 0 ? -1 : 1) * (TILEX - TILEX / player->move_delay_value); + player->step_counter++; + + player->drop_delay = 0; + + PlayerVisit[jx][jy] = FrameCounter; + ScrollPlayer(player, SCROLL_INIT); #if 0 @@ -7268,7 +7721,7 @@ void TestIfPlayerTouchesCustomElement(int x, int y) int center_element = Feld[x][y]; /* should always be non-moving! */ int i; - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { int xx = x + xy[i][0]; int yy = y + xy[i][1]; @@ -7326,7 +7779,7 @@ void TestIfElementTouchesCustomElement(int x, int y) }; static int change_sides[4][2] = { - /* center side border side */ + /* center side border side */ { CH_SIDE_TOP, CH_SIDE_BOTTOM }, /* check top */ { CH_SIDE_LEFT, CH_SIDE_RIGHT }, /* check left */ { CH_SIDE_RIGHT, CH_SIDE_LEFT }, /* check right */ @@ -7344,7 +7797,7 @@ void TestIfElementTouchesCustomElement(int x, int y) int center_element = Feld[x][y]; /* should always be non-moving! */ int i, j; - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { int xx = x + xy[i][0]; int yy = y + xy[i][1]; @@ -7369,7 +7822,7 @@ void TestIfElementTouchesCustomElement(int x, int y) HAS_ANY_CHANGE_EVENT(center_element, CE_OTHER_IS_TOUCHING) && !change_center_element) { - for (j=0; j < element_info[center_element].num_change_pages; j++) + for (j = 0; j < element_info[center_element].num_change_pages; j++) { struct ElementChangeInfo *change = &element_info[center_element].change_page[j]; @@ -7391,7 +7844,7 @@ void TestIfElementTouchesCustomElement(int x, int y) if (IS_CUSTOM_ELEMENT(border_element) && HAS_ANY_CHANGE_EVENT(border_element, CE_OTHER_IS_TOUCHING)) { - for (j=0; j < element_info[border_element].num_change_pages; j++) + for (j = 0; j < element_info[border_element].num_change_pages; j++) { struct ElementChangeInfo *change = &element_info[border_element].change_page[j]; @@ -7432,7 +7885,7 @@ void TestIfGoodThingHitsBadThing(int good_x, int good_y, int good_move_dir) MV_DOWN }; - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { int test_x, test_y, test_move_dir, test_element; @@ -7507,7 +7960,7 @@ void TestIfBadThingHitsGoodThing(int bad_x, int bad_y, int bad_move_dir) if (bad_element == EL_EXPLOSION) /* skip just exploding bad things */ return; - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { int test_x, test_y, test_move_dir, test_element; @@ -7611,7 +8064,7 @@ void TestIfBadThingTouchesOtherBadThing(int bad_x, int bad_y) { 0, +1 } }; - for (i=0; i<4; i++) + for (i = 0; i < 4; i++) { int x, y, element; @@ -7687,7 +8140,7 @@ void RemoveHero(struct PlayerInfo *player) if (!ExplodeField[jx][jy]) StorePlayer[jx][jy] = 0; - for (i=0; iinventory_size < MAX_INVENTORY_SIZE) player->inventory_element[player->inventory_size++] = element; @@ -8276,7 +8729,7 @@ int DigField(struct PlayerInfo *player, { int xx, yy; - for (yy=0; yy < lev_fieldy; yy++) for (xx=0; xx < lev_fieldx; xx++) + for (yy = 0; yy < lev_fieldy; yy++) for (xx=0; xx < lev_fieldx; xx++) { if (Feld[xx][yy] == EL_SP_DISK_YELLOW) Bang(xx, yy); @@ -8438,8 +8891,9 @@ boolean DropElement(struct PlayerInfo *player) { int jx = player->jx, jy = player->jy; int old_element; + int new_element; - if (!player->active || player->MovPos) + if (!player->active || player->MovPos || player->drop_delay > 0) return FALSE; old_element = Feld[jx][jy]; @@ -8461,14 +8915,24 @@ boolean DropElement(struct PlayerInfo *player) if (old_element != EL_EMPTY) Back[jx][jy] = old_element; /* store old element on this field */ + + + /* !!! CHANGE !!! CHANGE !!! */ + +#if 0 MovDelay[jx][jy] = 96; +#endif + + /* !!! CHANGE !!! CHANGE !!! */ + + ResetGfxAnimation(jx, jy); ResetRandomAnimationValue(jx, jy); if (player->inventory_size > 0) { - int new_element = player->inventory_element[--player->inventory_size]; + new_element = player->inventory_element[--player->inventory_size]; Feld[jx][jy] = (new_element == EL_DYNAMITE ? EL_DYNAMITE_ACTIVE : new_element == EL_SP_DISK_RED ? EL_SP_DISK_RED_ACTIVE : @@ -8498,8 +8962,52 @@ boolean DropElement(struct PlayerInfo *player) DrawGraphicThruMask(SCREENX(jx), SCREENY(jy), el2img(Feld[jx][jy]), 0); PlayLevelSoundAction(jx, jy, ACTION_DROPPING); + + MovDelay[jx][jy] = 96; + } + + + +#if 1 + InitField(jx, jy, FALSE); + if (CAN_MOVE(Feld[jx][jy])) + InitMovDir(jx, jy); + + new_element = Feld[jx][jy]; + + if (IS_CUSTOM_ELEMENT(new_element) && CAN_MOVE(new_element) && + element_info[new_element].move_pattern == MV_PROJECTILE) + { + int direction, dx, dy, nextx, nexty; + + if (element_info[new_element].move_direction_initial == MV_NO_MOVING) + MovDir[jx][jy] = player->MovDir; + + direction = MovDir[jx][jy]; + dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0); + dy = (direction == MV_UP ? -1 : direction == MV_DOWN ? +1 : 0); + nextx = jx + dx; + nexty = jy + dy; + + if (IN_LEV_FIELD(nextx, nexty) && IS_FREE(nextx, nexty)) + { + InitMovingField(jx, jy, MovDir[jx][jy]); + ContinueMoving(jx, jy); + } + else + { + Changed[jx][jy] = 0; /* allow another change */ + CheckElementSideChange(jx, jy, new_element, + direction, CE_COLLISION_ACTIVE, -1); + } } +#endif + + player->drop_delay = 8 + 8 + 8; + + + return TRUE; } @@ -8514,13 +9022,10 @@ void InitPlayLevelSound() { int num_sounds = getSoundListSize(); - if (loop_sound_frame != NULL) - free(loop_sound_frame); + checked_free(loop_sound_frame); + checked_free(loop_sound_volume); - if (loop_sound_volume != NULL) - free(loop_sound_volume); - - loop_sound_frame = checked_calloc(num_sounds * sizeof(int)); + loop_sound_frame = checked_calloc(num_sounds * sizeof(int)); loop_sound_volume = checked_calloc(num_sounds * sizeof(int)); } @@ -8591,6 +9096,15 @@ static void PlayLevelSoundElementAction(int x, int y, int element, int action) PlayLevelSound(x, y, sound_effect); } +static void PlayLevelSoundElementActionIfLoop(int x, int y, int element, + int action) +{ + int sound_effect = element_info[element].sound[action]; + + if (sound_effect != SND_UNDEFINED && IS_LOOP_SOUND(sound_effect)) + PlayLevelSound(x, y, sound_effect); +} + static void PlayLevelSoundActionIfLoop(int x, int y, int action) { int sound_effect = element_info[Feld[x][y]].sound[action]; @@ -8604,19 +9118,15 @@ static void StopLevelSoundActionIfLoop(int x, int y, int action) int sound_effect = element_info[Feld[x][y]].sound[action]; if (sound_effect != SND_UNDEFINED && IS_LOOP_SOUND(sound_effect)) - StopSoundExt(sound_effect, SND_CTRL_STOP_SOUND); + StopSound(sound_effect); } static void PlayLevelMusic() { -#if 1 if (levelset.music[level_nr] != MUS_UNDEFINED) PlayMusic(levelset.music[level_nr]); /* from config file */ else - PlayMusic(-(level_nr + 1)); /* from music dir */ -#else - PlayMusic(level_nr); -#endif + PlayMusic(MAP_NOCONF_MUSIC(level_nr)); /* from music dir */ } void RaiseScore(int value) @@ -8780,7 +9290,7 @@ void CreateGameButtons() { int i; - for (i=0; i