locales: updated fr translation
[neverball] / ball / level.c
index 7ecb296..d6cd0a0 100644 (file)
 #include <string.h>
 #include <math.h>
 #include <errno.h>
+#include <assert.h>
 
+#include "solid.h"
 #include "config.h"
-#include "demo.h"
-#include "text.h"
 #include "level.h"
-#include "mode.h"
 #include "set.h"
-#include "solid.h"
 
 /*---------------------------------------------------------------------------*/
 
-static void scan_dict(struct level *l, const struct s_file *fp)
+static void scan_level_attribs(struct level *l, const struct s_file *fp)
 {
     int i;
 
+    int have_goal = 0, have_time = 0;
+    int need_bt_easy = 0, need_ug_easy = 0, need_mc_easy = 0;
+
     for (i = 0; i < fp->dc; i++)
     {
         char *k = fp->av + fp->dv[i].ai;
@@ -39,37 +40,65 @@ static void scan_dict(struct level *l, const struct s_file *fp)
 
         if (strcmp(k, "message") == 0)
             strncpy(l->message, v, MAXSTR);
-        else if (strcmp(k, "back") == 0)
-            strncpy(l->back, v, PATHMAX);
         else if (strcmp(k, "song") == 0)
             strncpy(l->song, v, PATHMAX);
-        else if (strcmp(k, "grad") == 0)
-            strncpy(l->grad, v, PATHMAX);
         else if (strcmp(k, "shot") == 0)
             strncpy(l->shot, v, PATHMAX);
         else if (strcmp(k, "goal") == 0)
         {
             l->goal = atoi(v);
-            l->score.most_coins.coins[2] = l->goal;
+            have_goal = 1;
         }
         else if (strcmp(k, "time") == 0)
         {
             l->time = atoi(v);
-            l->score.best_times.timer[2] = l->time;
-            l->score.unlock_goal.timer[2] = l->time;
+            have_time = 1;
         }
         else if (strcmp(k, "time_hs") == 0)
-            sscanf(v, "%d %d",
-                   &l->score.best_times.timer[0],
-                   &l->score.best_times.timer[1]);
+        {
+            switch (sscanf(v, "%d %d %d",
+                           &l->score.best_times.timer[0],
+                           &l->score.best_times.timer[1],
+                           &l->score.best_times.timer[2]))
+            {
+            case 2: need_bt_easy = 1; break;
+            case 3:                   break;
+
+            default:
+                /* TODO, complain loudly? */
+                break;
+            }
+        }
         else if (strcmp(k, "goal_hs") == 0)
-            sscanf(v, "%d %d",
-                   &l->score.unlock_goal.timer[0],
-                   &l->score.unlock_goal.timer[1]);
+        {
+            switch (sscanf(v, "%d %d %d",
+                           &l->score.unlock_goal.timer[0],
+                           &l->score.unlock_goal.timer[1],
+                           &l->score.unlock_goal.timer[2]))
+            {
+            case 2: need_ug_easy = 1; break;
+            case 3:                   break;
+
+            default:
+                /* TODO, complain loudly? */
+                break;
+            }
+        }
         else if (strcmp(k, "coin_hs") == 0)
-            sscanf(v, "%d %d",
-                   &l->score.most_coins.coins[0],
-                   &l->score.most_coins.coins[1]);
+        {
+            switch (sscanf(v, "%d %d %d",
+                           &l->score.most_coins.coins[0],
+                           &l->score.most_coins.coins[1],
+                           &l->score.most_coins.coins[2]))
+            {
+            case 2: need_mc_easy = 1; break;
+            case 3:                   break;
+
+            default:
+                /* TODO, complain loudly? */
+                break;
+            }
+        }
         else if (strcmp(k, "version") == 0)
             strncpy(l->version, v, MAXSTR);
         else if (strcmp(k, "author") == 0)
@@ -77,6 +106,17 @@ static void scan_dict(struct level *l, const struct s_file *fp)
         else if (strcmp(k, "bonus") == 0)
             l->is_bonus = atoi(v) ? 1 : 0;
     }
+
+    if (have_goal && need_mc_easy)
+        l->score.most_coins.coins[2] = l->goal;
+
+    if (have_time)
+    {
+        if (need_bt_easy)
+            l->score.best_times.timer[2] = l->time;
+        if (need_ug_easy)
+            l->score.unlock_goal.timer[2] = l->time;
+    }
 }
 
 int level_load(const char *filename, struct level *level)
@@ -118,8 +158,7 @@ int level_load(const char *filename, struct level *level)
 
     level->score.most_coins.coins[0] = money;
 
-    if (sol.dc > 0)
-        scan_dict(level, &sol);
+    scan_level_attribs(level, &sol);
 
     /* Compute initial hs default values */
 
@@ -149,8 +188,6 @@ void level_dump(const struct level *l)
            "goal hs:         %d %d %d\n"
            "coin hs:         %d %d %d\n"
            "message:         %s\n"
-           "background:      %s\n"
-           "gradient:        %s\n"
            "screenshot:      %s\n"
            "song:            %s\n",
            l->file,
@@ -168,144 +205,125 @@ void level_dump(const struct level *l)
            l->score.most_coins.coins[1],
            l->score.most_coins.coins[2],
            l->message,
-           l->back,
-           l->grad,
            l->shot,
            l->song);
 }
 
 /*---------------------------------------------------------------------------*/
 
-static unsigned int do_level_init = 1;
-
-int level_replay(const char *filename)
+int  level_exists(int i)
 {
-    return demo_replay_init(filename, curr_lg());
+    return set_level_exists(curr_set(), i);
 }
 
-int level_play(const struct level *l, int m)
+void level_open(int i)
 {
-    struct level_game *lg = curr_lg();
-
-    if (do_level_init)
-    {
-        memset(lg, 0, sizeof (struct level_game));
-
-        lg->mode  = m;
-        lg->level = l;
-        lg->balls = 3;
-    }
-
-    lg->goal = (lg->mode == MODE_PRACTICE) ? 0 : lg->level->goal;
-    lg->time = (lg->mode == MODE_PRACTICE) ? 0 : lg->level->time;
-
-    /* Clear other fields. */
-
-    lg->status = GAME_NONE;
-    lg->coins = 0;
-    lg->timer = lg->time;
-    lg->coin_rank = lg->goal_rank = lg->time_rank =
-        lg->score_rank = lg->times_rank = 3;
-
-    lg->win = lg->dead = lg->unlock = 0;
-    lg->next_level = NULL;
-    lg->bonus = 0;
-
-    return demo_play_init(USER_REPLAY_FILE, lg->level, lg);
+    if (level_exists(i))
+        get_level(i)->is_locked = 0;
 }
 
-void level_stat(int status, int clock, int coins)
+int  level_opened(int i)
 {
-    struct level_game *lg = curr_lg();
-
-    int mode = lg->mode;
-    int timer = (mode == MODE_PRACTICE) ? clock : lg->time - clock;
-
-    char player[MAXNAM];
-
-    config_get_s(CONFIG_PLAYER, player, MAXNAM);
-
-    lg->status = status;
-    lg->coins = coins;
-    lg->timer = timer;
-
-    if (mode == MODE_CHALLENGE)
-    {
-        /* sum time */
-        lg->times += timer;
+    return level_exists(i) && !get_level(i)->is_locked;
+}
 
-        /* sum coins an earn extra balls */
-        if (status == GAME_GOAL || lg->level->is_bonus)
-        {
-            lg->balls += count_extra_balls(lg->score, coins);
-            lg->score += coins;
-        }
+void level_complete(int i)
+{
+    if (level_exists(i))
+        get_level(i)->is_completed = 1;
+}
 
-        /* lose ball and game */
-        else
-        {
-            lg->dead = (lg->balls <= 0);
-            lg->balls--;
-        }
-    }
+int  level_completed(int i)
+{
+    return level_exists(i) && get_level(i)->is_completed;
+}
 
-    set_finish_level(lg, player);
+int  level_time (int i)
+{
+    assert(level_exists(i));
+    return get_level(i)->time;
+}
 
-    demo_play_stat(lg);
+int  level_goal (int i)
+{
+    assert(level_exists(i));
+    return get_level(i)->goal;
 }
 
-void level_stop(void)
+int  level_bonus(int i)
 {
-    demo_play_stop();
-    do_level_init = 1;
+    return level_exists(i) && get_level(i)->is_bonus;
 }
 
-int level_next(void)
+const char *level_shot(int i)
 {
-    struct level_game *lg = curr_lg();
+    return level_exists(i) ? get_level(i)->shot : NULL;
+}
 
-    level_stop();
-    lg->level = lg->next_level;
-    do_level_init = 0;
+const char *level_file(int i)
+{
+    return level_exists(i) ? get_level(i)->file : NULL;
+}
 
-    return level_play(lg->level, lg->mode);
+const char *level_name(int i)
+{
+    return level_exists(i) ? get_level(i)->name : NULL;
 }
 
-int level_same(void)
+const char *level_msg(int i)
 {
-    level_stop();
-    do_level_init = 0;
-    return level_play(curr_lg()->level, curr_lg()->mode);
+    if (level_exists(i) && strlen(get_level(i)->message) > 0)
+        return _(get_level(i)->message);
+
+    return NULL;
 }
 
 /*---------------------------------------------------------------------------*/
 
-int count_extra_balls(int old_score, int coins)
+int level_score_update(int level,
+                       int timer,
+                       int coins,
+                       int *time_rank,
+                       int *goal_rank,
+                       int *coin_rank)
 {
-    return ((old_score % 100) + coins) / 100;
-}
+    struct level *l = get_level(level);
+    char player[MAXSTR] = "";
 
-void level_update_player_name(void)
-{
-    char player[MAXNAM];
+    config_get_s(CONFIG_PLAYER, player, MAXSTR);
 
-    config_get_s(CONFIG_PLAYER, player, MAXNAM);
+    if (time_rank)
+        *time_rank = score_time_insert(&l->score.best_times,
+                                       player, timer, coins);
 
-    score_change_name(curr_lg(), player);
-}
+    if (goal_rank)
+        *goal_rank = score_time_insert(&l->score.unlock_goal,
+                                       player, timer, coins);
 
-/*---------------------------------------------------------------------------*/
+    if (coin_rank)
+        *coin_rank = score_coin_insert(&l->score.most_coins,
+                                       player, timer, coins);
 
-const char *status_to_str(int m)
+    if ((time_rank && *time_rank < 3) ||
+        (goal_rank && *goal_rank < 3) ||
+        (coin_rank && *coin_rank < 3))
+        return 1;
+    else
+        return 0;
+}
+
+void level_rename_player(int level,
+                         int time_rank,
+                         int goal_rank,
+                         int coin_rank,
+                         const char *player)
 {
-    switch (m)
-    {
-    case GAME_NONE:    return _("Aborted");
-    case GAME_TIME:    return _("Time-out");
-    case GAME_GOAL:    return _("Success");
-    case GAME_FALL:    return _("Fall-out");
-    default:           return _("Unknown");
-    }
+    struct level *l = get_level(level);
+
+    strncpy(l->score.best_times.player [time_rank], player, MAXNAM);
+    strncpy(l->score.unlock_goal.player[goal_rank], player, MAXNAM);
+    strncpy(l->score.most_coins.player [coin_rank], player, MAXNAM);
 }
 
 /*---------------------------------------------------------------------------*/
+