rnd-20030218-3-src
[rocksndiamonds.git] / src / game.c
index ce26a3b853d51fc72f42b0108e6f65df741bc45c..b36eda0dc9c922e1a03be0f1b53a6a45be979cd3 100644 (file)
 #define NUM_GAME_BUTTONS               6
 
 /* forward declaration for internal use */
+#if 0
 static void ResetGfxAnimation(int, int);
+#endif
 
 static void InitBeltMovement(void);
 static void CloseAllOpenTimegates(void);
@@ -469,16 +471,16 @@ void DrawGameDoorValues()
     for (j=0; j<4; j++)
       if (stored_player[i].key[j])
        DrawMiniGraphicExt(drawto, DX_KEYS + j * MINI_TILEX, DY_KEYS,
-                          IMG_KEY1 + j);
+                          el2edimg(EL_KEY1 + j));
 
   DrawText(DX + XX_EMERALDS, DY + YY_EMERALDS,
-          int2str(local_player->gems_still_needed, 3), FS_SMALL, FC_YELLOW);
+          int2str(local_player->gems_still_needed, 3), FONT_DEFAULT_SMALL);
   DrawText(DX + XX_DYNAMITE, DY + YY_DYNAMITE,
-          int2str(local_player->dynamite, 3), FS_SMALL, FC_YELLOW);
+          int2str(local_player->dynamite, 3), FONT_DEFAULT_SMALL);
   DrawText(DX + XX_SCORE, DY + YY_SCORE,
-          int2str(local_player->score, 5), FS_SMALL, FC_YELLOW);
+          int2str(local_player->score, 5), FONT_DEFAULT_SMALL);
   DrawText(DX + XX_TIME, DY + YY_TIME,
-          int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+          int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
 }
 
 
@@ -900,14 +902,15 @@ void InitGame()
 
   if (level_nr < 100)
     DrawText(DX + XX_LEVEL, DY + YY_LEVEL,
-            int2str(level_nr, 2), FS_SMALL, FC_YELLOW);
+            int2str(level_nr, 2), FONT_DEFAULT_SMALL);
   else
   {
     DrawTextExt(drawto, DX + XX_EMERALDS, DY + YY_EMERALDS,
-               int2str(level_nr, 3), FS_SMALL, FC_SPECIAL3, FONT_OPAQUE);
+               int2str(level_nr, 3), FONT_SPECIAL_NARROW, FONT_OPAQUE);
     BlitBitmap(drawto, drawto,
               DX + XX_EMERALDS, DY + YY_EMERALDS + 1,
-              FONT5_XSIZE * 3, FONT5_YSIZE - 1,
+              getFontWidth(FONT_SPECIAL_NARROW) * 3,
+              getFontHeight(FONT_SPECIAL_NARROW) - 1,
               DX + XX_LEVEL - 1, DY + YY_LEVEL + 1);
   }
 
@@ -1101,7 +1104,7 @@ void GameWon()
        TimeLeft -= 10;
       else
        TimeLeft--;
-      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
       BackToFront();
 
       if (!tape.playing)
@@ -1127,7 +1130,7 @@ void GameWon()
        TimePlayed += 10;
       else
        TimePlayed++;
-      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FS_SMALL, FC_YELLOW);
+      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FONT_DEFAULT_SMALL);
       BackToFront();
 
       if (!tape.playing)
@@ -1254,18 +1257,22 @@ int NewHiScore()
 
 static void ResetRandomAnimationValue(int x, int y)
 {
+  GfxRandom[x][y] = INIT_GFX_RANDOM();
+}
+
+static void ResetGfxAnimation(int x, int y)
+{
+#if 0
+#if 1
   int element = Feld[x][y];
   int graphic = el2img(element);
 
-  /* reset random value not until one full delay cycle has reached */
+  /* reset random value not until one full delay cycle was reached */
   if (ANIM_MODE(graphic) == ANIM_RANDOM &&
       GfxFrame[x][y] > ANIM_DELAY(graphic))
-    GfxRandom[x][y] = INIT_GFX_RANDOM();
-}
-
-static void ResetGfxAnimation(int x, int y)
-{
-  ResetRandomAnimationValue(x, y);
+#endif
+    ResetRandomAnimationValue(x, y);
+#endif
 
   GfxFrame[x][y] = 0;
   GfxAction[x][y] = ACTION_DEFAULT;
@@ -1506,7 +1513,7 @@ void Explode(int ex, int ey, int phase, int mode)
        RemoveMovingField(x, y);
       }
 
-      if (IS_MASSIVE(element) || element == EL_FLAMES)
+      if (IS_INDESTRUCTIBLE(element) || element == EL_FLAMES)
        continue;
 
       if (IS_PLAYER(x, y) && SHIELD_ON(PLAYERINFO(x, y)))
@@ -1708,7 +1715,7 @@ void DynaExplode(int ex, int ey)
       int y = ey + j * xy[i % 4][1];
       int element;
 
-      if (!IN_LEV_FIELD(x, y) || IS_MASSIVE(Feld[x][y]))
+      if (!IN_LEV_FIELD(x, y) || IS_INDESTRUCTIBLE(Feld[x][y]))
        break;
 
       element = Feld[x][y];
@@ -2189,6 +2196,8 @@ void Impact(int x, int y)
     {
       Feld[x][y] = EL_AMOEBA_CREATING;
       Store[x][y] = EL_AMOEBA_WET;
+
+      ResetRandomAnimationValue(x, y);
     }
     return;
   }
@@ -2319,6 +2328,13 @@ void Impact(int x, int y)
     return;
   }
 
+#if 0
+  printf("::: -> %d,%d [%d]\n", element, ACTION_IMPACT,
+        element_info[element].sound[ACTION_IMPACT]);
+
+  PlaySound(177);
+#endif
+
   /* play sound of object that hits the ground */
   if (lastline || object_hit)
     PlaySoundLevelElementAction(x, y, element, ACTION_IMPACT);
@@ -2892,7 +2908,11 @@ void StartMoving(int x, int y)
         EL_BD_MAGIC_WALL_FILLING);
       Store[x][y] = element;
     }
+#if 0
     else if (CAN_SMASH(element) && Feld[x][y+1] == EL_ACID)
+#else
+    else if (CAN_FALL(element) && Feld[x][y+1] == EL_ACID)
+#endif
     {
       SplashAcid(x, y);
 
@@ -4380,6 +4400,7 @@ static void ChangeElement(int x, int y)
     MovDelay[x][y] = changing_element[element].change_delay + 1;
 
     ResetGfxAnimation(x, y);
+    ResetRandomAnimationValue(x, y);
 
     if (changing_element[element].pre_change_function)
       changing_element[element].pre_change_function(x, y);
@@ -4400,6 +4421,7 @@ static void ChangeElement(int x, int y)
     Feld[x][y] = changing_element[element].next_element;
 
     ResetGfxAnimation(x, y);
+    ResetRandomAnimationValue(x, y);
 
     DrawLevelField(x, y);
 
@@ -4697,7 +4719,7 @@ void GameActions()
 #endif
 
     if (ANIM_MODE(graphic) == ANIM_RANDOM &&
-       IS_NEW_FRAME(GfxFrame[x][y], graphic))
+       IS_NEXT_FRAME(GfxFrame[x][y], graphic))
       ResetRandomAnimationValue(x, y);
 
     SetRandomAnimationValue(x, y);
@@ -4828,7 +4850,6 @@ void GameActions()
 
     if (game.magic_wall_active)
     {
-      boolean sieb = FALSE;
       int jx = local_player->jx, jy = local_player->jy;
 
       /* play the element sound at the position nearest to the player */
@@ -5004,14 +5025,14 @@ void GameActions()
       if (TimeLeft <= 10 && setup.time_limit)
        PlaySoundStereo(SND_GAME_RUNNING_OUT_OF_TIME, SOUND_MAX_RIGHT);
 
-      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
 
       if (!TimeLeft && setup.time_limit)
        for (i=0; i<MAX_PLAYERS; i++)
          KillHero(&stored_player[i]);
     }
     else if (level.time == 0 && !AllPlayersGone) /* level without time limit */
-      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FS_SMALL, FC_YELLOW);
+      DrawText(DX_TIME, DY_TIME, int2str(TimePlayed, 3), FONT_DEFAULT_SMALL);
   }
 
   DrawAllPlayers();
@@ -5837,7 +5858,7 @@ int DigField(struct PlayerInfo *player,
       RaiseScoreElement(element);
       DrawText(DX_EMERALDS, DY_EMERALDS,
               int2str(local_player->gems_still_needed, 3),
-              FS_SMALL, FC_YELLOW);
+              FONT_DEFAULT_SMALL);
       PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
       break;
 
@@ -5857,7 +5878,7 @@ int DigField(struct PlayerInfo *player,
       if (level.time > 0)
       {
        TimeLeft += 10;
-       DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+       DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
       }
       PlaySoundStereo(SND_EXTRA_TIME_COLLECTING, SOUND_MAX_RIGHT);
       break;
@@ -5881,8 +5902,7 @@ int DigField(struct PlayerInfo *player,
       player->dynamite++;
       RaiseScoreElement(EL_DYNAMITE);
       DrawText(DX_DYNAMITE, DY_DYNAMITE,
-              int2str(local_player->dynamite, 3),
-              FS_SMALL, FC_YELLOW);
+              int2str(local_player->dynamite, 3), FONT_DEFAULT_SMALL);
       PlaySoundLevelElementAction(x, y, element, ACTION_COLLECTING);
       break;
 
@@ -5914,14 +5934,15 @@ int DigField(struct PlayerInfo *player,
     case EL_KEY4:
     {
       int key_nr = element - EL_KEY1;
+      int graphic = el2edimg(element);
 
       RemoveField(x, y);
       player->key[key_nr] = TRUE;
       RaiseScoreElement(element);
       DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
-                        IMG_KEY1 + key_nr);
+                        graphic);
       DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
-                        IMG_KEY1 + key_nr);
+                        graphic);
       PlaySoundLevel(x, y, SND_KEY_COLLECTING);
       break;
     }
@@ -5932,14 +5953,15 @@ int DigField(struct PlayerInfo *player,
     case EL_EM_KEY4:
     {
       int key_nr = element - EL_EM_KEY1;
+      int graphic = el2edimg(EL_KEY1 + key_nr);
 
       RemoveField(x, y);
       player->key[key_nr] = TRUE;
       RaiseScoreElement(element);
       DrawMiniGraphicExt(drawto, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
-                        IMG_KEY1 + key_nr);
+                        graphic);
       DrawMiniGraphicExt(window, DX_KEYS + key_nr * MINI_TILEX, DY_KEYS,
-                        IMG_KEY1 + key_nr);
+                        graphic);
       PlaySoundLevel(x, y, SND_KEY_COLLECTING);
       break;
     }
@@ -6055,7 +6077,9 @@ int DigField(struct PlayerInfo *player,
     case EL_SPRING:
       if (mode == DF_SNAP)
        return MF_NO_ACTION;
+
       /* no "break" -- fall through to next case */
+
       /* the following elements can be pushed by "snapping" */
     case EL_BD_ROCK:
       if (dy)
@@ -6076,7 +6100,8 @@ int DigField(struct PlayerInfo *player,
        player->push_delay = FrameCounter;
 #if 0
       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
-         !tape.playing && element != EL_SPRING)
+         !tape.playing &&
+         element != EL_SPRING)
        return MF_NO_ACTION;
 #else
       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
@@ -6282,7 +6307,7 @@ int DigField(struct PlayerInfo *player,
     case EL_TIME_ORB_FULL:
       Feld[x][y] = EL_TIME_ORB_EMPTY;
       TimeLeft += 10;
-      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FS_SMALL, FC_YELLOW);
+      DrawText(DX_TIME, DY_TIME, int2str(TimeLeft, 3), FONT_DEFAULT_SMALL);
       DrawLevelField(x, y);
       PlaySoundStereo(SND_TIME_ORB_FULL_COLLECTING, SOUND_MAX_RIGHT);
       return MF_ACTION;
@@ -6387,6 +6412,48 @@ int DigField(struct PlayerInfo *player,
       break;
 
     default:
+      if (IS_PUSHABLE(element))
+      {
+       if (mode == DF_SNAP)
+         return MF_NO_ACTION;
+
+       if (CAN_FALL(element) && dy)
+         return MF_NO_ACTION;
+
+       player->Pushing = TRUE;
+
+       if (!IN_LEV_FIELD(x+dx, y+dy) || !IS_FREE(x+dx, y+dy))
+         return MF_NO_ACTION;
+
+       if (dx && real_dy)
+       {
+         if (IN_LEV_FIELD(jx, jy+real_dy) && !IS_SOLID(Feld[jx][jy+real_dy]))
+           return MF_NO_ACTION;
+       }
+       else if (dy && real_dx)
+       {
+         if (IN_LEV_FIELD(jx+real_dx, jy) && !IS_SOLID(Feld[jx+real_dx][jy]))
+           return MF_NO_ACTION;
+       }
+
+       if (player->push_delay == 0)
+         player->push_delay = FrameCounter;
+
+       if (!FrameReached(&player->push_delay, player->push_delay_value) &&
+           !(tape.playing && tape.file_version < FILE_VERSION_2_0))
+         return MF_NO_ACTION;
+
+       RemoveField(x, y);
+       Feld[x + dx][y + dy] = element;
+
+       player->push_delay_value = 2 + RND(8);
+
+       DrawLevelField(x + dx, y + dy);
+       PlaySoundLevelElementAction(x, y, element, ACTION_PUSHING);
+
+       break;
+      }
+
       return MF_NO_ACTION;
   }
 
@@ -6453,6 +6520,7 @@ boolean PlaceBomb(struct PlayerInfo *player)
   MovDelay[jx][jy] = 96;
 
   ResetGfxAnimation(jx, jy);
+  ResetRandomAnimationValue(jx, jy);
 
   if (player->dynamite)
   {
@@ -6460,7 +6528,7 @@ boolean PlaceBomb(struct PlayerInfo *player)
     player->dynamite--;
 
     DrawText(DX_DYNAMITE, DY_DYNAMITE, int2str(local_player->dynamite, 3),
-            FS_SMALL, FC_YELLOW);
+            FONT_DEFAULT_SMALL);
     if (IN_SCR_FIELD(SCREENX(jx), SCREENY(jy)))
     {
       if (game.emulation == EMU_SUPAPLEX)
@@ -6579,7 +6647,7 @@ void RaiseScore(int value)
 {
   local_player->score += value;
   DrawText(DX_SCORE, DY_SCORE, int2str(local_player->score, 5),
-          FS_SMALL, FC_YELLOW);
+          FONT_DEFAULT_SMALL);
 }
 
 void RaiseScoreElement(int element)