X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Fgame.c;h=a9c903cceb5bab85072c08f8cb43cf9fcb632eea;hb=2fe139696892ee39f804b5c7315b8f0977ab01ec;hp=1fbb21a5cef1115e2672f62d0f3dd47f907f9da4;hpb=776100a335243955272732ccba109d366e0ba3fd;p=rocksndiamonds.git diff --git a/src/game.c b/src/game.c index 1fbb21a5..a9c903cc 100644 --- a/src/game.c +++ b/src/game.c @@ -23,6 +23,9 @@ #include "joystick.h" #include "network.h" +/* this switch controls how rocks move horizontally */ +#define OLD_GAME_BEHAVIOUR FALSE + /* for DigField() */ #define DF_NO_PUSH 0 #define DF_DIG 1 @@ -144,7 +147,7 @@ static unsigned int getStateCheckSum(int counter) checksum += mult++ * StorePlayer[x][y]; checksum += mult++ * Frame[x][y]; checksum += mult++ * AmoebaNr[x][y]; - checksum += mult++ * JustHit[x][y]; + checksum += mult++ * JustStopped[x][y]; checksum += mult++ * Stop[x][y]; */ } @@ -176,6 +179,50 @@ void GetPlayerConfig() InitJoysticks(); } +static int getBeltNrFromElement(int element) +{ + return (element < EL_BELT2_LEFT ? 0 : + element < EL_BELT3_LEFT ? 1 : + element < EL_BELT4_LEFT ? 2 : 3); +} + +static int getBeltNrFromSwitchElement(int element) +{ + return (element < EL_BELT2_SWITCH_L ? 0 : + element < EL_BELT3_SWITCH_L ? 1 : + element < EL_BELT4_SWITCH_L ? 2 : 3); +} + +static int getBeltDirNrFromSwitchElement(int element) +{ + static int belt_base_element[4] = + { + EL_BELT1_SWITCH_L, + EL_BELT2_SWITCH_L, + EL_BELT3_SWITCH_L, + EL_BELT4_SWITCH_L + }; + + int belt_nr = getBeltNrFromSwitchElement(element); + int belt_dir_nr = element - belt_base_element[belt_nr]; + + return (belt_dir_nr % 3); +} + +static int getBeltDirFromSwitchElement(int element) +{ + static int belt_move_dir[3] = + { + MV_LEFT, + MV_NO_MOVING, + MV_RIGHT + }; + + int belt_dir_nr = getBeltDirNrFromSwitchElement(element); + + return belt_move_dir[belt_dir_nr]; +} + static void InitField(int x, int y, boolean init_game) { switch (Feld[x][y]) @@ -319,6 +366,46 @@ static void InitField(int x, int y, boolean init_game) Feld[x][y] = EL_EM_KEY_4; break; + case EL_BELT1_SWITCH_L: + case EL_BELT1_SWITCH_M: + case EL_BELT1_SWITCH_R: + case EL_BELT2_SWITCH_L: + case EL_BELT2_SWITCH_M: + case EL_BELT2_SWITCH_R: + case EL_BELT3_SWITCH_L: + case EL_BELT3_SWITCH_M: + case EL_BELT3_SWITCH_R: + case EL_BELT4_SWITCH_L: + case EL_BELT4_SWITCH_M: + case EL_BELT4_SWITCH_R: + if (init_game) + { + int belt_nr = getBeltNrFromSwitchElement(Feld[x][y]); + int belt_dir = getBeltDirFromSwitchElement(Feld[x][y]); + int belt_dir_nr = getBeltDirNrFromSwitchElement(Feld[x][y]); + + if (game.belt_dir_nr[belt_nr] == 3) /* initial value */ + { + game.belt_dir[belt_nr] = belt_dir; + game.belt_dir_nr[belt_nr] = belt_dir_nr; + } + else /* more than one switch -- set it like the first switch */ + { + Feld[x][y] = Feld[x][y] - belt_dir_nr + game.belt_dir_nr[belt_nr]; + } + } + break; + + case EL_SWITCHGATE_SWITCH_2: /* always start with same switch pos */ + if (init_game) + Feld[x][y] = EL_SWITCHGATE_SWITCH_1; + break; + + case EL_LIGHT_SWITCH_ON: + if (init_game) + game.light_time_left = 10 * FRAMES_PER_SECOND; + break; + default: break; } @@ -366,6 +453,7 @@ void InitGame() player->MovDir = MV_NO_MOVING; player->MovPos = 0; player->Pushing = FALSE; + player->Switching = FALSE; player->GfxPos = 0; player->Frame = 0; @@ -419,6 +507,13 @@ void InitGame() AllPlayersGone = FALSE; game.magic_wall_active = FALSE; game.magic_wall_time_left = 0; + game.switchgate_pos = 0; + game.light_time_left = 0; + 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; iscore; position = k; break; } #ifdef ONE_PER_NAME - else if (!strncmp(setup.player_name, highscore[k].Name, MAX_NAMELEN - 1)) + else if (!strncmp(setup.player_name, highscore[k].Name, + MAX_PLAYER_NAME_LEN)) break; /* player already there with a higher score */ #endif @@ -1113,13 +1214,22 @@ void Explode(int ex, int ey, int phase, int mode) if (IS_MOVING(ex, ey) || IS_BLOCKED(ex, ey)) { + /* put moving element to center field (and let it explode there) */ center_element = MovingOrBlocked2Element(ex, ey); RemoveMovingField(ex, ey); + Feld[ex][ey] = center_element; } - for (y=ey-1; y0 && IS_FREE(x-1, y) && (IS_FREE(x-1, y+1) || Feld[x-1][y+1] == EL_SALZSAEURE)); @@ -2122,6 +2239,17 @@ void StartMoving(int x, int y) InitMovingField(x, y, left ? MV_LEFT : MV_RIGHT); } } + else if (IS_BELT(Feld[x][y+1])) + { + boolean left_is_free = (x>0 && IS_FREE(x-1, y)); + boolean right_is_free = (x0) - JustHit[x][y]--; + if (JustStopped[x][y] > 0) + JustStopped[x][y]--; #if DEBUG if (IS_BLOCKED(x, y)) @@ -3630,6 +3827,12 @@ void GameActions() DrawGraphicAnimation(x, y, GFX2_SP_TERMINAL, 7, 12, ANIM_NORMAL); else if (element == EL_SP_TERMINAL_ACTIVE) DrawGraphicAnimation(x, y, GFX2_SP_TERMINAL_ACTIVE, 7, 4, ANIM_NORMAL); + else if (IS_BELT(element)) + DrawBeltAnimation(x, y, element); + else if (element == EL_SWITCHGATE_OPENING) + OpenSwitchgate(x, y); + else if (element == EL_SWITCHGATE_CLOSING) + CloseSwitchgate(x, y); if (game.magic_wall_active) { @@ -3671,6 +3874,7 @@ void GameActions() for (y=0; y 0) + { + game.light_time_left--; + + if (game.light_time_left == 0) + { + for (y=0; y= (1000 / GameFrameDelay) && !tape.pausing) { TimeFrames = 0; @@ -4344,6 +4571,7 @@ int DigField(struct PlayerInfo *player, if (mode == DF_NO_PUSH) { + player->Switching = FALSE; player->push_delay = 0; return MF_NO_ACTION; } @@ -4353,13 +4581,14 @@ int DigField(struct PlayerInfo *player, element = Feld[x][y]; - switch(element) + switch (element) { case EL_LEERRAUM: PlaySoundLevel(x, y, SND_EMPTY); break; case EL_ERDREICH: + case EL_SAND_INVISIBLE: Feld[x][y] = EL_LEERRAUM; PlaySoundLevel(x, y, SND_SCHLURF); break; @@ -4397,6 +4626,11 @@ int DigField(struct PlayerInfo *player, PlaySoundLevel(x, y, SND_PONG); break; + case EL_ENVELOPE: + Feld[x][y] = EL_LEERRAUM; + PlaySoundLevel(x, y, SND_PONG); + break; + case EL_DYNAMITE_INACTIVE: case EL_SP_DISK_RED: RemoveField(x, y); @@ -4500,6 +4734,166 @@ int DigField(struct PlayerInfo *player, } break; + case EL_BELT1_SWITCH_L: + case EL_BELT1_SWITCH_M: + case EL_BELT1_SWITCH_R: + case EL_BELT2_SWITCH_L: + case EL_BELT2_SWITCH_M: + case EL_BELT2_SWITCH_R: + case EL_BELT3_SWITCH_L: + case EL_BELT3_SWITCH_M: + case EL_BELT3_SWITCH_R: + case EL_BELT4_SWITCH_L: + case EL_BELT4_SWITCH_M: + case EL_BELT4_SWITCH_R: + { + static int belt_base_element[4] = + { + EL_BELT1_SWITCH_L, + EL_BELT2_SWITCH_L, + EL_BELT3_SWITCH_L, + EL_BELT4_SWITCH_L + }; + static int belt_move_dir[4] = + { + MV_LEFT, + MV_NO_MOVING, + MV_RIGHT, + MV_NO_MOVING, + }; + + int belt_nr = getBeltNrFromSwitchElement(element); + int belt_dir_nr = (game.belt_dir_nr[belt_nr] + 1) % 4; + int belt_dir = belt_move_dir[belt_dir_nr]; + int xx, yy; + + if (player->Switching) + return MF_ACTION; + + player->Switching = TRUE; + + game.belt_dir_nr[belt_nr] = belt_dir_nr; + game.belt_dir[belt_nr] = belt_dir; + + if (belt_dir_nr == 3) + belt_dir_nr = 1; + + for (yy=0; yySwitching) + return MF_ACTION; + + player->Switching = TRUE; + + game.switchgate_pos = !game.switchgate_pos; + + for (yy=0; yySwitching) + return MF_ACTION; + + player->Switching = TRUE; + + game.light_time_left = + (element == EL_LIGHT_SWITCH_OFF ? 10 * FRAMES_PER_SECOND : 0); + + for (yy=0; yy 0) + { + Feld[xx][yy] = EL_LIGHT_SWITCH_ON; + DrawLevelField(xx, yy); + } + else if (element == EL_LIGHT_SWITCH_ON && + game.light_time_left == 0) + { + Feld[xx][yy] = EL_LIGHT_SWITCH_OFF; + DrawLevelField(xx, yy); + } + + if (element == EL_INVISIBLE_STEEL || + element == EL_UNSICHTBAR || + element == EL_SAND_INVISIBLE) + DrawLevelField(xx, yy); + } + } + + return MF_ACTION; + } + break; + case EL_SP_EXIT: if (local_player->gems_still_needed > 0) return MF_NO_ACTION; @@ -4579,6 +4973,8 @@ int DigField(struct PlayerInfo *player, player->programmed_action = move_direction; DOUBLE_PLAYER_SPEED(player); + PlaySoundLevel(x, y, SND_GATE); + break; case EL_EM_GATE_1X: @@ -4594,6 +4990,20 @@ int DigField(struct PlayerInfo *player, player->programmed_action = move_direction; DOUBLE_PLAYER_SPEED(player); + PlaySoundLevel(x, y, SND_GATE); + + break; + + case EL_SWITCHGATE_OPEN: + if (!IN_LEV_FIELD(x + dx, y + dy) || !IS_FREE(x + dx, y + dy)) + return MF_NO_ACTION; + + /* automatically move to the next field with double speed */ + player->programmed_action = move_direction; + DOUBLE_PLAYER_SPEED(player); + + PlaySoundLevel(x, y, SND_GATE); + break; case EL_SP_PORT1_LEFT: @@ -4635,6 +5045,8 @@ int DigField(struct PlayerInfo *player, player->programmed_action = move_direction; DOUBLE_PLAYER_SPEED(player); + PlaySoundLevel(x, y, SND_GATE); + break; case EL_AUSGANG_ZU: