#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;
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)
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)
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 */
"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,
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);
}
/*---------------------------------------------------------------------------*/
+