Make tilt limit angle independent (remove extra diagonal acceleration)
[neverball.git] / putt / hole.c
bloba344002d2229dc5b995e6f387e9563f0f515b0c8
1 /*
2 * Copyright (C) 2003 Robert Kooima
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.
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.
15 #include <stdio.h>
16 #include <string.h>
17 #include <math.h>
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"
29 /*---------------------------------------------------------------------------*/
31 struct hole
33 char file[MAXSTR];
34 char back[MAXSTR];
35 char song[MAXSTR];
36 int par;
39 static int hole;
40 static int party;
41 static int player;
42 static int count;
43 static int done;
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];
51 /*---------------------------------------------------------------------------*/
53 static void hole_init_rc(const char *filename)
55 fs_file fin;
56 char buff[MAXSTR];
58 hole = 0;
59 player = 0;
60 count = 0;
61 done = 0;
63 /* Load the holes list. */
65 if ((fin = fs_open(filename, "r")))
67 /* Skip shot and description. */
69 if (fs_gets(buff, sizeof (buff), fin) &&
70 fs_gets(buff, sizeof (buff), fin))
72 /* Read the list. */
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) >= 1)
80 count++;
83 fs_close(fin);
87 /*---------------------------------------------------------------------------*/
89 int hole_load(int h, const char *filename)
91 struct s_base base;
93 if (filename != hole_v[h].file)
95 /* Note filename if it came from elsewhere. */
97 SAFECPY(hole_v[h].file, filename);
100 if (sol_load_meta(&base, filename))
102 int i;
104 for (i = 0; i < base.dc; i++)
106 const char *k = base.av + base.dv[i].ai;
107 const char *v = base.av + base.dv[i].aj;
109 if (strcmp("grad", k) == 0)
110 SAFECPY(hole_v[h].back, v);
111 else if (strcmp("par", k) == 0)
112 hole_v[h].par = atoi(v);
113 else if (strcmp("song", k) == 0)
114 SAFECPY(hole_v[h].song, v);
117 score_v[h][0] = hole_v[h].par;
119 sol_free_base(&base);
120 return 1;
122 return 0;
125 void hole_init(const char *filename)
127 int i;
129 memset(hole_v, 0, sizeof (struct hole) * MAXHOL);
130 memset(score_v, 0, sizeof (int) * MAXPLY * MAXHOL);
132 if (filename)
134 hole_init_rc(filename);
136 for (i = 0; i < count; i++)
137 hole_load(i, hole_v[i].file);
139 else
141 /* Standalone mode. */
142 /* Why is this 2, you ask? Good question. */
144 count = 2;
148 void hole_free(void)
150 game_free();
151 back_free();
153 count = 0;
156 /*---------------------------------------------------------------------------*/
158 char *hole_player(int p)
160 if (p == 0) return _("Par");
162 if (p == 1 && 1 <= party) return _("P1");
163 if (p == 2 && 2 <= party) return _("P2");
164 if (p == 3 && 3 <= party) return _("P3");
165 if (p == 4 && 4 <= party) return _("P4");
167 return NULL;
170 char *hole_score(int h, int p)
172 static char str[MAXSTR];
174 if (1 <= h && h <= hole)
176 if (h <= hole && 0 <= p && p <= party)
178 sprintf(str, "%d", score_v[h][p]);
179 return str;
182 return NULL;
185 char *hole_tot(int p)
187 static char str[MAXSTR];
189 int h, T = 0;
191 if (p <= party)
193 for (h = 1; h <= hole && h < count; h++)
194 T += score_v[h][p];
196 sprintf(str, "%d", T);
198 return str;
200 return NULL;
203 char *hole_out(int p)
205 static char str[MAXSTR];
207 int h, T = 0;
209 if (p <= party)
211 for (h = 1; h <= hole && h <= count / 2; h++)
212 T += score_v[h][p];
214 sprintf(str, "%d", T);
216 return str;
218 return NULL;
221 char *hole_in(int p)
223 static char str[MAXSTR];
225 int h, T = 0;
226 int out = count / 2;
228 if (hole > out && p <= party)
230 for (h = out + 1; h <= hole && h < count; h++)
231 T += score_v[h][p];
233 sprintf(str, "%d", T);
235 return str;
237 return NULL;
240 /*---------------------------------------------------------------------------*/
242 int curr_hole(void) { return hole; }
243 int curr_party(void) { return party; }
244 int curr_player(void) { return player; }
245 int curr_count(void) { return count; }
247 const char *curr_scr(void)
249 static char buf[8];
251 sprintf(buf, "%d", score_v[hole][player]);
253 return buf;
256 const char *curr_par(void)
258 static char buf[8];
260 sprintf(buf, "%d", score_v[hole][0]);
262 return buf;
265 /*---------------------------------------------------------------------------*/
267 int hole_goto(int h, int p)
269 int i;
271 if (h < count)
273 if (h >= 0) hole = h;
274 if (p >= 0) party = p;
276 if (game_init(hole_v[hole].file))
278 back_init(hole_v[hole].back);
280 player = (hole - 1) % party + 1;
281 done = 0;
283 for (i = 1; i <= party; i++)
285 game_get_pos(ball_p[i], ball_e[i]);
286 stat_v[i] = 0;
288 game_ball(player);
289 hole_song();
290 return 1;
293 return 0;
296 int hole_next(void)
298 if (done < party)
302 player = player % party + 1;
304 while (stat_v[player]);
306 game_ball(player);
307 game_get_pos(ball_p[player], ball_e[player]);
309 return 1;
311 return 0;
314 int hole_move(void)
316 if (hole + 1 < count)
318 hole++;
320 game_free();
321 back_free();
323 if (hole_goto(hole, party))
324 return 1;
326 return 0;
329 void hole_goal(void)
331 score_v[hole][player]++;
333 if (score_v[hole][player] == 1)
334 audio_play(AUD_ONE, 1.0f);
336 else if (score_v[hole][player] == score_v[hole][0] - 2)
337 audio_play(AUD_EAGLE, 1.0f);
338 else if (score_v[hole][player] == score_v[hole][0] - 1)
339 audio_play(AUD_BIRDIE, 1.0f);
340 else if (score_v[hole][player] == score_v[hole][0])
341 audio_play(AUD_PAR, 1.0f);
342 else if (score_v[hole][player] == score_v[hole][0] + 1)
343 audio_play(AUD_BOGEY, 1.0f);
344 else if (score_v[hole][player] == score_v[hole][0] + 2)
345 audio_play(AUD_DOUBLE, 1.0f);
346 else
347 audio_play(AUD_SUCCESS, 1.0f);
349 stat_v[player] = 1;
350 done++;
352 if (done == party)
353 audio_music_fade_out(2.0f);
356 void hole_stop(void)
358 score_v[hole][player]++;
360 /* Cap scores at 12 or par plus 3. */
362 if (score_v[hole][player] >= 12 &&
363 score_v[hole][player] >= score_v[hole][0] + 3)
365 score_v[hole][player] = (score_v[hole][0] > 12 - 3) ? score_v[hole][0] + 3 : 12;
366 stat_v[player] = 1;
367 done++;
371 void hole_fall(void)
373 audio_play(AUD_PENALTY, 1.0f);
375 /* Reset to the position of the putt, and apply a one-stroke penalty. */
377 game_set_pos(ball_p[player], ball_e[player]);
378 score_v[hole][player] += 2;
380 /* Cap scores at 12 or par plus 3. */
382 if (score_v[hole][player] >= 12 &&
383 score_v[hole][player] >= score_v[hole][0] + 3)
385 score_v[hole][player] = (score_v[hole][0] > 12 - 3) ? score_v[hole][0] + 3 : 12;
386 stat_v[player] = 1;
387 done++;
391 /*---------------------------------------------------------------------------*/
393 void hole_song(void)
395 audio_music_fade_to(0.5f, hole_v[hole].song);