2 * Copyright (C) 2003 Robert Kooima
4 * NEVERBALL is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published
6 * by the Free Software Foundation; either version 2 of the License,
7 * or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
28 /*---------------------------------------------------------------------------*/
30 static void scan_dict(struct level *l, const struct s_file *fp)
34 for (i = 0; i < fp->dc; i++)
36 char *k = fp->av + fp->dv[i].ai;
37 char *v = fp->av + fp->dv[i].aj;
39 if (strcmp(k, "message") == 0)
40 strncpy(l->message, v, MAXSTR);
41 else if (strcmp(k, "back") == 0)
42 strncpy(l->back, v, PATHMAX);
43 else if (strcmp(k, "song") == 0)
44 strncpy(l->song, v, PATHMAX);
45 else if (strcmp(k, "grad") == 0)
46 strncpy(l->grad, v, PATHMAX);
47 else if (strcmp(k, "shot") == 0)
48 strncpy(l->shot, v, PATHMAX);
49 else if (strcmp(k, "goal") == 0)
52 l->score.most_coins.coins[2] = l->goal;
54 else if (strcmp(k, "time") == 0)
57 l->score.best_times.timer[2] = l->time;
58 l->score.unlock_goal.timer[2] = l->time;
60 else if (strcmp(k, "time_hs") == 0)
62 &l->score.best_times.timer[0],
63 &l->score.best_times.timer[1]);
64 else if (strcmp(k, "goal_hs") == 0)
66 &l->score.unlock_goal.timer[0],
67 &l->score.unlock_goal.timer[1]);
68 else if (strcmp(k, "coin_hs") == 0)
70 &l->score.most_coins.coins[0],
71 &l->score.most_coins.coins[1]);
72 else if (strcmp(k, "version") == 0)
73 strncpy(l->version, v, MAXSTR);
74 else if (strcmp(k, "author") == 0)
75 strncpy(l->author, v, MAXSTR);
76 else if (strcmp(k, "bonus") == 0)
77 l->is_bonus = atoi(v) ? 1 : 0;
81 int level_load(const char *filename, struct level *level)
88 memset(level, 0, sizeof (struct level));
89 memset(&sol, 0, sizeof (sol));
91 /* Try to load the sol file */
92 if (!sol_load_only_file(&sol, config_data(filename)))
95 _("Error while loading level file '%s': %s\n"), filename,
96 errno ? strerror(errno) : _("Not a valid level file"));
100 strcpy(level->file, filename);
102 /* Init hs with default values */
103 score_init_hs(&level->score.best_times, 59999, 0);
104 score_init_hs(&level->score.unlock_goal, 59999, 0);
105 score_init_hs(&level->score.most_coins, 59999, 0);
107 /* Compute money and default max money */
109 for (i = 0; i < sol.hc; i++)
110 if (sol.hv[i].t == ITEM_COIN)
111 money += sol.hv[i].n;
112 level->score.most_coins.coins[0] = money;
115 scan_dict(level, &sol);
117 /* Compute initial hs default values */
121 t[0] = t[1] = t[2]; \
122 else if (t[2] c t[1]) \
123 t[1] = (t[0] + t[2]) / 2
125 HOP(level->score.best_times.timer, <=);
126 HOP(level->score.unlock_goal.timer, <=);
127 HOP(level->score.most_coins.coins, >=);
134 void level_dump(const struct level *l)
136 printf("filename: %s\n"
141 "time hs: %d %d %d\n"
142 "goal hs: %d %d %d\n"
143 "coin hs: %d %d %d\n"
154 l->score.best_times.timer[0],
155 l->score.best_times.timer[1],
156 l->score.best_times.timer[2],
157 l->score.unlock_goal.timer[0],
158 l->score.unlock_goal.timer[1],
159 l->score.unlock_goal.timer[2],
160 l->score.most_coins.coins[0],
161 l->score.most_coins.coins[1],
162 l->score.most_coins.coins[2],
170 /*---------------------------------------------------------------------------*/
172 int level_replay(const char *filename)
174 return demo_replay_init(filename, curr_lg());
177 int level_play(const struct level *l, int m)
179 struct level_game *lg = curr_lg();
181 memset(lg, 0, sizeof (struct level_game));
187 lg->goal = (lg->mode == MODE_PRACTICE) ? 0 : lg->level->goal;
188 lg->time = (lg->mode == MODE_PRACTICE) ? 0 : lg->level->time;
190 /* Clear other fields. */
192 lg->status = GAME_NONE;
194 lg->timer = lg->time;
195 lg->coin_rank = lg->goal_rank = lg->time_rank =
196 lg->score_rank = lg->times_rank = 3;
198 lg->win = lg->dead = lg->unlock = 0;
199 lg->next_level = NULL;
201 return demo_play_init(USER_REPLAY_FILE, lg->level, lg);
204 void level_stat(int status, int clock, int coins)
206 struct level_game *lg = curr_lg();
209 int timer = (mode == MODE_PRACTICE) ? clock : lg->time - clock;
213 config_get_s(CONFIG_PLAYER, player, MAXNAM);
219 if (mode == MODE_CHALLENGE)
224 /* sum coins an earn extra balls */
225 if (status == GAME_GOAL || lg->level->is_bonus)
227 lg->balls += count_extra_balls(lg->score, coins);
231 /* lose ball and game */
234 lg->dead = (lg->balls <= 0);
239 set_finish_level(lg, player);
244 void level_stop(void)
251 struct level_game *lg = curr_lg();
254 lg->level = lg->next_level;
255 return level_play(lg->level, lg->mode);
261 return level_play(curr_lg()->level, curr_lg()->mode);
264 /*---------------------------------------------------------------------------*/
266 int count_extra_balls(int old_score, int coins)
268 return ((old_score % 100) + coins) / 100;
271 void level_update_player_name(void)
275 config_get_s(CONFIG_PLAYER, player, MAXNAM);
277 score_change_name(curr_lg(), player);
280 /*---------------------------------------------------------------------------*/
282 const char *status_to_str(int m)
286 case GAME_NONE: return _("Aborted");
287 case GAME_TIME: return _("Time-out");
288 case GAME_GOAL: return _("Success");
289 case GAME_FALL: return _("Fall-out");
290 default: return _("Unknown");
294 /*---------------------------------------------------------------------------*/