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.
29 /*---------------------------------------------------------------------------*/
31 static void scan_dict(struct level *l, const struct s_file *fp)
35 for (i = 0; i < fp->dc; i++)
37 char *k = fp->av + fp->dv[i].ai;
38 char *v = fp->av + fp->dv[i].aj;
40 if (strcmp(k, "message") == 0)
41 strncpy(l->message, v, MAXSTR);
42 else if (strcmp(k, "back") == 0)
43 strncpy(l->back, v, PATHMAX);
44 else if (strcmp(k, "song") == 0)
45 strncpy(l->song, v, PATHMAX);
46 else if (strcmp(k, "grad") == 0)
47 strncpy(l->grad, v, PATHMAX);
48 else if (strcmp(k, "shot") == 0)
49 strncpy(l->shot, v, PATHMAX);
50 else if (strcmp(k, "goal") == 0)
53 l->score.most_coins.coins[2] = l->goal;
55 else if (strcmp(k, "time") == 0)
58 l->score.best_times.timer[2] = l->time;
59 l->score.unlock_goal.timer[2] = l->time;
61 else if (strcmp(k, "time_hs") == 0)
63 &l->score.best_times.timer[0],
64 &l->score.best_times.timer[1]);
65 else if (strcmp(k, "goal_hs") == 0)
67 &l->score.unlock_goal.timer[0],
68 &l->score.unlock_goal.timer[1]);
69 else if (strcmp(k, "coin_hs") == 0)
71 &l->score.most_coins.coins[0],
72 &l->score.most_coins.coins[1]);
73 else if (strcmp(k, "version") == 0)
74 strncpy(l->version, v, MAXSTR);
75 else if (strcmp(k, "author") == 0)
76 strncpy(l->author, v, MAXSTR);
77 else if (strcmp(k, "bonus") == 0)
78 l->is_bonus = atoi(v) ? 1 : 0;
82 int level_load(const char *filename, struct level *level)
89 memset(level, 0, sizeof (struct level));
90 memset(&sol, 0, sizeof (sol));
93 L_("Error while loading level file '%s': %s\n")
94 #define default_error \
95 L_("Not a valid level file")
97 if (!sol_load_only_head(&sol, config_data(filename)))
99 const char *error = errno ? strerror(errno) : default_error;
100 fprintf(stderr, format, filename, error);
107 strncpy(level->file, filename, PATHMAX - 1);
109 score_init_hs(&level->score.best_times, 59999, 0);
110 score_init_hs(&level->score.unlock_goal, 59999, 0);
111 score_init_hs(&level->score.most_coins, 59999, 0);
115 for (i = 0; i < sol.hc; i++)
116 if (sol.hv[i].t == ITEM_COIN)
117 money += sol.hv[i].n;
119 level->score.most_coins.coins[0] = money;
122 scan_dict(level, &sol);
124 /* Compute initial hs default values */
128 t[0] = t[1] = t[2]; \
129 else if (t[2] c t[1]) \
130 t[1] = (t[0] + t[2]) / 2
132 HOP(level->score.best_times.timer, <=);
133 HOP(level->score.unlock_goal.timer, <=);
134 HOP(level->score.most_coins.coins, >=);
141 void level_dump(const struct level *l)
143 printf("filename: %s\n"
148 "time hs: %d %d %d\n"
149 "goal hs: %d %d %d\n"
150 "coin hs: %d %d %d\n"
161 l->score.best_times.timer[0],
162 l->score.best_times.timer[1],
163 l->score.best_times.timer[2],
164 l->score.unlock_goal.timer[0],
165 l->score.unlock_goal.timer[1],
166 l->score.unlock_goal.timer[2],
167 l->score.most_coins.coins[0],
168 l->score.most_coins.coins[1],
169 l->score.most_coins.coins[2],
177 /*---------------------------------------------------------------------------*/
179 static unsigned int do_level_init = 1;
181 int level_replay(const char *filename)
183 return demo_replay_init(filename, curr_lg());
186 int level_play(const struct level *l, int m)
188 struct level_game *lg = curr_lg();
192 memset(lg, 0, sizeof (struct level_game));
199 lg->goal = (lg->mode == MODE_PRACTICE) ? 0 : lg->level->goal;
200 lg->time = (lg->mode == MODE_PRACTICE) ? 0 : lg->level->time;
202 /* Clear other fields. */
204 lg->status = GAME_NONE;
206 lg->timer = lg->time;
207 lg->coin_rank = lg->goal_rank = lg->time_rank =
208 lg->score_rank = lg->times_rank = 3;
210 lg->win = lg->dead = lg->unlock = 0;
211 lg->next_level = NULL;
214 return demo_play_init(USER_REPLAY_FILE, lg->level, lg);
217 void level_stat(int status, int clock, int coins)
219 struct level_game *lg = curr_lg();
222 int timer = (mode == MODE_PRACTICE) ? clock : lg->time - clock;
226 config_get_s(CONFIG_PLAYER, player, MAXNAM);
232 if (mode == MODE_CHALLENGE)
237 /* sum coins an earn extra balls */
238 if (status == GAME_GOAL || lg->level->is_bonus)
240 lg->balls += count_extra_balls(lg->score, coins);
244 /* lose ball and game */
247 lg->dead = (lg->balls <= 0);
252 set_finish_level(lg, player);
257 void level_stop(void)
265 struct level_game *lg = curr_lg();
268 lg->level = lg->next_level;
271 return level_play(lg->level, lg->mode);
278 return level_play(curr_lg()->level, curr_lg()->mode);
281 /*---------------------------------------------------------------------------*/
283 int count_extra_balls(int old_score, int coins)
285 return ((old_score % 100) + coins) / 100;
288 void level_update_player_name(void)
292 config_get_s(CONFIG_PLAYER, player, MAXNAM);
294 score_change_name(curr_lg(), player);
297 /*---------------------------------------------------------------------------*/
299 const char *status_to_str(int m)
303 case GAME_NONE: return _("Aborted");
304 case GAME_TIME: return _("Time-out");
305 case GAME_GOAL: return _("Success");
306 case GAME_FALL: return _("Fall-out");
307 default: return _("Unknown");
311 /*---------------------------------------------------------------------------*/