rnd-20050314-1-src
[rocksndiamonds.git] / src / game.c
index 31bc2f526da3b26d602cee4b88c07186ed93d26d..bd41a32415039cc7952246e04ff2f1f2341f60b1 100644 (file)
@@ -1062,11 +1062,12 @@ inline void DrawGameValue_Dynamite(int value)
   DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(value, 3), FONT_TEXT_2);
 }
 
-inline void DrawGameValue_Keys(int key[4])
+inline void DrawGameValue_Keys(int key[MAX_NUM_KEYS])
 {
   int i;
 
-  for (i = 0; i < MAX_KEYS; i++)
+  /* currently only 4 of 8 possible keys are displayed */
+  for (i = 0; i < STD_NUM_KEYS; i++)
     if (key[i])
       DrawMiniGraphicExt(drawto, DX_KEYS + i * MINI_TILEX, DY_KEYS,
                         el2edimg(EL_KEY_1 + i));
@@ -1112,12 +1113,14 @@ inline void DrawGameValue_Level(int value)
 void DrawAllGameValues(int emeralds, int dynamite, int score, int time,
                       int key_bits)
 {
-  int key[4];
+  int key[MAX_NUM_KEYS];
   int i;
 
-  for (i = 0; i < MAX_KEYS; i++)
+  for (i = 0; i < MAX_NUM_KEYS; i++)
     key[i] = key_bits & (1 << i);
 
+  DrawGameValue_Level(level_nr);
+
   DrawGameValue_Emeralds(emeralds);
   DrawGameValue_Dynamite(dynamite);
   DrawGameValue_Score(score);
@@ -1584,7 +1587,7 @@ void InitGame()
     player->lights_still_needed = 0;
     player->friends_still_needed = 0;
 
-    for (j = 0; j < MAX_KEYS; j++)
+    for (j = 0; j < MAX_NUM_KEYS; j++)
       player->key[j] = FALSE;
 
     player->dynabomb_count = 0;
@@ -2541,6 +2544,37 @@ int NewHiScore()
   return position;
 }
 
+inline static int getElementMoveStepsize(int x, int y)
+{
+  int element = Feld[x][y];
+  int direction = MovDir[x][y];
+  int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
+  int dy = (direction == MV_UP   ? -1 : direction == MV_DOWN  ? +1 : 0);
+  int horiz_move = (dx != 0);
+  int sign = (horiz_move ? dx : dy);
+  int step = sign * element_info[element].move_stepsize;
+
+  /* special values for move stepsize for spring and things on conveyor belt */
+  if (horiz_move)
+  {
+#if 0
+    if (element == EL_SPRING)
+      step = sign * MOVE_STEPSIZE_NORMAL * 2;
+    else if (CAN_FALL(element) && !CAN_MOVE(element) &&
+            y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
+      step = sign * MOVE_STEPSIZE_NORMAL / 2;
+#else
+    if (CAN_FALL(element) &&
+       y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
+      step = sign * MOVE_STEPSIZE_NORMAL / 2;
+    else if (element == EL_SPRING)
+      step = sign * MOVE_STEPSIZE_NORMAL * 2;
+#endif
+  }
+
+  return step;
+}
+
 void InitPlayerGfxAnimation(struct PlayerInfo *player, int action, int dir)
 {
   if (player->GfxAction != action || player->GfxDir != dir)
@@ -2580,6 +2614,27 @@ void InitMovingField(int x, int y, int direction)
   if (!WasJustMoving[x][y] || direction != MovDir[x][y])
     ResetGfxAnimation(x, y);
 
+#if 1
+
+  MovDir[x][y] = direction;
+  GfxDir[x][y] = direction;
+  GfxAction[x][y] = (direction == MV_DOWN && CAN_FALL(element) ?
+                    ACTION_FALLING : ACTION_MOVING);
+
+  if (getElementMoveStepsize(x, y) != 0)
+  {
+    if (Feld[newx][newy] == EL_EMPTY)
+      Feld[newx][newy] = EL_BLOCKED;
+
+    MovDir[newx][newy] = MovDir[x][y];
+    GfxFrame[newx][newy] = GfxFrame[x][y];
+    GfxRandom[newx][newy] = GfxRandom[x][y];
+    GfxAction[newx][newy] = GfxAction[x][y];
+    GfxDir[newx][newy] = GfxDir[x][y];
+  }
+
+#else
+
   MovDir[newx][newy] = MovDir[x][y] = direction;
   GfxDir[x][y] = direction;
 
@@ -2595,6 +2650,7 @@ void InitMovingField(int x, int y, int direction)
   GfxRandom[newx][newy] = GfxRandom[x][y];
   GfxAction[newx][newy] = GfxAction[x][y];
   GfxDir[newx][newy] = GfxDir[x][y];
+#endif
 }
 
 void Moving2Blocked(int x, int y, int *goes_to_x, int *goes_to_y)
@@ -4168,6 +4224,10 @@ static void RedrawAllLightSwitchesAndInvisibleElements()
          Feld[x][y] = getInvisibleActiveFromInvisibleElement(element);
 
        DrawLevelField(x, y);
+
+       /* uncrumble neighbour fields, if needed */
+       if (element == EL_INVISIBLE_SAND)
+         DrawLevelFieldCrumbledSandNeighbours(x, y);
       }
       else if (element == EL_INVISIBLE_STEELWALL_ACTIVE ||
               element == EL_INVISIBLE_WALL_ACTIVE ||
@@ -4177,6 +4237,10 @@ static void RedrawAllLightSwitchesAndInvisibleElements()
          Feld[x][y] = getInvisibleFromInvisibleActiveElement(element);
 
        DrawLevelField(x, y);
+
+       /* re-crumble neighbour fields, if needed */
+       if (element == EL_INVISIBLE_SAND)
+         DrawLevelFieldCrumbledSandNeighbours(x, y);
       }
     }
   }
@@ -4226,37 +4290,6 @@ static void ActivateTimegateSwitch(int x, int y)
   Feld[x][y] = EL_TIMEGATE_SWITCH_ACTIVE;
 }
 
-inline static int getElementMoveStepsize(int x, int y)
-{
-  int element = Feld[x][y];
-  int direction = MovDir[x][y];
-  int dx = (direction == MV_LEFT ? -1 : direction == MV_RIGHT ? +1 : 0);
-  int dy = (direction == MV_UP   ? -1 : direction == MV_DOWN  ? +1 : 0);
-  int horiz_move = (dx != 0);
-  int sign = (horiz_move ? dx : dy);
-  int step = sign * element_info[element].move_stepsize;
-
-  /* special values for move stepsize for spring and things on conveyor belt */
-  if (horiz_move)
-  {
-#if 0
-    if (element == EL_SPRING)
-      step = sign * MOVE_STEPSIZE_NORMAL * 2;
-    else if (CAN_FALL(element) && !CAN_MOVE(element) &&
-            y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
-      step = sign * MOVE_STEPSIZE_NORMAL / 2;
-#else
-    if (CAN_FALL(element) &&
-       y < lev_fieldy - 1 && IS_BELT_ACTIVE(Feld[x][y + 1]))
-      step = sign * MOVE_STEPSIZE_NORMAL / 2;
-    else if (element == EL_SPRING)
-      step = sign * MOVE_STEPSIZE_NORMAL * 2;
-#endif
-  }
-
-  return step;
-}
-
 void Impact(int x, int y)
 {
   boolean lastline = (y == lev_fieldy-1);
@@ -4995,6 +5028,11 @@ inline static void TurnRoundExt(int x, int y)
     boolean can_turn_right =
       CUSTOM_ELEMENT_CAN_ENTER_FIELD(element, right_x,right_y);
 
+#if 1
+    if (getElementMoveStepsize(x, y) == 0)
+      return;
+#endif
+
     if (move_pattern == MV_TURNING_LEFT)
       MovDir[x][y] = left_dir;
     else if (move_pattern == MV_TURNING_RIGHT)
@@ -5105,6 +5143,16 @@ inline static void TurnRoundExt(int x, int y)
       boolean first_horiz = RND(2);
       int new_move_dir = MovDir[x][y];
 
+#if 1
+      if (getElementMoveStepsize(x, y) == 0)
+      {
+       first_horiz = (ABS(attr_x - x) >= ABS(attr_y - y));
+       MovDir[x][y] &= (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
+
+       return;
+      }
+#endif
+
       MovDir[x][y] =
        new_move_dir & (first_horiz ? MV_HORIZONTAL : MV_VERTICAL);
       Moving2Blocked(x, y, &newx, &newy);
@@ -9694,7 +9742,7 @@ boolean MovePlayerOneStep(struct PlayerInfo *player,
 
   /* check if DigField() has caused relocation of the player */
   if (player->jx != jx || player->jy != jy)
-    return MF_NO_ACTION;
+    return MF_NO_ACTION;       /* <-- !!! CHECK THIS [-> MF_ACTION ?] !!! */
 
   StorePlayer[jx][jy] = 0;
   player->last_jx = jx;
@@ -11358,14 +11406,14 @@ int DigField(struct PlayerInfo *player,
          return MF_NO_ACTION;  /* player cannot walk here due to gravity */
 #endif
 
-       if (IS_GATE(element))
+       if (IS_RND_GATE(element))
        {
-         if (!player->key[element - EL_GATE_1])
+         if (!player->key[RND_GATE_NR(element)])
            return MF_NO_ACTION;
        }
-       else if (IS_GATE_GRAY(element))
+       else if (IS_RND_GATE_GRAY(element))
        {
-         if (!player->key[element - EL_GATE_1_GRAY])
+         if (!player->key[RND_GATE_GRAY_NR(element)])
            return MF_NO_ACTION;
        }
        else if (element == EL_EXIT_OPEN ||
@@ -11428,12 +11476,12 @@ int DigField(struct PlayerInfo *player,
 
        if (IS_EM_GATE(element))
        {
-         if (!player->key[element - EL_EM_GATE_1])
+         if (!player->key[EM_GATE_NR(element)])
            return MF_NO_ACTION;
        }
        else if (IS_EM_GATE_GRAY(element))
        {
-         if (!player->key[element - EL_EM_GATE_1_GRAY])
+         if (!player->key[EM_GATE_GRAY_NR(element)])
            return MF_NO_ACTION;
        }
        else if (IS_SP_PORT(element))
@@ -11544,13 +11592,9 @@ int DigField(struct PlayerInfo *player,
        {
          player->dynabomb_xl = TRUE;
        }
-       else if ((element >= EL_KEY_1 && element <= EL_KEY_4) ||
-                (element >= EL_EM_KEY_1 && element <= EL_EM_KEY_4))
+       else if (IS_KEY(element))
        {
-         int key_nr = (element >= EL_KEY_1 && element <= EL_KEY_4 ?
-                       element - EL_KEY_1 : element - EL_EM_KEY_1);
-
-         player->key[key_nr] = TRUE;
+         player->key[KEY_NR(element)] = TRUE;
 
          DrawGameValue_Keys(player->key);
 
@@ -12462,17 +12506,21 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample)
       break;
 
     case SAMPLE_bug:
-      PlayLevelSoundElementAction(x, y, EL_BUG, ACTION_MOVING);
+      PlayLevelSoundElementAction(x, y, element, ACTION_MOVING);
       break;
 
     case SAMPLE_tank:
-      PlayLevelSoundElementAction(x, y, EL_SPACESHIP, ACTION_MOVING);
+      PlayLevelSoundElementAction(x, y, element, ACTION_MOVING);
       break;
 
-    case SAMPLE_android:
+    case SAMPLE_android_clone:
       PlayLevelSoundElementAction(x, y, element, ACTION_DROPPING);
       break;
 
+    case SAMPLE_android_move:
+      PlayLevelSoundElementAction(x, y, element, ACTION_MOVING);
+      break;
+
     case SAMPLE_spring:
       PlayLevelSoundElementAction(x, y, element, ACTION_IMPACT);
       break;
@@ -12482,7 +12530,11 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample)
       break;
 
     case SAMPLE_eater:
-      PlayLevelSoundElementAction(x, y, EL_YAMYAM, ACTION_WAITING);
+      PlayLevelSoundElementAction(x, y, element, ACTION_WAITING);
+      break;
+
+    case SAMPLE_eater_eat:
+      PlayLevelSoundElementAction(x, y, element, ACTION_DIGGING);
       break;
 
     case SAMPLE_alien:
@@ -12498,11 +12550,16 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample)
       break;
 
     case SAMPLE_squash:
+      /* !!! CHECK THIS !!! */
+#if 1
+      PlayLevelSoundElementAction(x, y, element, ACTION_BREAKING);
+#else
       PlayLevelSoundElementAction(x, y, element, ACTION_SMASHED_BY_ROCK);
+#endif
       break;
 
     case SAMPLE_wonderfall:
-      PlayLevelSoundElementAction(x, y, EL_MAGIC_WALL, ACTION_FILLING);
+      PlayLevelSoundElementAction(x, y, element, ACTION_FILLING);
       break;
 
     case SAMPLE_drip:
@@ -12518,7 +12575,7 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample)
       break;
 
     case SAMPLE_acid:
-      PlayLevelSound(x, y, SND_ACID_SPLASHING);
+      PlayLevelSoundElementAction(x, y, element, ACTION_SPLASHING);
       break;
 
     case SAMPLE_ball:
@@ -12537,7 +12594,11 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample)
       PlayLevelSoundElementAction(x, y, element, ACTION_PASSING);
       break;
 
-    case SAMPLE_exit:
+    case SAMPLE_exit_open:
+      PlayLevelSoundElementAction(x, y, element, ACTION_OPENING);
+      break;
+
+    case SAMPLE_exit_leave:
       PlayLevelSoundElementAction(x, y, element, ACTION_PASSING);
       break;
 
@@ -12554,21 +12615,21 @@ void PlayLevelSound_EM(int x, int y, int element_em, int sample)
       break;
 
     case SAMPLE_wheel:
-      PlayLevelSound(x, y, SND_ROBOT_WHEEL_ACTIVE);
+      PlayLevelSoundElementAction(x, y, element, ACTION_ACTIVE);
       break;
 
     case SAMPLE_boom:
       PlayLevelSoundElementAction(x, y, element, ACTION_EXPLODING);
       break;
 
-    case SAMPLE_time:
-      PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE);
-      break;
-
     case SAMPLE_die:
       PlayLevelSoundElementAction(x, y, element, ACTION_DYING);
       break;
 
+    case SAMPLE_time:
+      PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MIDDLE);
+      break;
+
     default:
       PlayLevelSoundElementAction(x, y, element, ACTION_DEFAULT);
       break;
@@ -12644,6 +12705,14 @@ void RaiseScoreElement(int element)
     case EL_KEY_2:
     case EL_KEY_3:
     case EL_KEY_4:
+    case EL_EM_KEY_1:
+    case EL_EM_KEY_2:
+    case EL_EM_KEY_3:
+    case EL_EM_KEY_4:
+    case EL_EMC_KEY_5:
+    case EL_EMC_KEY_6:
+    case EL_EMC_KEY_7:
+    case EL_EMC_KEY_8:
       RaiseScore(level.score[SC_KEY]);
       break;
     default: