X-Git-Url: https://git.artsoft.org/?p=rocksndiamonds.git;a=blobdiff_plain;f=src%2Fgame.c;h=8b9d1132f23e7588ac0c6bb68ebabf0bc4ed58d2;hp=0468be7fa87a4be79be812213f84ecf3a8e9fd0b;hb=2486a7a849210371bb59e733e37b0271a4332d8b;hpb=ae1359da280d87576ff65d7cb5c407cd35983472 diff --git a/src/game.c b/src/game.c index 0468be7f..8b9d1132 100644 --- a/src/game.c +++ b/src/game.c @@ -21,6 +21,11 @@ #include "tape.h" #include "network.h" + +/* DEBUG SETTINGS */ +#define DEBUG_INIT_PLAYER 1 +#define DEBUG_PLAYER_ACTIONS 0 + /* EXPERIMENTAL STUFF */ #define USE_NEW_AMOEBA_CODE FALSE @@ -1009,8 +1014,10 @@ static struct GamePanelControlInfo game_panel_controls[] = #define SOUND_CTRL_ID_MUSIC 3 #define SOUND_CTRL_ID_LOOPS 4 #define SOUND_CTRL_ID_SIMPLE 5 +#define GAME_CTRL_ID_SAVE 6 +#define GAME_CTRL_ID_LOAD 7 -#define NUM_GAME_BUTTONS 6 +#define NUM_GAME_BUTTONS 8 /* forward declaration for internal use */ @@ -1077,7 +1084,6 @@ static void PlayLevelSoundActionIfLoop(int, int, int); static void StopLevelSoundActionIfLoop(int, int, int); static void PlayLevelMusic(); -static void MapGameButtons(); static void HandleGameButtons(struct GadgetInfo *); int AmoebeNachbarNr(int, int); @@ -1740,14 +1746,16 @@ static void InitPlayerField(int x, int y, int element, boolean init_game) StorePlayer[x][y] = Feld[x][y]; +#if DEBUG_INIT_PLAYER if (options.debug) { - printf("Player %d activated.\n", player->element_nr); - printf("[Local player is %d and currently %s.]\n", + 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"); } } +#endif Feld[x][y] = EL_EMPTY; @@ -3023,6 +3031,21 @@ static void InitGameEngine() game.engine_version = (tape.playing ? tape.engine_version : level.game_version); + /* set single or multi-player game mode (needed for re-playing tapes) */ + game.team_mode = setup.team_mode; + + if (tape.playing) + { + int num_players = 0; + + for (i = 0; i < MAX_PLAYERS; i++) + if (tape.player_participates[i]) + num_players++; + + /* multi-player tapes contain input data for more than one player */ + game.team_mode = (num_players > 1); + } + /* ---------------------------------------------------------------------- */ /* set flags for bugs and changes according to active game engine version */ /* ---------------------------------------------------------------------- */ @@ -3497,6 +3520,9 @@ int get_num_special_action(int element, int action_first, int action_last) void InitGame() { + int full_lev_fieldx = lev_fieldx + (BorderElement != EL_EMPTY ? 2 : 0); + int full_lev_fieldy = lev_fieldy + (BorderElement != EL_EMPTY ? 2 : 0); + boolean emulate_bd = TRUE; /* unless non-BOULDERDASH elements found */ boolean emulate_sb = TRUE; /* unless non-SOKOBAN elements found */ boolean emulate_sp = TRUE; /* unless non-SUPAPLEX elements found */ @@ -3510,7 +3536,46 @@ void InitGame() #endif int i, j, x, y; +#if 1 + game_status = GAME_MODE_PLAYING; +#endif + +#if 1 + + StopAnimation(); + + if (!game.restart_level) + CloseDoor(DOOR_CLOSE_1); + +#if 1 + if (level_editor_test_game) + FadeSkipNextFadeIn(); + else + FadeSetEnterScreen(); +#else + if (level_editor_test_game) + fading = fading_none; + else + fading = menu.destination; +#endif + +#if 1 + FadeOut(REDRAW_FIELD); +#else + if (do_fading) + FadeOut(REDRAW_FIELD); +#endif + +#endif + +#if 0 + printf("::: FADING OUT: DONE\n"); + Delay(1000); +#endif + +#if 0 game_status = GAME_MODE_PLAYING; +#endif #if 1 /* needed if different viewport properties defined for playing */ @@ -3753,6 +3818,13 @@ void InitGame() for (i = 0; i < MAX_NUM_AMOEBA; i++) AmoebaCnt[i] = AmoebaCnt2[i] = 0; +#if DEBUG_INIT_PLAYER + if (options.debug) + { + printf("Player status at level initialization:\n"); + } +#endif + SCAN_PLAYFIELD(x, y) { Feld[x][y] = level.field[x][y]; @@ -3886,16 +3958,25 @@ void InitGame() local_player->connected = TRUE; /* !!! SAME AS init.c:InitPlayerInfo() -- FIX THIS !!! */ +#if 0 + printf("::: TEAM MODE: %d\n", game.team_mode); +#endif + if (tape.playing) { +#if 1 + for (i = 0; i < MAX_PLAYERS; i++) + stored_player[i].connected = tape.player_participates[i]; +#else /* try to guess locally connected team mode players (needed for correct assignment of player figures from level to locally playing players) */ for (i = 0; i < MAX_PLAYERS; i++) if (tape.player_participates[i]) stored_player[i].connected = TRUE; +#endif } - else if (setup.team_mode && !options.network) + else if (game.team_mode && !options.network) { /* try to guess locally connected team mode players (needed for correct assignment of player figures from level to locally playing players) */ @@ -3906,14 +3987,32 @@ void InitGame() stored_player[i].connected = TRUE; } -#if 0 - for (i = 0; i < MAX_PLAYERS; i++) - printf("::: player %d: %s\n", i, - (stored_player[i].connected ? "connected" : "not connected")); +#if DEBUG_INIT_PLAYER + if (options.debug) + { + printf("Player status after level initialization:\n"); - for (i = 0; i < MAX_PLAYERS; i++) - printf("::: player %d: %s\n", i, - (stored_player[i].present ? "present" : "not present")); + for (i = 0; i < MAX_PLAYERS; i++) + { + struct PlayerInfo *player = &stored_player[i]; + + printf("- player %d: present == %d, connected == %d, active == %d", + i + 1, + player->present, + player->connected, + player->active); + + if (local_player == player) + printf(" (local player)"); + + printf("\n"); + } + } +#endif + +#if DEBUG_INIT_PLAYER + if (options.debug) + printf("Reassigning players ...\n"); #endif /* check if any connected player was not found in playfield */ @@ -3925,12 +4024,29 @@ void InitGame() { struct PlayerInfo *field_player = NULL; -#if 0 - printf("::: looking for field player for player %d ...\n", i); +#if DEBUG_INIT_PLAYER + if (options.debug) + printf("- looking for field player for player %d ...\n", i + 1); #endif /* assign first free player found that is present in the playfield */ +#if 1 + /* first try: look for unmapped playfield player that is not connected */ + for (j = 0; j < MAX_PLAYERS; j++) + if (field_player == NULL && + stored_player[j].present && + !stored_player[j].mapped && + !stored_player[j].connected) + field_player = &stored_player[j]; + + /* second try: look for *any* unmapped playfield player */ + for (j = 0; j < MAX_PLAYERS; j++) + if (field_player == NULL && + stored_player[j].present && + !stored_player[j].mapped) + field_player = &stored_player[j]; +#else /* first try: look for unmapped playfield player that is not connected */ if (field_player == NULL) for (j = 0; j < MAX_PLAYERS; j++) @@ -3945,13 +4061,15 @@ void InitGame() if (stored_player[j].present && !stored_player[j].mapped) field_player = &stored_player[j]; +#endif if (field_player != NULL) { int jx = field_player->jx, jy = field_player->jy; -#if 0 - printf("::: found player figure %d\n", field_player->index_nr); +#if DEBUG_INIT_PLAYER + if (options.debug) + printf("- found player %d\n", field_player->index_nr + 1); #endif player->present = FALSE; @@ -3980,9 +4098,10 @@ void InitGame() field_player->mapped = TRUE; -#if 0 - printf("::: map_player_action[%d] == %d\n", - field_player->index_nr, i); +#if DEBUG_INIT_PLAYER + if (options.debug) + printf("- map_player_action[%d] == %d\n", + field_player->index_nr + 1, i + 1); #endif } } @@ -3991,6 +4110,29 @@ void InitGame() player->mapped = TRUE; } +#if DEBUG_INIT_PLAYER + if (options.debug) + { + printf("Player status after player assignment (first stage):\n"); + + for (i = 0; i < MAX_PLAYERS; i++) + { + struct PlayerInfo *player = &stored_player[i]; + + printf("- player %d: present == %d, connected == %d, active == %d", + i + 1, + player->present, + player->connected, + player->active); + + if (local_player == player) + printf(" (local player)"); + + printf("\n"); + } + } +#endif + #else /* check if any connected player was not found in playfield */ @@ -4041,6 +4183,11 @@ void InitGame() /* when playing a tape, eliminate all players who do not participate */ #if USE_NEW_PLAYER_ASSIGNMENTS + +#if 1 + if (!game.team_mode) +#endif + for (i = 0; i < MAX_PLAYERS; i++) { if (stored_player[i].active && @@ -4049,12 +4196,19 @@ void InitGame() struct PlayerInfo *player = &stored_player[i]; 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); +#endif + player->active = FALSE; StorePlayer[jx][jy] = 0; Feld[jx][jy] = EL_EMPTY; } } + #else + for (i = 0; i < MAX_PLAYERS; i++) { if (stored_player[i].active && @@ -4070,7 +4224,7 @@ void InitGame() } #endif } - else if (!options.network && !setup.team_mode) /* && !tape.playing */ + else if (!options.network && !game.team_mode) /* && !tape.playing */ { /* when in single player mode, eliminate all but the first active player */ @@ -4110,21 +4264,28 @@ void InitGame() #endif } +#if DEBUG_INIT_PLAYER if (options.debug) { + printf("Player status after player assignment (final stage):\n"); + for (i = 0; i < MAX_PLAYERS; i++) { struct PlayerInfo *player = &stored_player[i]; - printf("Player %d: present == %d, connected == %d, active == %d.\n", - i+1, + printf("- player %d: present == %d, connected == %d, active == %d", + i + 1, player->present, player->connected, player->active); + if (local_player == player) - printf("Player %d is local player.\n", i+1); + printf(" (local player)"); + + printf("\n"); } } +#endif if (BorderElement == EL_EMPTY) { @@ -4143,16 +4304,44 @@ void InitGame() #if NEW_TILESIZE + // printf("::: START-0: %d, %d\n", lev_fieldx, SCR_FIELDX); + // printf("::: START-1: %d, %d\n", SBX_Left, SBX_Right); + +#if 1 + if (full_lev_fieldx <= SCR_FIELDX) + SBX_Left = SBX_Right = -1 * (SCR_FIELDX - lev_fieldx) / 2; + + if (full_lev_fieldy <= SCR_FIELDY) + SBY_Upper = SBY_Lower = -1 * (SCR_FIELDY - lev_fieldy) / 2; +#else if (lev_fieldx + (SBX_Left < 0 ? 2 : 0) <= SCR_FIELDX) SBX_Left = SBX_Right = -1 * (SCR_FIELDX - lev_fieldx) / 2; if (lev_fieldy + (SBY_Upper < 0 ? 2 : 0) <= SCR_FIELDY) SBY_Upper = SBY_Lower = -1 * (SCR_FIELDY - lev_fieldy) / 2; +#endif + /* + printf("::: START-2: %d, %d (%d)\n", SBX_Left, SBX_Right, + SBX_Right - SBX_Left + 1); + */ + +#if 1 + if (EVEN(SCR_FIELDX) && full_lev_fieldx > SCR_FIELDX) + SBX_Left--; + if (EVEN(SCR_FIELDY) && full_lev_fieldy > SCR_FIELDY) + SBY_Upper--; +#else if (EVEN(SCR_FIELDX)) SBX_Left--; if (EVEN(SCR_FIELDY)) SBY_Upper--; +#endif + + /* + printf("::: START-3: %d, %d\n", SBX_Left, SBX_Right); + printf("\n"); + */ #else @@ -4281,6 +4470,8 @@ void InitGame() game_status = GAME_MODE_MAIN; #endif +#if 0 + StopAnimation(); if (!game.restart_level) @@ -4305,6 +4496,8 @@ void InitGame() FadeOut(REDRAW_FIELD); #endif +#endif + #if 0 game_status = GAME_MODE_PLAYING; #endif @@ -4398,8 +4591,12 @@ void InitGame() MapTapeButtons(); /* copy actual game door content to door double buffer for OpenDoor() */ +#if 1 + BlitBitmap(drawto, bitmap_db_door_1, DX, DY, DXSIZE, DYSIZE, 0, 0); +#else BlitBitmap(drawto, bitmap_db_door, DX, DY, DXSIZE, DYSIZE, DOOR_GFX_PAGEX1, DOOR_GFX_PAGEY1); +#endif OpenDoor(DOOR_OPEN_ALL); @@ -4410,12 +4607,28 @@ void InitGame() KeyboardAutoRepeatOffUnlessAutoplay(); +#if DEBUG_INIT_PLAYER if (options.debug) { + printf("Player status (final):\n"); + for (i = 0; i < MAX_PLAYERS; i++) - printf("Player %d %sactive.\n", - i + 1, (stored_player[i].active ? "" : "not ")); + { + struct PlayerInfo *player = &stored_player[i]; + + printf("- player %d: present == %d, connected == %d, active == %d", + i + 1, + player->present, + player->connected, + player->active); + + if (local_player == player) + printf(" (local player)"); + + printf("\n"); + } } +#endif } #if 1 @@ -11872,7 +12085,6 @@ static void CheckSingleStepMode(struct PlayerInfo *player) static byte PlayerActions(struct PlayerInfo *player, byte player_action) { - boolean moved = FALSE, snapped = FALSE, dropped = FALSE; int left = player_action & JOY_LEFT; int right = player_action & JOY_RIGHT; int up = player_action & JOY_UP; @@ -11888,13 +12100,13 @@ static byte PlayerActions(struct PlayerInfo *player, byte player_action) if (player_action) { if (button1) - snapped = SnapField(player, dx, dy); + SnapField(player, dx, dy); else { if (button2) - dropped = DropElement(player); + DropElement(player); - moved = MovePlayer(player, dx, dy); + MovePlayer(player, dx, dy); } CheckSingleStepMode(player); @@ -12127,9 +12339,9 @@ void GameActions() /* detect endless loops, caused by custom element programming */ if (recursion_loop_detected && recursion_loop_depth == 0) { - char *message = getStringCat3("Internal Error ! Element ", + char *message = getStringCat3("Internal Error! Element ", EL_NAME(recursion_loop_element), - " caused endless loop ! Quit the game ?"); + " caused endless loop! Quit the game?"); Error(ERR_WARN, "element '%s' caused endless loop in game engine", EL_NAME(recursion_loop_element)); @@ -12244,8 +12456,13 @@ void GameActions() { summarized_player_action |= stored_player[i].action; +#if 1 + if (!network_playing && (game.team_mode || tape.playing)) + stored_player[i].effective_action = stored_player[i].action; +#else if (!network_playing) stored_player[i].effective_action = stored_player[i].action; +#endif } #if defined(NETWORK_AVALIABLE) @@ -12253,10 +12470,13 @@ void GameActions() SendToServer_MovePlayer(summarized_player_action); #endif - if (!options.network && !setup.team_mode) + if (!options.network && !game.team_mode) local_player->effective_action = summarized_player_action; - if (setup.team_mode && setup.input_on_focus && game.centered_player_nr != -1) + if (tape.recording && + setup.team_mode && + setup.input_on_focus && + game.centered_player_nr != -1) { for (i = 0; i < MAX_PLAYERS; i++) stored_player[i].effective_action = @@ -12271,9 +12491,19 @@ void GameActions() { tape_action[i] = stored_player[i].effective_action; +#if 1 + /* (this may happen in the RND game engine if a player was not present on + the playfield on level start, but appeared later from a custom element */ + if (tape.recording && + setup.team_mode && + tape_action[i] && + !tape.player_participates[i]) + tape.player_participates[i] = TRUE; +#else /* (this can only happen in the R'n'D game engine) */ if (tape.recording && tape_action[i] && !tape.player_participates[i]) tape.player_participates[i] = TRUE; /* player just appeared from CE */ +#endif } /* only record actions from input devices, but not programmed actions */ @@ -12281,16 +12511,76 @@ void GameActions() TapeRecordAction(tape_action); #if USE_NEW_PLAYER_ASSIGNMENTS +#if 1 + if (game.team_mode) +#endif { byte mapped_action[MAX_PLAYERS]; +#if DEBUG_PLAYER_ACTIONS + printf(":::"); + for (i = 0; i < MAX_PLAYERS; i++) + printf(" %d, ", stored_player[i].effective_action); +#endif + for (i = 0; i < MAX_PLAYERS; i++) mapped_action[i] = stored_player[map_player_action[i]].effective_action; for (i = 0; i < MAX_PLAYERS; i++) stored_player[i].effective_action = mapped_action[i]; + +#if DEBUG_PLAYER_ACTIONS + printf(" =>"); + for (i = 0; i < MAX_PLAYERS; i++) + printf(" %d, ", stored_player[i].effective_action); + printf("\n"); +#endif + } +#if DEBUG_PLAYER_ACTIONS + else + { + printf(":::"); + for (i = 0; i < MAX_PLAYERS; i++) + printf(" %d, ", stored_player[i].effective_action); + printf("\n"); } #endif +#endif + +#if 0 + printf("::: summarized_player_action == %d\n", + local_player->effective_action); +#endif + + + + +#if 0 +#if DEBUG_INIT_PLAYER + if (options.debug) + { + printf("Player status (final):\n"); + + for (i = 0; i < MAX_PLAYERS; i++) + { + struct PlayerInfo *player = &stored_player[i]; + + printf("- player %d: present == %d, connected == %d, active == %d", + i + 1, + player->present, + player->connected, + player->active); + + if (local_player == player) + printf(" (local player)"); + + printf("\n"); + } + } +#endif +#endif + + if (level.game_engine_type == GAME_ENGINE_TYPE_EM) { @@ -15803,14 +16093,19 @@ static boolean DropElement(struct PlayerInfo *player) if (IS_CUSTOM_ELEMENT(new_element) && CAN_MOVE(new_element) && element_info[new_element].move_pattern == MV_WHEN_DROPPED) { - int move_direction, nextx, nexty; +#if 0 + int move_direction; + int nextx, nexty; +#endif if (element_info[new_element].move_direction_initial == MV_START_AUTOMATIC) MovDir[dropx][dropy] = drop_direction; +#if 0 move_direction = MovDir[dropx][dropy]; nextx = dropx + GET_DX_FROM_DIR(move_direction); nexty = dropy + GET_DY_FROM_DIR(move_direction); +#endif ChangeCount[dropx][dropy] = 0; /* allow at least one more change */ @@ -16224,6 +16519,12 @@ void RequestQuitGameExt(boolean skip_request, boolean quick_quit, char *message) { if (skip_request || Request(message, REQ_ASK | REQ_STAY_CLOSED)) { +#if 1 + /* closing door required in case of envelope style request dialogs */ + if (!skip_request) + CloseDoor(DOOR_CLOSE_1); +#endif + #if defined(NETWORK_AVALIABLE) if (options.network) SendToServer_StopPlaying(NETWORK_STOP_BY_PLAYER); @@ -16282,7 +16583,7 @@ void RequestQuitGame(boolean ask_if_really_quit) boolean skip_request = AllPlayersGone || quick_quit; RequestQuitGameExt(skip_request, quick_quit, - "Do you really want to quit the game ?"); + "Do you really want to quit the game?"); } @@ -16587,6 +16888,14 @@ static struct { IMG_GAME_BUTTON_GFX_SOUND_SIMPLE, &game.button.sound_simple, SOUND_CTRL_ID_SIMPLE, "normal sounds on/off" + }, + { + IMG_GAME_BUTTON_GFX_SAVE, &game.button.save, + GAME_CTRL_ID_SAVE, "save game" + }, + { + IMG_GAME_BUTTON_GFX_LOAD, &game.button.load, + GAME_CTRL_ID_LOAD, "load game" } }; @@ -16602,6 +16911,8 @@ void CreateGameButtons() int button_type; boolean checked; unsigned int event_mask; + int base_x = (tape.show_game_buttons ? VX : DX); + int base_y = (tape.show_game_buttons ? VY : DY); int gd_x = gfx->src_x; int gd_y = gfx->src_y; int gd_xp = gfx->src_x + gfx->pressed_xoffset; @@ -16612,9 +16923,18 @@ void CreateGameButtons() int gd_yap = gfx->src_y + gfx->active_yoffset + gfx->pressed_yoffset; int id = i; + if (gfx->bitmap == NULL) + { + game_gadget[id] = NULL; + + continue; + } + if (id == GAME_CTRL_ID_STOP || id == GAME_CTRL_ID_PAUSE || - id == GAME_CTRL_ID_PLAY) + id == GAME_CTRL_ID_PLAY || + id == GAME_CTRL_ID_SAVE || + id == GAME_CTRL_ID_LOAD) { button_type = GD_TYPE_NORMAL_BUTTON; checked = FALSE; @@ -16632,8 +16952,8 @@ void CreateGameButtons() gi = CreateGadget(GDI_CUSTOM_ID, id, GDI_INFO_TEXT, gamebutton_info[i].infotext, - GDI_X, DX + pos->x, - GDI_Y, DY + pos->y, + GDI_X, base_x + GDI_ACTIVE_POS(pos->x), + GDI_Y, base_y + GDI_ACTIVE_POS(pos->y), GDI_WIDTH, gfx->width, GDI_HEIGHT, gfx->height, GDI_TYPE, button_type, @@ -16663,7 +16983,7 @@ void FreeGameButtons() FreeGadget(game_gadget[i]); } -static void MapGameButtons() +void MapGameButtons() { int i; @@ -16689,20 +17009,28 @@ void RedrawGameButtons() static void HandleGameButtonsExt(int id) { - if (game_status != GAME_MODE_PLAYING) + boolean handle_game_buttons = + (game_status == GAME_MODE_PLAYING || + (game_status == GAME_MODE_MAIN && tape.show_game_buttons)); + + if (!handle_game_buttons) return; switch (id) { case GAME_CTRL_ID_STOP: + if (game_status == GAME_MODE_MAIN) + break; + if (tape.playing) TapeStop(); else RequestQuitGame(TRUE); + break; case GAME_CTRL_ID_PAUSE: - if (options.network) + if (options.network && game_status == GAME_MODE_PLAYING) { #if defined(NETWORK_AVALIABLE) if (tape.pausing) @@ -16716,7 +17044,11 @@ static void HandleGameButtonsExt(int id) break; case GAME_CTRL_ID_PLAY: - if (tape.pausing) + if (game_status == GAME_MODE_MAIN) + { + StartGameActions(options.network, setup.autorecord, level.random_seed); + } + else if (tape.pausing) { #if defined(NETWORK_AVALIABLE) if (options.network) @@ -16769,6 +17101,14 @@ static void HandleGameButtonsExt(int id) } break; + case GAME_CTRL_ID_SAVE: + TapeQuickSave(); + break; + + case GAME_CTRL_ID_LOAD: + TapeQuickLoad(); + break; + default: break; }