locales: Improved words-fr.png texture
[neverball] / ball / progress.c
index 875dbfa..3477e63 100644 (file)
 #include "lang.h"
 #include "score.h"
 
+#include <assert.h>
+
 /*---------------------------------------------------------------------------*/
 
+struct progress
+{
+    int balls;
+    int score;
+    int times;
+};
+
 static int mode = MODE_NORMAL;
 
 static int level =  0;
 static int next  = -1;
 static int done  =  0;
 
-static int balls =  2;
 static int bonus =  0;
 
-/* Set stats. */
+static struct progress curr;
+static struct progress prev;
 
-static int score = 0;
-static int times = 0;
+/* Set stats. */
 
 static int score_rank = 3;
 static int times_rank = 3;
@@ -50,6 +58,9 @@ static int timer = 0;
 static int goal   = 0; /* Current goal value. */
 static int goal_i = 0; /* Initial goal value. */
 
+static int goal_e      = 0; /* Goal enabled flag                */
+static int same_goal_e = 0; /* Reuse existing goal enabled flag */
+
 static int time_rank = 3;
 static int goal_rank = 3;
 static int coin_rank = 3;
@@ -59,12 +70,14 @@ static int coin_rank = 3;
 void progress_init(int m)
 {
     mode  = m;
-
-    balls = 2;
-    score = 0;
-    times = 0;
     bonus = 0;
 
+    curr.balls = 2;
+    curr.score = 0;
+    curr.times = 0;
+
+    prev = curr;
+
     score_rank = times_rank = 3;
 
     done  = 0;
@@ -82,13 +95,19 @@ int  progress_play(int i)
         timer  = 0;
         goal   = goal_i = level_goal(level);
 
+        if (same_goal_e)
+            same_goal_e = 0;
+        else
+            goal_e = (mode != MODE_CHALLENGE && level_completed(level) &&
+                      config_get_d(CONFIG_LOCK_GOALS) == 0) || goal == 0;
+
+        prev = curr;
+
         time_rank = goal_rank = coin_rank = 3;
 
         if (demo_play_init(USER_REPLAY_FILE, get_level(level), mode,
                            level_time(level), level_goal(level),
-                           (mode != MODE_CHALLENGE && level_completed(level) &&
-                            config_get_d(CONFIG_LOCK_GOALS) == 0) || goal == 0,
-                           score, balls, times))
+                           goal_e, curr.score, curr.balls, curr.times))
         {
             return 1;
         }
@@ -128,12 +147,12 @@ void progress_stat(int s)
     {
     case GAME_GOAL:
 
-        for (i = score + 1; i <= score + coins; i++)
+        for (i = curr.score + 1; i <= curr.score + coins; i++)
             if (progress_reward_ball(i))
-                balls++;
+                curr.balls++;
 
-        score += coins;
-        times += timer;
+        curr.score += coins;
+        curr.times += timer;
 
         dirty = level_score_update(level, timer, coins,
                                    &time_rank,
@@ -166,21 +185,15 @@ void progress_stat(int s)
                 /* Do nothing. */;
         }
 
-        /* Complete the set or open next level. */
+        /* Open next level or complete the set. */
 
-        if (!level_exists(next))
-        {
-            if (mode == MODE_CHALLENGE)
-            {
-                dirty = set_score_update(times, score, &score_rank, &times_rank);
-                done  = 1;
-            }
-        }
-        else
+        if (level_exists(next))
         {
             level_open(next);
             dirty = 1;
         }
+        else
+            done = mode == MODE_CHALLENGE;
 
         break;
 
@@ -193,7 +206,9 @@ void progress_stat(int s)
              next++)
             /* Do nothing. */;
 
-        balls--;
+        curr.times += timer;
+        curr.balls -= 1;
+
         break;
     }
 
@@ -208,15 +223,20 @@ void progress_stop(void)
     demo_play_stop();
 }
 
-void progress_exit(int s)
+void progress_exit(void)
 {
-    progress_stat(s);
-    progress_stop();
+    assert(done);
+
+    if (set_score_update(curr.times, curr.score, &score_rank, &times_rank))
+        set_store_hs();
 }
 
 int  progress_replay(const char *filename)
 {
-    if (demo_replay_init(filename, &goal, &mode, &balls, &score, &times))
+    if (demo_replay_init(filename, &goal, &mode,
+                         &curr.balls,
+                         &curr.score,
+                         &curr.times))
     {
         goal_i = goal;
         return 1;
@@ -242,7 +262,7 @@ int  progress_same_avail(void)
 
     default:
         if (mode == MODE_CHALLENGE)
-            return status != GAME_GOAL && !progress_dead();
+            return !progress_dead();
         else
             return 1;
     }
@@ -257,12 +277,21 @@ int  progress_next(void)
 int  progress_same(void)
 {
     progress_stop();
+
+    /* Reset progress and goal enabled state. */
+
+    if (status == GAME_GOAL)
+    {
+        curr = prev;
+        same_goal_e = 1;
+    }
+
     return progress_play(level);
 }
 
 int  progress_dead(void)
 {
-    return mode == MODE_CHALLENGE ? balls < 0 : 0;
+    return mode == MODE_CHALLENGE ? curr.balls < 0 : 0;
 }
 
 int  progress_done(void)
@@ -280,14 +309,25 @@ int  progress_set_high(void)
     return score_rank < 3 || times_rank < 3;
 }
 
-void progress_rename(void)
+void progress_rename(int set_only)
 {
     char player[MAXNAM] = "";
 
     config_get_s(CONFIG_PLAYER, player, sizeof (player));
 
-    level_rename_player(level, time_rank, goal_rank, coin_rank, player);
-    set_rename_player  (score_rank, times_rank, player);
+    if (set_only)
+    {
+        set_rename_player(score_rank, times_rank, player);
+    }
+    else
+    {
+        level_rename_player(level, time_rank, goal_rank, coin_rank, player);
+
+        demo_rename_player(USER_REPLAY_FILE, player);
+
+        if (progress_done())
+            set_rename_player(score_rank, times_rank, player);
+    }
 
     set_store_hs();
 }
@@ -299,12 +339,12 @@ int  progress_reward_ball(int s)
 
 /*---------------------------------------------------------------------------*/
 
-int curr_level(void) { return level; }
-int curr_balls(void) { return balls; }
-int curr_score(void) { return score; }
-int curr_mode (void) { return mode;  }
-int curr_bonus(void) { return bonus; }
-int curr_goal (void) { return goal;  }
+int curr_level(void) { return level;      }
+int curr_balls(void) { return curr.balls; }
+int curr_score(void) { return curr.score; }
+int curr_mode (void) { return mode;       }
+int curr_bonus(void) { return bonus;      }
+int curr_goal (void) { return goal;       }
 
 int progress_time_rank(void) { return time_rank; }
 int progress_goal_rank(void) { return goal_rank; }