bonus ball for bonus levels. Fix #56
[neverball] / putt / hole.c
1 /*   
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERPUTT 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 <string.h>
17 #include <math.h>
18
19 #include "hole.h"
20 #include "glext.h"
21 #include "image.h"
22 #include "game.h"
23 #include "geom.h"
24 #include "hud.h"
25 #include "back.h"
26 #include "audio.h"
27 #include "config.h"
28
29 /*---------------------------------------------------------------------------*/
30
31 struct hole
32 {
33     char   file[MAXSTR];
34     char   back[MAXSTR];
35     char   song[MAXSTR];
36     int    par;
37 };
38
39 static int hole;
40 static int party;
41 static int player;
42 static int count;
43 static int done;
44
45 static int         stat_v[MAXPLY];
46 static float       ball_p[MAXPLY][3];
47 static float       ball_e[MAXPLY][3][3];
48 static struct hole hole_v[MAXHOL];
49 static int        score_v[MAXHOL][MAXPLY];
50
51 /*---------------------------------------------------------------------------*/
52
53 static void hole_init_rc(const char *filename)
54 {
55     FILE *fin;
56
57     hole   = 0;
58     player = 0;
59     count  = 0;
60     done   = 0;
61
62     /* Load the holes list. */
63
64     if ((fin = fopen(config_data(filename), "r")))
65     {
66         while (fscanf(fin, "%s %s %d %s",
67                        hole_v[count].file,
68                        hole_v[count].back,
69                       &hole_v[count].par,
70                        hole_v[count].song) == 4)
71             count++;
72
73         fclose(fin);
74     }
75 }
76
77 /*---------------------------------------------------------------------------*/
78
79 void hole_init(const char *filename)
80 {
81     int i;
82
83     memset(hole_v,  0, sizeof (struct hole) * MAXHOL);
84     memset(score_v, 0, sizeof (int) * MAXPLY * MAXHOL);
85
86     hole_init_rc(filename);
87
88     for (i = 0; i < count; i++)
89         score_v[i][0] = hole_v[i].par;
90 }
91
92 void hole_free(void)
93 {
94     game_free();
95     back_free();
96
97     count = 0;
98 }
99
100 /*---------------------------------------------------------------------------*/
101
102 char *hole_player(int p)
103 {
104     if (p == 0)               return _("Par");
105
106     if (p == 1 && 1 <= party) return _("P1");
107     if (p == 2 && 2 <= party) return _("P2");
108     if (p == 3 && 3 <= party) return _("P3");
109     if (p == 4 && 4 <= party) return _("P4");
110
111     return NULL;
112 }
113
114 char *hole_score(int h, int p)
115 {
116     static char str[MAXSTR];
117
118     if (1 <= h && h <= hole)
119     {
120         if (h <= hole && 0 <= p && p <= party)
121         {
122             sprintf(str, "%d", score_v[h][p]);
123             return str;
124         }
125     }
126     return NULL;
127 }
128
129 char *hole_tot(int p)
130 {
131     static char str[MAXSTR];
132
133     int h, T = 0;
134
135     if (p <= party)
136     {
137         for (h = 1; h <= hole && h <= 18; h++)
138             T += score_v[h][p];
139
140         sprintf(str, "%d", T);
141
142         return str;
143     }
144     return NULL;
145 }
146
147 char *hole_out(int p)
148 {
149     static char str[MAXSTR];
150
151     int h, T = 0;
152
153     if (p <= party)
154     {
155         for (h = 1; h <= hole && h <= 9; h++)
156             T += score_v[h][p];
157
158         sprintf(str, "%d", T);
159
160         return str;
161     }
162     return NULL;
163 }
164
165 char *hole_in(int p)
166 {
167     static char str[MAXSTR];
168
169     int h, T = 0;
170
171     if (hole > 9 && p <= party)
172     {
173         for (h = 10; h <= hole && h <= 18; h++)
174             T += score_v[h][p];
175
176         sprintf(str, "%d", T);
177
178         return str;
179     }
180     return NULL;
181 }
182
183 /*---------------------------------------------------------------------------*/
184
185 int curr_hole(void)   { return hole;   }
186 int curr_party(void)  { return party;  }
187 int curr_player(void) { return player; }
188 int curr_count(void)  { return count;  }
189
190 const char *curr_scr(void)
191 {
192     static char buf[8];
193
194     sprintf(buf, "%d", score_v[hole][player]);
195
196     return buf;
197 }
198
199 const char *curr_par(void)
200 {
201     static char buf[8];
202
203     sprintf(buf, "%d", score_v[hole][0]);
204
205     return buf;
206 }
207
208 /*---------------------------------------------------------------------------*/
209
210 void hole_goto(int h, int p)
211 {
212     int i;
213
214     if (h < count)
215     {
216         if (h >= 0) hole  = h;
217         if (p >= 0) party = p;
218
219         player = (hole - 1) % party + 1;
220         done   = 0;
221
222         back_init(hole_v[hole].back, 1);
223         game_init(hole_v[hole].file);
224
225         for (i = 1; i <= party; i++)
226         {
227             game_get_pos(ball_p[i], ball_e[i]);
228             stat_v[i] = 0;
229         }
230         game_ball(player);
231         hole_song();
232     }
233 }
234
235 int hole_next(void)
236 {
237     if (done < party)
238     {
239         do
240         {
241             player = player % party + 1;
242         }
243         while (stat_v[player]);
244
245         game_ball(player);
246         game_get_pos(ball_p[player], ball_e[player]);
247
248         return 1;
249     }
250     return 0;
251 }
252
253 int hole_move(void)
254 {
255     if (hole + 1 < count)
256     {
257         hole++;
258
259         game_free();
260         back_free();
261
262         hole_goto(hole, party);
263
264         return 1;
265     }
266     return 0;
267 }
268
269 void hole_goal(void)
270 {
271     score_v[hole][player]++;
272
273     if (score_v[hole][player] == 1)
274         audio_play(AUD_ONE, 1.0f);
275
276     else if (score_v[hole][player] == score_v[hole][0] - 2)
277         audio_play(AUD_EAGLE, 1.0f);
278     else if (score_v[hole][player] == score_v[hole][0] - 1)
279         audio_play(AUD_BIRDIE, 1.0f);
280     else if (score_v[hole][player] == score_v[hole][0])
281         audio_play(AUD_PAR, 1.0f);
282     else if (score_v[hole][player] == score_v[hole][0] + 1)
283         audio_play(AUD_BOGEY, 1.0f);
284     else if (score_v[hole][player] == score_v[hole][0] + 2)
285         audio_play(AUD_DOUBLE, 1.0f);
286     else
287         audio_play(AUD_SUCCESS, 1.0f);
288
289     stat_v[player] = 1;
290     done++;
291
292     if (done == party)
293         audio_music_fade_out(2.0f);
294 }
295
296 void hole_stop(void)
297 {
298     score_v[hole][player]++;
299
300     /* Cap scores at 12. */
301
302     if (score_v[hole][player] >= 12)
303     {
304         score_v[hole][player] = 12;
305         stat_v[player] = 1;
306         done++;
307     }
308 }
309
310 void hole_fall(void)
311 {
312     audio_play(AUD_PENALTY, 1.0f);
313
314     /* Reset to the position of the putt, and apply a one-stroke penalty. */
315
316     game_set_pos(ball_p[player], ball_e[player]);
317     score_v[hole][player] += 2;
318
319     /* Cap scores at 12. */
320
321     if (score_v[hole][player] >= 12)
322     {
323         score_v[hole][player] = 12;
324         stat_v[player] = 1;
325         done++;
326     }
327 }
328
329 /*---------------------------------------------------------------------------*/
330
331 void hole_song(void)
332 {
333     audio_music_fade_to(0.5f, hole_v[hole].song);
334 }