Simple smooth fix
[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 < count; 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 <= count / 2; 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     int out = count / 2;
171
172     if (hole > out && p <= party)
173     {
174         for (h = out + 1; h <= hole && h < count; h++)
175             T += score_v[h][p];
176
177         sprintf(str, "%d", T);
178
179         return str;
180     }
181     return NULL;
182 }
183
184 /*---------------------------------------------------------------------------*/
185
186 int curr_hole(void)   { return hole;   }
187 int curr_party(void)  { return party;  }
188 int curr_player(void) { return player; }
189 int curr_count(void)  { return count;  }
190
191 const char *curr_scr(void)
192 {
193     static char buf[8];
194
195     sprintf(buf, "%d", score_v[hole][player]);
196
197     return buf;
198 }
199
200 const char *curr_par(void)
201 {
202     static char buf[8];
203
204     sprintf(buf, "%d", score_v[hole][0]);
205
206     return buf;
207 }
208
209 /*---------------------------------------------------------------------------*/
210
211 void hole_goto(int h, int p)
212 {
213     int i;
214
215     if (h < count)
216     {
217         if (h >= 0) hole  = h;
218         if (p >= 0) party = p;
219
220         player = (hole - 1) % party + 1;
221         done   = 0;
222
223         back_init(hole_v[hole].back, 1);
224         game_init(hole_v[hole].file);
225
226         for (i = 1; i <= party; i++)
227         {
228             game_get_pos(ball_p[i], ball_e[i]);
229             stat_v[i] = 0;
230         }
231         game_ball(player);
232         hole_song();
233     }
234 }
235
236 int hole_next(void)
237 {
238     if (done < party)
239     {
240         do
241         {
242             player = player % party + 1;
243         }
244         while (stat_v[player]);
245
246         game_ball(player);
247         game_get_pos(ball_p[player], ball_e[player]);
248
249         return 1;
250     }
251     return 0;
252 }
253
254 int hole_move(void)
255 {
256     if (hole + 1 < count)
257     {
258         hole++;
259
260         game_free();
261         back_free();
262
263         hole_goto(hole, party);
264
265         return 1;
266     }
267     return 0;
268 }
269
270 void hole_goal(void)
271 {
272     score_v[hole][player]++;
273
274     if (score_v[hole][player] == 1)
275         audio_play(AUD_ONE, 1.0f);
276
277     else if (score_v[hole][player] == score_v[hole][0] - 2)
278         audio_play(AUD_EAGLE, 1.0f);
279     else if (score_v[hole][player] == score_v[hole][0] - 1)
280         audio_play(AUD_BIRDIE, 1.0f);
281     else if (score_v[hole][player] == score_v[hole][0])
282         audio_play(AUD_PAR, 1.0f);
283     else if (score_v[hole][player] == score_v[hole][0] + 1)
284         audio_play(AUD_BOGEY, 1.0f);
285     else if (score_v[hole][player] == score_v[hole][0] + 2)
286         audio_play(AUD_DOUBLE, 1.0f);
287     else
288         audio_play(AUD_SUCCESS, 1.0f);
289
290     stat_v[player] = 1;
291     done++;
292
293     if (done == party)
294         audio_music_fade_out(2.0f);
295 }
296
297 void hole_stop(void)
298 {
299     score_v[hole][player]++;
300
301     /* Cap scores at 12 or par plus 3. */
302
303     if (score_v[hole][player] >= 12 && score_v[hole][player] >= score_v[hole][0] + 3)
304     {
305         score_v[hole][player] = (score_v[hole][0] > 12 - 3) ? score_v[hole][0] + 3 : 12;
306         stat_v[player] = 1;
307         done++;
308     }
309 }
310
311 void hole_fall(void)
312 {
313     audio_play(AUD_PENALTY, 1.0f);
314
315     /* Reset to the position of the putt, and apply a one-stroke penalty. */
316
317     game_set_pos(ball_p[player], ball_e[player]);
318     score_v[hole][player] += 2;
319
320     /* Cap scores at 12 or par plus 3. */
321
322     if (score_v[hole][player] >= 12 && score_v[hole][player] >= score_v[hole][0] + 3)
323     {
324         score_v[hole][player] = (score_v[hole][0] > 12 - 3) ? score_v[hole][0] + 3 : 12;
325         stat_v[player] = 1;
326         done++;
327     }
328 }
329
330 /*---------------------------------------------------------------------------*/
331
332 void hole_song(void)
333 {
334     audio_music_fade_to(0.5f, hole_v[hole].song);
335 }