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_fu_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.fast_unlock.timer[0],
76 &l->score.fast_unlock.timer[1],
77 &l->score.fast_unlock.timer[2]))
79 case 2: need_fu_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;
113 l->score.most_coins.coins[2] = l->goal;
115 l->score.fast_unlock.coins[0] =
116 l->score.fast_unlock.coins[1] =
117 l->score.fast_unlock.coins[2] = l->goal;
123 l->score.best_times.timer[2] = l->time;
125 l->score.fast_unlock.timer[2] = l->time;
129 int level_load(const char *filename, struct level *level)
136 memset(level, 0, sizeof (struct level));
137 memset(&sol, 0, sizeof (sol));
140 L_("Error while loading level file '%s': %s\n")
141 #define default_error \
142 L_("Not a valid level file")
144 if (!sol_load_only_head(&sol, filename))
146 const char *error = errno ? strerror(errno) : default_error;
147 fprintf(stderr, format, filename, error);
154 strncpy(level->file, filename, PATHMAX - 1);
156 score_init_hs(&level->score.best_times, 59999, 0);
157 score_init_hs(&level->score.fast_unlock, 59999, 0);
158 score_init_hs(&level->score.most_coins, 59999, 0);
162 for (i = 0; i < sol.hc; i++)
163 if (sol.hv[i].t == ITEM_COIN)
164 money += sol.hv[i].n;
166 level->score.most_coins.coins[0] = money;
168 scan_level_attribs(level, &sol);
170 /* Compute initial hs default values */
174 t[0] = t[1] = t[2]; \
175 else if (t[2] c t[1]) \
176 t[1] = (t[0] + t[2]) / 2
178 HOP(level->score.best_times.timer, <=);
179 HOP(level->score.fast_unlock.timer, <=);
180 HOP(level->score.most_coins.coins, >=);
187 /*---------------------------------------------------------------------------*/
189 int level_exists(int i)
191 return set_level_exists(curr_set(), i);
194 void level_open(int i)
197 get_level(i)->is_locked = 0;
200 int level_opened(int i)
202 return level_exists(i) && !get_level(i)->is_locked;
205 void level_complete(int i)
208 get_level(i)->is_completed = 1;
211 int level_completed(int i)
213 return level_exists(i) && get_level(i)->is_completed;
216 int level_time (int i)
218 assert(level_exists(i));
219 return get_level(i)->time;
222 int level_goal (int i)
224 assert(level_exists(i));
225 return get_level(i)->goal;
228 int level_bonus(int i)
230 return level_exists(i) && get_level(i)->is_bonus;
233 const char *level_shot(int i)
235 return level_exists(i) ? get_level(i)->shot : NULL;
238 const char *level_file(int i)
240 return level_exists(i) ? get_level(i)->file : NULL;
243 const char *level_name(int i)
245 return level_exists(i) ? get_level(i)->name : NULL;
248 const char *level_msg(int i)
250 if (level_exists(i) && strlen(get_level(i)->message) > 0)
251 return _(get_level(i)->message);
256 /*---------------------------------------------------------------------------*/
258 int level_score_update(int level,
265 struct level *l = get_level(level);
266 char player[MAXSTR] = "";
268 config_get_s(CONFIG_PLAYER, player, MAXSTR);
271 *time_rank = score_time_insert(&l->score.best_times,
272 player, timer, coins);
275 *goal_rank = score_time_insert(&l->score.fast_unlock,
276 player, timer, coins);
279 *coin_rank = score_coin_insert(&l->score.most_coins,
280 player, timer, coins);
282 if ((time_rank && *time_rank < 3) ||
283 (goal_rank && *goal_rank < 3) ||
284 (coin_rank && *coin_rank < 3))
290 void level_rename_player(int level,
296 struct level *l = get_level(level);
298 strncpy(l->score.best_times.player [time_rank], player, MAXNAM);
299 strncpy(l->score.fast_unlock.player[goal_rank], player, MAXNAM);
300 strncpy(l->score.most_coins.player [coin_rank], player, MAXNAM);
303 /*---------------------------------------------------------------------------*/