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