Fix redundant glTexEnv calls
[neverball] / ball / level.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
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.
8  *
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.
13  */
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <math.h>
19 #include <assert.h>
20
21 #include "solid_base.h"
22
23 #include "common.h"
24 #include "config.h"
25 #include "level.h"
26 #include "set.h"
27
28 /*---------------------------------------------------------------------------*/
29
30 static void scan_level_attribs(struct level *l, const struct s_base *base)
31 {
32     int i;
33
34     int have_goal = 0;
35     int have_time = 0;
36
37     int need_time_easy = 0;
38     int need_goal_easy = 0;
39     int need_coin_easy = 0;
40
41     for (i = 0; i < base->dc; i++)
42     {
43         char *k = base->av + base->dv[i].ai;
44         char *v = base->av + base->dv[i].aj;
45
46         if (strcmp(k, "message") == 0)
47             SAFECPY(l->message, v);
48         else if (strcmp(k, "song") == 0)
49             SAFECPY(l->song, v);
50         else if (strcmp(k, "shot") == 0)
51             SAFECPY(l->shot, v);
52         else if (strcmp(k, "goal") == 0)
53         {
54             l->goal = atoi(v);
55             have_goal = 1;
56         }
57         else if (strcmp(k, "time") == 0)
58         {
59             l->time = atoi(v);
60             have_time = 1;
61         }
62         else if (strcmp(k, "time_hs") == 0)
63         {
64             switch (sscanf(v, "%d %d %d",
65                            &l->scores[SCORE_TIME].timer[RANK_HARD],
66                            &l->scores[SCORE_TIME].timer[RANK_MEDM],
67                            &l->scores[SCORE_TIME].timer[RANK_EASY]))
68             {
69             case 2: need_time_easy = 1; break;
70             case 3: break;
71             }
72         }
73         else if (strcmp(k, "goal_hs") == 0)
74         {
75             switch (sscanf(v, "%d %d %d",
76                            &l->scores[SCORE_GOAL].timer[RANK_HARD],
77                            &l->scores[SCORE_GOAL].timer[RANK_MEDM],
78                            &l->scores[SCORE_GOAL].timer[RANK_EASY]))
79             {
80             case 2: need_goal_easy = 1; break;
81             case 3: break;
82             }
83         }
84         else if (strcmp(k, "coin_hs") == 0)
85         {
86             switch (sscanf(v, "%d %d %d",
87                            &l->scores[SCORE_COIN].coins[RANK_HARD],
88                            &l->scores[SCORE_COIN].coins[RANK_MEDM],
89                            &l->scores[SCORE_COIN].coins[RANK_EASY]))
90             {
91             case 2: need_coin_easy = 1; break;
92             case 3: break;
93             }
94         }
95         else if (strcmp(k, "version") == 0)
96             SAFECPY(l->version, v);
97         else if (strcmp(k, "author") == 0)
98             SAFECPY(l->author, v);
99         else if (strcmp(k, "bonus") == 0)
100             l->is_bonus = atoi(v) ? 1 : 0;
101     }
102
103     if (have_goal)
104     {
105         if (need_coin_easy)
106             l->scores[SCORE_COIN].coins[RANK_EASY] = l->goal;
107
108         l->scores[SCORE_GOAL].coins[RANK_HARD] = l->goal;
109         l->scores[SCORE_GOAL].coins[RANK_MEDM] = l->goal;
110         l->scores[SCORE_GOAL].coins[RANK_EASY] = l->goal;
111     }
112
113     if (have_time)
114     {
115         if (need_time_easy)
116             l->scores[SCORE_TIME].timer[RANK_EASY] = l->time;
117         if (need_goal_easy)
118             l->scores[SCORE_GOAL].timer[RANK_EASY] = l->time;
119
120         l->scores[SCORE_COIN].timer[RANK_HARD] = l->time;
121         l->scores[SCORE_COIN].timer[RANK_MEDM] = l->time;
122         l->scores[SCORE_COIN].timer[RANK_EASY] = l->time;
123     }
124 }
125
126 int level_load(const char *filename, struct level *level)
127 {
128     struct s_base base;
129
130     memset(level, 0, sizeof (struct level));
131     memset(&base, 0, sizeof (base));
132
133     if (!sol_load_meta(&base, filename))
134     {
135         fprintf(stderr, L_("Failure to load level file '%s'\n"), filename);
136         return 0;
137     }
138
139     SAFECPY(level->file, filename);
140     SAFECPY(level->name, "00");
141
142     score_init_hs(&level->scores[SCORE_TIME], 59999, 0);
143     score_init_hs(&level->scores[SCORE_GOAL], 59999, 0);
144     score_init_hs(&level->scores[SCORE_COIN], 59999, 0);
145
146     scan_level_attribs(level, &base);
147
148     sol_free_base(&base);
149
150     return 1;
151 }
152
153 /*---------------------------------------------------------------------------*/
154
155 int level_exists(int i)
156 {
157     return !!get_level(i);
158 }
159
160 void level_open(struct level *level)
161 {
162     level->is_locked = 0;
163 }
164
165 int level_opened(const struct level *level)
166 {
167     return !level->is_locked;
168 }
169
170 void level_complete(struct level *level)
171 {
172     level->is_completed = 1;
173 }
174
175 int level_completed(const struct level *level)
176 {
177     return level->is_completed;
178 }
179
180 int level_time(const struct level *level)
181 {
182     return level->time;
183 }
184
185 int level_goal(const struct level *level)
186 {
187     return level->goal;
188 }
189
190 int  level_bonus(const struct level *level)
191 {
192     return level->is_bonus;
193 }
194
195 const char *level_shot(const struct level *level)
196 {
197     return level->shot;
198 }
199
200 const char *level_file(const struct level *level)
201 {
202     return level->file;
203 }
204
205 const char *level_song(const struct level *level)
206 {
207     return level->song;
208 }
209
210 const char *level_name(const struct level *level)
211 {
212     return level->name;
213 }
214
215 const char *level_msg(const struct level *level)
216 {
217     if (strlen(level->message) > 0)
218         return _(level->message);
219     return "";
220 }
221
222 const struct score *level_score(struct level *level, int s)
223 {
224     return &level->scores[s];
225 }
226
227 /*---------------------------------------------------------------------------*/
228
229 int level_score_update(struct level *l,
230                        int timer,
231                        int coins,
232                        int *time_rank,
233                        int *goal_rank,
234                        int *coin_rank)
235 {
236     const char *player =  config_get_s(CONFIG_PLAYER);
237
238     score_time_insert(&l->scores[SCORE_TIME], time_rank, player, timer, coins);
239     score_time_insert(&l->scores[SCORE_GOAL], goal_rank, player, timer, coins);
240     score_coin_insert(&l->scores[SCORE_COIN], coin_rank, player, timer, coins);
241
242     if ((time_rank && *time_rank < 3) ||
243         (goal_rank && *goal_rank < 3) ||
244         (coin_rank && *coin_rank < 3))
245         return 1;
246     else
247         return 0;
248 }
249
250 void level_rename_player(struct level *l,
251                          int time_rank,
252                          int goal_rank,
253                          int coin_rank,
254                          const char *player)
255 {
256     SAFECPY(l->scores[SCORE_TIME].player[time_rank], player);
257     SAFECPY(l->scores[SCORE_GOAL].player[goal_rank], player);
258     SAFECPY(l->scores[SCORE_COIN].player[coin_rank], player);
259 }
260
261 /*---------------------------------------------------------------------------*/
262