#include <math.h>
#include <errno.h>
+#include "config.h"
+#include "demo.h"
+#include "text.h"
#include "level.h"
+#include "mode.h"
+#include "set.h"
#include "solid.h"
/*---------------------------------------------------------------------------*/
-static void level_scan_metadata(struct level *l, const struct s_file *fp)
+static void scan_dict(struct level *l, const struct s_file *fp)
{
int i;
else if (strcmp(k, "author") == 0)
strncpy(l->author, v, MAXSTR);
else if (strcmp(k, "bonus") == 0)
- l->is_bonus = atoi(v);
+ l->is_bonus = atoi(v) ? 1 : 0;
}
}
-/* Load the sol file 'filename' and fill the 'level' structure. Return 1 on
- * success, 0 on error. */
-
int level_load(const char *filename, struct level *level)
{
struct s_file sol;
memset(level, 0, sizeof (struct level));
memset(&sol, 0, sizeof (sol));
- /* Try to load the sol file */
- if (!sol_load_only_file(&sol, config_data(filename)))
+#define format \
+ L_("Error while loading level file '%s': %s\n")
+#define default_error \
+ L_("Not a valid level file")
+
+ if (!sol_load_only_head(&sol, config_data(filename)))
{
- fprintf(stderr,
- _("Error while loading level file '%s': %s\n"), filename,
- errno ? strerror(errno) : _("Not a valid level file"));
+ const char *error = errno ? strerror(errno) : default_error;
+ fprintf(stderr, format, filename, error);
return 0;
}
+#undef format
+#undef default_error
+
strcpy(level->file, filename);
/* Init hs with default values */
money += sol.hv[i].n;
level->score.most_coins.coins[0] = money;
- /* Scan sol metadata */
if (sol.dc > 0)
- level_scan_metadata(level, &sol);
+ scan_dict(level, &sol);
/* Compute initial hs default values */
return 1;
}
-/*---------------------------------------------------------------------------*/
-
-void level_dump_info(const struct level *l)
+void level_dump(const struct level *l)
{
printf("filename: %s\n"
"version: %s\n"
/*---------------------------------------------------------------------------*/
-const char *state_to_str(int m)
+static unsigned int do_level_init = 1;
+
+int level_replay(const char *filename)
+{
+ return demo_replay_init(filename, curr_lg());
+}
+
+int level_play(const struct level *l, int m)
+{
+ 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;
+
+ return demo_play_init(USER_REPLAY_FILE, lg->level, lg);
+}
+
+void level_stat(int status, int clock, int coins)
+{
+ 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;
+
+ /* 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;
+ }
+
+ /* lose ball and game */
+ else
+ {
+ lg->dead = (lg->balls <= 0);
+ lg->balls--;
+ }
+ }
+
+ set_finish_level(lg, player);
+
+ demo_play_stat(lg);
+}
+
+void level_stop(void)
+{
+ demo_play_stop();
+ do_level_init = 1;
+}
+
+int level_next(void)
+{
+ struct level_game *lg = curr_lg();
+
+ level_stop();
+ lg->level = lg->next_level;
+ do_level_init = 0;
+
+ return level_play(lg->level, lg->mode);
+}
+
+int level_same(void)
+{
+ level_stop();
+ do_level_init = 0;
+ return level_play(curr_lg()->level, curr_lg()->mode);
+}
+
+/*---------------------------------------------------------------------------*/
+
+int count_extra_balls(int old_score, int coins)
+{
+ return ((old_score % 100) + coins) / 100;
+}
+
+void level_update_player_name(void)
+{
+ char player[MAXNAM];
+
+ config_get_s(CONFIG_PLAYER, player, MAXNAM);
+
+ score_change_name(curr_lg(), player);
+}
+
+/*---------------------------------------------------------------------------*/
+
+const char *status_to_str(int m)
{
switch (m)
{
case GAME_NONE: return _("Aborted");
case GAME_TIME: return _("Time-out");
- case GAME_SPEC:
case GAME_GOAL: return _("Success");
case GAME_FALL: return _("Fall-out");
default: return _("Unknown");