Changed all references to "state" as in "outcome of the game" to
[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 <errno.h>
20
21 #include "level.h"
22 #include "solid.h"
23
24 /*---------------------------------------------------------------------------*/
25
26 static void level_scan_metadata(struct level *l, const struct s_file *fp)
27 {
28     int i;
29
30     for (i = 0; i < fp->dc; i++)
31     {
32         char *k = fp->av + fp->dv[i].ai;
33         char *v = fp->av + fp->dv[i].aj;
34
35         if (strcmp(k, "message") == 0)
36             strncpy(l->message, v, MAXSTR);
37         else if (strcmp(k, "back") == 0)
38             strncpy(l->back, v, PATHMAX);
39         else if (strcmp(k, "song") == 0)
40             strncpy(l->song, v, PATHMAX);
41         else if (strcmp(k, "grad") == 0)
42             strncpy(l->grad, v, PATHMAX);
43         else if (strcmp(k, "shot") == 0)
44             strncpy(l->shot, v, PATHMAX);
45         else if (strcmp(k, "goal") == 0)
46         {
47             l->goal = atoi(v);
48             l->score.most_coins.coins[2] = l->goal;
49         }
50         else if (strcmp(k, "time") == 0)
51         {
52             l->time = atoi(v);
53             l->score.best_times.timer[2] = l->time;
54             l->score.unlock_goal.timer[2] = l->time;
55         }
56         else if (strcmp(k, "time_hs") == 0)
57             sscanf(v, "%d %d",
58                    &l->score.best_times.timer[0],
59                    &l->score.best_times.timer[1]);
60         else if (strcmp(k, "goal_hs") == 0)
61             sscanf(v, "%d %d",
62                    &l->score.unlock_goal.timer[0],
63                    &l->score.unlock_goal.timer[1]);
64         else if (strcmp(k, "coin_hs") == 0)
65             sscanf(v, "%d %d",
66                    &l->score.most_coins.coins[0],
67                    &l->score.most_coins.coins[1]);
68         else if (strcmp(k, "version") == 0)
69             strncpy(l->version, v, MAXSTR);
70         else if (strcmp(k, "author") == 0)
71             strncpy(l->author, v, MAXSTR);
72         else if (strcmp(k, "bonus") == 0)
73             l->is_bonus = atoi(v) ? 1 : 0;
74     }
75 }
76
77 /* Load the sol file 'filename' and fill the 'level' structure.  Return 1 on
78  * success, 0 on error. */
79
80 int level_load(const char *filename, struct level *level)
81 {
82     struct s_file sol;
83
84     int money;
85     int i;
86
87     memset(level, 0, sizeof (struct level));
88     memset(&sol,  0, sizeof (sol));
89
90     /* Try to load the sol file */
91     if (!sol_load_only_file(&sol, config_data(filename)))
92     {
93         fprintf(stderr,
94                 _("Error while loading level file '%s': %s\n"), filename,
95                 errno ? strerror(errno) : _("Not a valid level file"));
96         return 0;
97     }
98
99     strcpy(level->file, filename);
100
101     /* Init hs with default values */
102     score_init_hs(&level->score.best_times, 59999, 0);
103     score_init_hs(&level->score.unlock_goal, 59999, 0);
104     score_init_hs(&level->score.most_coins, 59999, 0);
105
106     /* Compute money and default max money */
107     money = 0;
108     for (i = 0; i < sol.hc; i++)
109         if (sol.hv[i].t == ITEM_COIN)
110             money += sol.hv[i].n;
111     level->score.most_coins.coins[0] = money;
112
113     /* Scan sol metadata */
114     if (sol.dc > 0)
115         level_scan_metadata(level, &sol);
116
117     /* Compute initial hs default values */
118
119 #define HOP(t, c) \
120     if (t[2] c t[0]) \
121         t[0] = t[1] = t[2]; \
122     else if (t[2] c t[1]) \
123         t[1] = (t[0] + t[2]) / 2
124
125     HOP(level->score.best_times.timer, <=);
126     HOP(level->score.unlock_goal.timer, <=);
127     HOP(level->score.most_coins.coins, >=);
128
129     sol_free(&sol);
130
131     return 1;
132 }
133
134 /*---------------------------------------------------------------------------*/
135
136 void level_dump_info(const struct level *l)
137 {
138     printf("filename:        %s\n"
139            "version:         %s\n"
140            "author:          %s\n"
141            "time limit:      %d\n"
142            "goal count:      %d\n"
143            "time hs:         %d %d %d\n"
144            "goal hs:         %d %d %d\n"
145            "coin hs:         %d %d %d\n"
146            "message:         %s\n"
147            "background:      %s\n"
148            "gradient:        %s\n"
149            "screenshot:      %s\n"
150            "song:            %s\n",
151            l->file,
152            l->version,
153            l->author,
154            l->time,
155            l->goal,
156            l->score.best_times.timer[0],
157            l->score.best_times.timer[1],
158            l->score.best_times.timer[2],
159            l->score.unlock_goal.timer[0],
160            l->score.unlock_goal.timer[1],
161            l->score.unlock_goal.timer[2],
162            l->score.most_coins.coins[0],
163            l->score.most_coins.coins[1],
164            l->score.most_coins.coins[2],
165            l->message,
166            l->back,
167            l->grad,
168            l->shot,
169            l->song);
170 }
171
172 /*---------------------------------------------------------------------------*/
173
174 const char *status_to_str(int m)
175 {
176     switch (m)
177     {
178     case GAME_NONE:    return _("Aborted");
179     case GAME_TIME:    return _("Time-out");
180     case GAME_GOAL:    return _("Success");
181     case GAME_FALL:    return _("Fall-out");
182     default:           return _("Unknown");
183     }
184 }
185
186 /*---------------------------------------------------------------------------*/