X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=8de889ac5cf4757c8433e4b3ec10ce8a20b76bbb;hb=70dc207bf840929d1f21821f1a94ed305df96f56;hp=a7aa775237a91e4c643aae0f277ab72967577586;hpb=4cd59cef0737229da365e385a8762e681a5e471f;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index a7aa7752..8de889ac 100644 --- a/src/game.c +++ b/src/game.c @@ -1769,13 +1769,11 @@ static void InitPlayerField(int x, int y, int element, boolean init_game) StorePlayer[x][y] = Tile[x][y]; #if DEBUG_INIT_PLAYER - if (options.debug) - { - printf("- player element %d activated", player->element_nr); - printf(" (local player is %d and currently %s)\n", - local_player->element_nr, - local_player->active ? "active" : "not active"); - } + Debug("game:init:player", "- player element %d activated", + player->element_nr); + Debug("game:init:player", " (local player is %d and currently %s)", + local_player->element_nr, + local_player->active ? "active" : "not active"); } #endif @@ -2149,8 +2147,9 @@ static void InitGameControlValues(void) if (nr != i) { - Error(ERR_INFO, "'game_panel_controls' structure corrupted at %d", i); - Error(ERR_EXIT, "this should not happen -- please debug"); + Error("'game_panel_controls' structure corrupted at %d", i); + + Fail("this should not happen -- please debug"); } // force update of game controls after initialization @@ -2252,6 +2251,7 @@ static void UpdateGameControlValues(void) level.game_engine_type == GAME_ENGINE_TYPE_MM ? MM_HEALTH(game_mm.laser_overload_value) : game.health); + int sync_random_frame = INIT_GFX_RANDOM(); // random, but synchronized UpdatePlayfieldElementCount(); @@ -2326,6 +2326,71 @@ static void UpdateGameControlValues(void) stored_player[player_nr].num_white_keys; } + // move keys to leftmost position in game panel, if defined by style settings + for (i = 0; i < MAX_NUM_KEYS + 1; i++) // all normal keys + white key + { + int nr = GAME_PANEL_KEY_1 + i; + struct GamePanelControlInfo *gpc = &game_panel_controls[nr]; + struct TextPosInfo *pos = gpc->pos; + + if (gpc->value == EL_EMPTY) + continue; + + if (pos->style != STYLE_LEFTMOST_POSITION) + continue; + + // check previous key positions (left from current key) + for (k = 0; k < i; k++) + { + int nr_new = GAME_PANEL_KEY_1 + k; + + if (game_panel_controls[nr_new].value == EL_EMPTY) + { + game_panel_controls[nr_new].value = gpc->value; + gpc->value = EL_EMPTY; + + break; + } + } + } + + // try to display as many collected keys as possible in the default game panel + for (i = STD_NUM_KEYS; i < MAX_NUM_KEYS + 1; i++) // EMC keys + white key + { + int nr = GAME_PANEL_KEY_1 + i; + int emc_key = get_key_element_from_nr(i); + int element = (i < MAX_NUM_KEYS ? emc_key : EL_DC_KEY_WHITE); + struct GamePanelControlInfo *gpc = &game_panel_controls[nr]; + struct TextPosInfo *pos = gpc->pos; + + // check if panel position is undefined for a certain EMC key or white key + if (gpc->value != EL_EMPTY && pos->x == -1 && pos->y == -1) + { + int nr_new = GAME_PANEL_KEY_1 + i % STD_NUM_KEYS; + + // 1st try: display key at the same position as normal or EM keys + if (game_panel_controls[nr_new].value == EL_EMPTY) + { + game_panel_controls[nr_new].value = element; + } + else + { + // 2nd try: display key at the next free position in the key panel + for (k = 0; k < STD_NUM_KEYS; k++) + { + nr_new = GAME_PANEL_KEY_1 + k; + + if (game_panel_controls[nr_new].value == EL_EMPTY) + { + game_panel_controls[nr_new].value = element; + + break; + } + } + } + } + } + for (i = 0; i < NUM_PANEL_INVENTORY; i++) { game_panel_controls[GAME_PANEL_INVENTORY_FIRST_1 + i].value = @@ -2479,11 +2544,13 @@ static void UpdateGameControlValues(void) int last_anim_random_frame = gfx.anim_random_frame; int element = gpc->value; int graphic = el2panelimg(element); + int init_gfx_random = (graphic_info[graphic].anim_global_sync ? + sync_random_frame : INIT_GFX_RANDOM()); if (gpc->value != gpc->last_value) { gpc->gfx_frame = 0; - gpc->gfx_random = INIT_GFX_RANDOM(); + gpc->gfx_random = init_gfx_random; } else { @@ -2491,7 +2558,7 @@ static void UpdateGameControlValues(void) if (ANIM_MODE(graphic) == ANIM_RANDOM && IS_NEXT_FRAME(gpc->gfx_frame, graphic)) - gpc->gfx_random = INIT_GFX_RANDOM(); + gpc->gfx_random = init_gfx_random; } if (ANIM_MODE(graphic) == ANIM_RANDOM) @@ -2500,8 +2567,7 @@ static void UpdateGameControlValues(void) if (ANIM_MODE(graphic) == ANIM_CE_SCORE) gpc->gfx_frame = element_info[element].collect_score; - gpc->frame = getGraphicAnimationFrame(el2panelimg(gpc->value), - gpc->gfx_frame); + gpc->frame = getGraphicAnimationFrame(graphic, gpc->gfx_frame); if (ANIM_MODE(graphic) == ANIM_RANDOM) gfx.anim_random_frame = last_anim_random_frame; @@ -2513,11 +2579,13 @@ static void UpdateGameControlValues(void) { int last_anim_random_frame = gfx.anim_random_frame; int graphic = gpc->graphic; + int init_gfx_random = (graphic_info[graphic].anim_global_sync ? + sync_random_frame : INIT_GFX_RANDOM()); if (gpc->value != gpc->last_value) { gpc->gfx_frame = 0; - gpc->gfx_random = INIT_GFX_RANDOM(); + gpc->gfx_random = init_gfx_random; } else { @@ -2525,7 +2593,7 @@ static void UpdateGameControlValues(void) if (ANIM_MODE(graphic) == ANIM_RANDOM && IS_NEXT_FRAME(gpc->gfx_frame, graphic)) - gpc->gfx_random = INIT_GFX_RANDOM(); + gpc->gfx_random = init_gfx_random; } if (ANIM_MODE(graphic) == ANIM_RANDOM) @@ -2590,6 +2658,10 @@ static void DisplayGameControlValues(void) if (PANEL_DEACTIVATED(pos)) continue; + if (pos->class == get_hash_from_key("extra_panel_items") && + !setup.prefer_extra_panel_items) + continue; + gpc->last_value = value; gpc->last_frame = frame; @@ -2637,7 +2709,10 @@ static void DisplayGameControlValues(void) element = value; graphic = el2panelimg(value); - // printf("::: %d, '%s' [%d]\n", element, EL_NAME(element), size); +#if 0 + Debug("game:DisplayGameControlValues", "%d, '%s' [%d]", + element, EL_NAME(element), size); +#endif if (element >= EL_GRAPHIC_1 && element <= EL_GRAPHIC_8 && size == 0) size = TILESIZE; @@ -2843,16 +2918,16 @@ static void InitGameEngine(void) } #if 0 - printf("level %d: level.game_version == %06d\n", level_nr, - level.game_version); - printf(" tape.file_version == %06d\n", - tape.file_version); - printf(" tape.game_version == %06d\n", - tape.game_version); - printf(" tape.engine_version == %06d\n", - tape.engine_version); - printf(" => game.engine_version == %06d [tape mode: %s]\n", - game.engine_version, (tape.playing ? "PLAYING" : "RECORDING")); + Debug("game:init:level", "level %d: level.game_version == %06d", level_nr, + level.game_version); + Debug("game:init:level", " tape.file_version == %06d", + tape.file_version); + Debug("game:init:level", " tape.game_version == %06d", + tape.game_version); + Debug("game:init:level", " tape.engine_version == %06d", + tape.engine_version); + Debug("game:init:level", " => game.engine_version == %06d [tape mode: %s]", + game.engine_version, (tape.playing ? "PLAYING" : "RECORDING")); #endif // -------------------------------------------------------------------------- @@ -3441,24 +3516,21 @@ static void DebugPrintPlayerStatus(char *message) if (!options.debug) return; - printf("%s:\n", message); + Debug("game:init:player", "%s:", message); for (i = 0; i < MAX_PLAYERS; i++) { struct PlayerInfo *player = &stored_player[i]; - printf("- player %d: present == %d, connected == %d [%d/%d], active == %d", - i + 1, - player->present, - player->connected, - player->connected_locally, - player->connected_network, - player->active); - - if (local_player == player) - printf(" (local player)"); - - printf("\n"); + Debug("game:init:player", + "- player %d: present == %d, connected == %d [%d/%d], active == %d%s", + i + 1, + player->present, + player->connected, + player->connected_locally, + player->connected_network, + player->active, + (local_player == player ? " (local player)" : "")); } } #endif @@ -3934,8 +4006,7 @@ void InitGame(void) #endif #if DEBUG_INIT_PLAYER - if (options.debug) - printf("Reassigning players ...\n"); + Debug("game:init:player", "Reassigning players ..."); #endif // check if any connected player was not found in playfield @@ -3948,8 +4019,8 @@ void InitGame(void) struct PlayerInfo *field_player = NULL; #if DEBUG_INIT_PLAYER - if (options.debug) - printf("- looking for field player for player %d ...\n", i + 1); + Debug("game:init:player", + "- looking for field player for player %d ...", i + 1); #endif // assign first free player found that is present in the playfield @@ -3974,8 +4045,8 @@ void InitGame(void) int jx = field_player->jx, jy = field_player->jy; #if DEBUG_INIT_PLAYER - if (options.debug) - printf("- found player %d\n", field_player->index_nr + 1); + Debug("game:init:player", "- found player %d", + field_player->index_nr + 1); #endif player->present = FALSE; @@ -4005,9 +4076,8 @@ void InitGame(void) field_player->mapped = TRUE; #if DEBUG_INIT_PLAYER - if (options.debug) - printf("- map_player_action[%d] == %d\n", - field_player->index_nr + 1, i + 1); + Debug("game:init:player", "- map_player_action[%d] == %d", + field_player->index_nr + 1, i + 1); #endif } } @@ -4062,7 +4132,8 @@ void InitGame(void) #endif #if 0 - printf("::: local_player->present == %d\n", local_player->present); + Debug("game:init:player", "local_player->present == %d", + local_player->present); #endif // set focus to local player for network games, else to all players @@ -4095,8 +4166,8 @@ void InitGame(void) int jx = player->jx, jy = player->jy; #if DEBUG_INIT_PLAYER - if (options.debug) - printf("Removing player %d at (%d, %d)\n", i + 1, jx, jy); + Debug("game:init:player", "Removing player %d at (%d, %d)", + i + 1, jx, jy); #endif player->active = FALSE; @@ -8776,8 +8847,9 @@ void AmoebaToDiamond(int ax, int ay) #ifdef DEBUG if (group_nr == 0) { - printf("AmoebaToDiamond(): ax = %d, ay = %d\n", ax, ay); - printf("AmoebaToDiamond(): This should never happen!\n"); + Debug("game:playing:AmoebaToDiamond", "ax = %d, ay = %d", ax, ay); + Debug("game:playing:AmoebaToDiamond", "This should never happen!"); + return; } #endif @@ -8834,8 +8906,9 @@ static void AmoebaToDiamondBD(int ax, int ay, int new_element) #ifdef DEBUG if (group_nr == 0) { - printf("AmoebaToDiamondBD(): ax = %d, ay = %d\n", ax, ay); - printf("AmoebaToDiamondBD(): This should never happen!\n"); + Debug("game:playing:AmoebaToDiamondBD", "ax = %d, ay = %d", ax, ay); + Debug("game:playing:AmoebaToDiamondBD", "This should never happen!"); + return; } #endif @@ -9043,8 +9116,10 @@ static void AmoebaReproduce(int ax, int ay) #ifdef DEBUG if (new_group_nr == 0) { - printf("AmoebaReproduce(): newax = %d, neway = %d\n", newax, neway); - printf("AmoebaReproduce(): This should never happen!\n"); + Debug("game:playing:AmoebaReproduce", "newax = %d, neway = %d", + newax, neway); + Debug("game:playing:AmoebaReproduce", "This should never happen!"); + return; } #endif @@ -10660,11 +10735,9 @@ static void HandleElementChange(int x, int y, int page) if (!CAN_CHANGE_OR_HAS_ACTION(element) && !CAN_CHANGE_OR_HAS_ACTION(Back[x][y])) { - printf("\n\n"); - printf("HandleElementChange(): %d,%d: element = %d ('%s')\n", - x, y, element, element_info[element].token_name); - printf("HandleElementChange(): This should never happen!\n"); - printf("\n\n"); + Debug("game:playing:HandleElementChange", "%d,%d: element = %d ('%s')", + x, y, element, element_info[element].token_name); + Debug("game:playing:HandleElementChange", "This should never happen!"); } #endif @@ -11200,6 +11273,15 @@ static void CheckSaveEngineSnapshot(struct PlayerInfo *player) if (!player->is_dropping) player->was_dropping = FALSE; } + + static struct MouseActionInfo mouse_action_last = { 0 }; + struct MouseActionInfo mouse_action = player->effective_mouse_action; + boolean new_released = (!mouse_action.button && mouse_action_last.button); + + if (new_released) + CheckSaveEngineSnapshotToList(); + + mouse_action_last = mouse_action; } static void CheckSingleStepMode(struct PlayerInfo *player) @@ -11210,7 +11292,8 @@ static void CheckSingleStepMode(struct PlayerInfo *player) player stopped moving after one tile (or never starts moving at all) */ if (!player->is_moving && !player->is_pushing && - !player->is_dropping_pressed) + !player->is_dropping_pressed && + !player->effective_mouse_action.button) TapeTogglePause(TAPE_TOGGLE_AUTOMATIC); } @@ -11544,7 +11627,7 @@ static void GameActionsExt(void) int skip = WaitUntilDelayReached(&game_frame_delay, game_frame_delay_value); - printf("::: skip == %d\n", skip); + Debug("game:playing:skip", "skip == %d", skip); #else // ---------- main game synchronization point ---------- @@ -11661,9 +11744,8 @@ static void GameActionsExt(void) byte mapped_action[MAX_PLAYERS]; #if DEBUG_PLAYER_ACTIONS - printf(":::"); for (i = 0; i < MAX_PLAYERS; i++) - printf(" %d, ", stored_player[i].effective_action); + DebugContinued("", "%d, ", stored_player[i].effective_action); #endif for (i = 0; i < MAX_PLAYERS; i++) @@ -11673,19 +11755,18 @@ static void GameActionsExt(void) stored_player[i].effective_action = mapped_action[i]; #if DEBUG_PLAYER_ACTIONS - printf(" =>"); + DebugContinued("", "=> "); for (i = 0; i < MAX_PLAYERS; i++) - printf(" %d, ", stored_player[i].effective_action); - printf("\n"); + DebugContinued("", "%d, ", stored_player[i].effective_action); + DebugContinued("game:playing:player", "\n"); #endif } #if DEBUG_PLAYER_ACTIONS else { - printf(":::"); for (i = 0; i < MAX_PLAYERS; i++) - printf(" %d, ", stored_player[i].effective_action); - printf("\n"); + DebugContinued("", "%d, ", stored_player[i].effective_action); + DebugContinued("game:playing:player", "\n"); } #endif #endif @@ -11962,8 +12043,9 @@ void GameActions_RND(void) #if DEBUG if (ChangePage[x][y] != -1 && ChangeDelay[x][y] != 1) { - printf("GameActions(): x = %d, y = %d: ChangePage != -1\n", x, y); - printf("GameActions(): This should never happen!\n"); + Debug("game:playing:GameActions_RND", "x = %d, y = %d: ChangePage != -1", + x, y); + Debug("game:playing:GameActions_RND", "This should never happen!"); ChangePage[x][y] = -1; } @@ -11997,10 +12079,10 @@ void GameActions_RND(void) Blocked2Moving(x, y, &oldx, &oldy); if (!IS_MOVING(oldx, oldy)) { - printf("GameActions(): (BLOCKED => MOVING) context corrupted!\n"); - printf("GameActions(): BLOCKED: x = %d, y = %d\n", x, y); - printf("GameActions(): !MOVING: oldx = %d, oldy = %d\n", oldx, oldy); - printf("GameActions(): This should never happen!\n"); + Debug("game:playing:GameActions_RND", "(BLOCKED => MOVING) context corrupted!"); + Debug("game:playing:GameActions_RND", "BLOCKED: x = %d, y = %d", x, y); + Debug("game:playing:GameActions_RND", "!MOVING: oldx = %d, oldy = %d", oldx, oldy); + Debug("game:playing:GameActions_RND", "This should never happen!"); } } #endif @@ -12641,8 +12723,9 @@ boolean MovePlayer(struct PlayerInfo *player, int dx, int dy) int original_move_delay_value = player->move_delay_value; #if DEBUG - printf("THIS SHOULD ONLY HAPPEN WITH PRE-1.2 LEVEL TAPES. [%d]\n", - tape.counter); + Debug("game:playing:MovePlayer", + "THIS SHOULD ONLY HAPPEN WITH PRE-1.2 LEVEL TAPES. [%d]", + tape.counter); #endif // scroll remaining steps with finest movement resolution @@ -13567,8 +13650,9 @@ void KillPlayer(struct PlayerInfo *player) return; #if 0 - printf("::: 0: killed == %d, active == %d, reanimated == %d\n", - player->killed, player->active, player->reanimated); + Debug("game:playing:KillPlayer", + "0: killed == %d, active == %d, reanimated == %d", + player->killed, player->active, player->reanimated); #endif /* the following code was introduced to prevent an infinite loop when calling @@ -13596,15 +13680,17 @@ void KillPlayer(struct PlayerInfo *player) player->shield_deadly_time_left = 0; #if 0 - printf("::: 1: killed == %d, active == %d, reanimated == %d\n", - player->killed, player->active, player->reanimated); + Debug("game:playing:KillPlayer", + "1: killed == %d, active == %d, reanimated == %d", + player->killed, player->active, player->reanimated); #endif Bang(jx, jy); #if 0 - printf("::: 2: killed == %d, active == %d, reanimated == %d\n", - player->killed, player->active, player->reanimated); + Debug("game:playing:KillPlayer", + "2: killed == %d, active == %d, reanimated == %d", + player->killed, player->active, player->reanimated); #endif if (player->reanimated) // killed player may have been reanimated @@ -13984,6 +14070,10 @@ static int DigField(struct PlayerInfo *player, CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_DIGS_X, player->index_bit, dig_side); + // if digging triggered player relocation, finish digging tile + if (mode == DF_DIG && (player->jx != jx || player->jy != jy)) + setFieldForSnapping(x, y, element, move_direction); + if (mode == DF_SNAP) { if (level.block_snap_field) @@ -14105,9 +14195,15 @@ static int DigField(struct PlayerInfo *player, PlayLevelSoundElementAction(x, y, element, ACTION_COLLECTING); if (is_player) + { CheckTriggeredElementChangeByPlayer(x, y, element, CE_PLAYER_COLLECTS_X, player->index_bit, dig_side); + // if collecting triggered player relocation, finish collecting tile + if (mode == DF_DIG && (player->jx != jx || player->jy != jy)) + setFieldForSnapping(x, y, element, move_direction); + } + if (mode == DF_SNAP) { if (level.block_snap_field) @@ -15229,6 +15325,9 @@ void RequestRestartGame(char *message) } else { + // needed in case of envelope request to close game panel + CloseDoor(DOOR_CLOSE_1); + SetGameStatus(GAME_MODE_MAIN); DrawMainMenu(); @@ -15420,10 +15519,11 @@ static void LoadEngineSnapshotValues_RND(void) if (game.num_random_calls != num_random_calls) { - Error(ERR_INFO, "number of random calls out of sync"); - Error(ERR_INFO, "number of random calls should be %d", num_random_calls); - Error(ERR_INFO, "number of random calls is %d", game.num_random_calls); - Error(ERR_EXIT, "this should not happen -- please debug"); + Error("number of random calls out of sync"); + Error("number of random calls should be %d", num_random_calls); + Error("number of random calls is %d", game.num_random_calls); + + Fail("this should not happen -- please debug"); } } @@ -15536,7 +15636,8 @@ static ListNode *SaveEngineSnapshotBuffers(void) node = node->next; } - printf("::: size of engine snapshot: %d bytes\n", num_bytes); + Debug("game:playing:SaveEngineSnapshotBuffers", + "size of engine snapshot: %d bytes", num_bytes); #endif return buffers; @@ -15831,7 +15932,7 @@ void CreateGameButtons(void) GDI_END); if (gi == NULL) - Error(ERR_EXIT, "cannot create gadget"); + Fail("cannot create gadget"); game_gadget[id] = gi; }