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.
27 /*---------------------------------------------------------------------------*/
29 static void scan_level_attribs(struct level *l, const struct s_file *fp)
33 int have_goal = 0, have_time = 0;
34 int need_bt_easy = 0, need_ug_easy = 0, need_mc_easy = 0;
36 for (i = 0; i < fp->dc; i++)
38 char *k = fp->av + fp->dv[i].ai;
39 char *v = fp->av + fp->dv[i].aj;
41 if (strcmp(k, "message") == 0)
42 strncpy(l->message, v, MAXSTR);
43 else if (strcmp(k, "song") == 0)
44 strncpy(l->song, v, PATHMAX);
45 else if (strcmp(k, "shot") == 0)
46 strncpy(l->shot, v, PATHMAX);
47 else if (strcmp(k, "goal") == 0)
52 else if (strcmp(k, "time") == 0)
57 else if (strcmp(k, "time_hs") == 0)
59 switch (sscanf(v, "%d %d %d",
60 &l->score.best_times.timer[0],
61 &l->score.best_times.timer[1],
62 &l->score.best_times.timer[2]))
64 case 2: need_bt_easy = 1; break;
68 /* TODO, complain loudly? */
72 else if (strcmp(k, "goal_hs") == 0)
74 switch (sscanf(v, "%d %d %d",
75 &l->score.unlock_goal.timer[0],
76 &l->score.unlock_goal.timer[1],
77 &l->score.unlock_goal.timer[2]))
79 case 2: need_ug_easy = 1; break;
83 /* TODO, complain loudly? */
87 else if (strcmp(k, "coin_hs") == 0)
89 switch (sscanf(v, "%d %d %d",
90 &l->score.most_coins.coins[0],
91 &l->score.most_coins.coins[1],
92 &l->score.most_coins.coins[2]))
94 case 2: need_mc_easy = 1; break;
98 /* TODO, complain loudly? */
102 else if (strcmp(k, "version") == 0)
103 strncpy(l->version, v, MAXSTR);
104 else if (strcmp(k, "author") == 0)
105 strncpy(l->author, v, MAXSTR);
106 else if (strcmp(k, "bonus") == 0)
107 l->is_bonus = atoi(v) ? 1 : 0;
110 if (have_goal && need_mc_easy)
111 l->score.most_coins.coins[2] = l->goal;
116 l->score.best_times.timer[2] = l->time;
118 l->score.unlock_goal.timer[2] = l->time;
122 int level_load(const char *filename, struct level *level)
129 memset(level, 0, sizeof (struct level));
130 memset(&sol, 0, sizeof (sol));
133 L_("Error while loading level file '%s': %s\n")
134 #define default_error \
135 L_("Not a valid level file")
137 if (!sol_load_only_head(&sol, config_data(filename)))
139 const char *error = errno ? strerror(errno) : default_error;
140 fprintf(stderr, format, filename, error);
147 strncpy(level->file, filename, PATHMAX - 1);
149 score_init_hs(&level->score.best_times, 59999, 0);
150 score_init_hs(&level->score.unlock_goal, 59999, 0);
151 score_init_hs(&level->score.most_coins, 59999, 0);
155 for (i = 0; i < sol.hc; i++)
156 if (sol.hv[i].t == ITEM_COIN)
157 money += sol.hv[i].n;
159 level->score.most_coins.coins[0] = money;
161 scan_level_attribs(level, &sol);
163 /* Compute initial hs default values */
167 t[0] = t[1] = t[2]; \
168 else if (t[2] c t[1]) \
169 t[1] = (t[0] + t[2]) / 2
171 HOP(level->score.best_times.timer, <=);
172 HOP(level->score.unlock_goal.timer, <=);
173 HOP(level->score.most_coins.coins, >=);
180 void level_dump(const struct level *l)
182 printf("filename: %s\n"
187 "time hs: %d %d %d\n"
188 "goal hs: %d %d %d\n"
189 "coin hs: %d %d %d\n"
198 l->score.best_times.timer[0],
199 l->score.best_times.timer[1],
200 l->score.best_times.timer[2],
201 l->score.unlock_goal.timer[0],
202 l->score.unlock_goal.timer[1],
203 l->score.unlock_goal.timer[2],
204 l->score.most_coins.coins[0],
205 l->score.most_coins.coins[1],
206 l->score.most_coins.coins[2],
212 /*---------------------------------------------------------------------------*/
214 int level_exists(int i)
216 return set_level_exists(curr_set(), i);
219 void level_open(int i)
222 get_level(i)->is_locked = 0;
225 int level_opened(int i)
227 return level_exists(i) && !get_level(i)->is_locked;
230 void level_complete(int i)
233 get_level(i)->is_completed = 1;
236 int level_completed(int i)
238 return level_exists(i) && get_level(i)->is_completed;
241 int level_time (int i)
243 assert(level_exists(i));
244 return get_level(i)->time;
247 int level_goal (int i)
249 assert(level_exists(i));
250 return get_level(i)->goal;
253 int level_bonus(int i)
255 return level_exists(i) && get_level(i)->is_bonus;
258 const char *level_shot(int i)
260 return level_exists(i) ? get_level(i)->shot : NULL;
263 const char *level_file(int i)
265 return level_exists(i) ? get_level(i)->file : NULL;
268 const char *level_repr(int i)
270 return level_exists(i) ? get_level(i)->repr : NULL;
273 const char *level_msg(int i)
275 if (level_exists(i) && strlen(get_level(i)->message) > 0)
276 return _(get_level(i)->message);
281 /*---------------------------------------------------------------------------*/
283 int level_score_update(int level,
290 struct level *l = get_level(level);
291 char player[MAXSTR] = "";
293 config_get_s(CONFIG_PLAYER, player, MAXSTR);
296 *time_rank = score_time_insert(&l->score.best_times,
297 player, timer, coins);
300 *goal_rank = score_time_insert(&l->score.unlock_goal,
301 player, timer, coins);
304 *coin_rank = score_coin_insert(&l->score.most_coins,
305 player, timer, coins);
307 if ((time_rank && *time_rank < 3) ||
308 (goal_rank && *goal_rank < 3) ||
309 (coin_rank && *coin_rank < 3))
315 void level_rename_player(int level,
321 struct level *l = get_level(level);
323 strncpy(l->score.best_times.player [time_rank], player, MAXNAM);
324 strncpy(l->score.unlock_goal.player[goal_rank], player, MAXNAM);
325 strncpy(l->score.most_coins.player [coin_rank], player, MAXNAM);
328 /*---------------------------------------------------------------------------*/