Add a "idle" method to the state structure
[neverball] / putt / st_all.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 <math.h>
16
17 #include "hud.h"
18 #include "geom.h"
19 #include "gui.h"
20 #include "vec3.h"
21 #include "game.h"
22 #include "hole.h"
23 #include "audio.h"
24 #include "course.h"
25 #include "config.h"
26 #include "video.h"
27
28 #include "st_all.h"
29 #include "st_conf.h"
30
31 /*---------------------------------------------------------------------------*/
32
33 static SDL_Joystick *joystick = NULL;
34
35 void set_joystick(SDL_Joystick *j)
36 {
37     joystick = j;
38 }
39
40 /*---------------------------------------------------------------------------*/
41
42 static char *number(int i)
43 {
44     static char str[MAXSTR];
45
46     sprintf(str, "%02d", i);
47
48     return str;
49 }
50
51 static int score_card(const char  *title,
52                       const GLubyte *c0,
53                       const GLubyte *c1)
54 {
55     int id, jd, kd, ld;
56
57     int p1 = (curr_party() >= 1) ? 1 : 0, l1 = (curr_party() == 1) ? 1 : 0;
58     int p2 = (curr_party() >= 2) ? 1 : 0, l2 = (curr_party() == 2) ? 1 : 0;
59     int p3 = (curr_party() >= 3) ? 1 : 0, l3 = (curr_party() == 3) ? 1 : 0;
60     int p4 = (curr_party() >= 4) ? 1 : 0, l4 = (curr_party() == 4) ? 1 : 0;
61
62     int i;
63     int n = curr_count() - 1;
64     int m = curr_count() / 2;
65
66     if ((id = gui_vstack(0)))
67     {
68         gui_label(id, title, GUI_MED, GUI_ALL, c0, c1);
69         gui_space(id);
70
71         if ((jd = gui_hstack(id)))
72         {
73             if ((kd = gui_varray(jd)))
74             {
75                 if (p1) gui_label(kd, _("O"),         0, GUI_NE, 0, 0);
76                 if (p1) gui_label(kd, hole_out(0), 0, 0,           gui_wht, gui_wht);
77                 if (p1) gui_label(kd, hole_out(1), 0, GUI_SE * l1, gui_red, gui_wht);
78                 if (p2) gui_label(kd, hole_out(2), 0, GUI_SE * l2, gui_grn, gui_wht);
79                 if (p3) gui_label(kd, hole_out(3), 0, GUI_SE * l3, gui_blu, gui_wht);
80                 if (p4) gui_label(kd, hole_out(4), 0, GUI_SE * l4, gui_yel, gui_wht);
81             }
82
83             if ((kd = gui_harray(jd)))
84                 for (i = m; i > 0; i--)
85                     if ((ld = gui_varray(kd)))
86                     {
87                         if (p1) gui_label(ld, number(i), 0, (i == 1) ? GUI_NW : 0, 0, 0);
88                         if (p1) gui_label(ld, hole_score(i, 0), 0, 0, gui_wht, gui_wht);
89                         if (p1) gui_label(ld, hole_score(i, 1), 0, 0, gui_red, gui_wht);
90                         if (p2) gui_label(ld, hole_score(i, 2), 0, 0, gui_grn, gui_wht);
91                         if (p3) gui_label(ld, hole_score(i, 3), 0, 0, gui_blu, gui_wht);
92                         if (p4) gui_label(ld, hole_score(i, 4), 0, 0, gui_yel, gui_wht);
93                     }
94             if ((kd = gui_varray(jd)))
95             {
96                 gui_filler(kd);
97                 if (p1) gui_label(kd, _("Par"), 0, GUI_NW,      gui_wht, gui_wht);
98                 if (p1) gui_label(kd, _("P1"),  0, GUI_SW * l1, gui_red, gui_wht);
99                 if (p2) gui_label(kd, _("P2"),  0, GUI_SW * l2, gui_grn, gui_wht);
100                 if (p3) gui_label(kd, _("P3"),  0, GUI_SW * l3, gui_blu, gui_wht);
101                 if (p4) gui_label(kd, _("P4"),  0, GUI_SW * l4, gui_yel, gui_wht);
102             }
103         }
104
105         gui_space(id);
106
107         if ((jd = gui_hstack(id)))
108         {
109             if ((kd = gui_varray(jd)))
110             {
111                 if (p1) gui_label(kd, _("Tot"),    0, GUI_TOP, 0, 0);
112                 if (p1) gui_label(kd, hole_tot(0), 0, 0,           gui_wht, gui_wht);
113                 if (p1) gui_label(kd, hole_tot(1), 0, GUI_BOT * l1, gui_red, gui_wht);
114                 if (p2) gui_label(kd, hole_tot(2), 0, GUI_BOT * l2, gui_grn, gui_wht);
115                 if (p3) gui_label(kd, hole_tot(3), 0, GUI_BOT * l3, gui_blu, gui_wht);
116                 if (p4) gui_label(kd, hole_tot(4), 0, GUI_BOT * l4, gui_yel, gui_wht);
117             }
118             if ((kd = gui_varray(jd)))
119             {
120                 if (p1) gui_label(kd, _("I"),     0, GUI_NE, 0, 0);
121                 if (p1) gui_label(kd, hole_in(0), 0, 0,           gui_wht, gui_wht);
122                 if (p1) gui_label(kd, hole_in(1), 0, GUI_SE * l1, gui_red, gui_wht);
123                 if (p2) gui_label(kd, hole_in(2), 0, GUI_SE * l2, gui_grn, gui_wht);
124                 if (p3) gui_label(kd, hole_in(3), 0, GUI_SE * l3, gui_blu, gui_wht);
125                 if (p4) gui_label(kd, hole_in(4), 0, GUI_SE * l4, gui_yel, gui_wht);
126             }
127             if ((kd = gui_harray(jd)))
128                 for (i = n; i > m; i--)
129                     if ((ld = gui_varray(kd)))
130                     {
131                         if (p1) gui_label(ld, number(i), 0, (i == m+1) ? GUI_NW : 0, 0, 0);
132                         if (p1) gui_label(ld, hole_score(i, 0), 0, 0, gui_wht, gui_wht);
133                         if (p1) gui_label(ld, hole_score(i, 1), 0, 0, gui_red, gui_wht);
134                         if (p2) gui_label(ld, hole_score(i, 2), 0, 0, gui_grn, gui_wht);
135                         if (p3) gui_label(ld, hole_score(i, 3), 0, 0, gui_blu, gui_wht);
136                         if (p4) gui_label(ld, hole_score(i, 4), 0, 0, gui_yel, gui_wht);
137                     }
138             if ((kd = gui_varray(jd)))
139             {
140                 gui_filler(kd);
141                 if (p1) gui_label(kd, _("Par"), 0, GUI_NW,      gui_wht, gui_wht);
142                 if (p1) gui_label(kd, _("P1"),  0, GUI_SW * l1, gui_red, gui_wht);
143                 if (p2) gui_label(kd, _("P2"),  0, GUI_SW * l2, gui_grn, gui_wht);
144                 if (p3) gui_label(kd, _("P3"),  0, GUI_SW * l3, gui_blu, gui_wht);
145                 if (p4) gui_label(kd, _("P4"),  0, GUI_SW * l4, gui_yel, gui_wht);
146             }
147         }
148
149         gui_layout(id, 0, 0);
150     }
151
152     return id;
153 }
154
155 /*---------------------------------------------------------------------------*/
156
157 static int shared_stick_basic(int id, int a, float v, int bump)
158 {
159     int jd;
160
161     if ((jd = gui_stick(id, a, v, bump)))
162         gui_pulse(jd, 1.2f);
163
164     return jd;
165 }
166
167 static void shared_stick(int id, int a, float v, int bump)
168 {
169     shared_stick_basic(id, a, v, bump);
170 }
171
172 /*---------------------------------------------------------------------------*/
173
174 #define TITLE_PLAY 1
175 #define TITLE_CONF 2
176 #define TITLE_EXIT 3
177
178 static int title_action(int i)
179 {
180     audio_play(AUD_MENU, 1.0f);
181
182     switch (i)
183     {
184     case TITLE_PLAY: return goto_state(&st_course);
185     case TITLE_CONF: return goto_state(&st_conf);
186     case TITLE_EXIT: return 0;
187     }
188     return 1;
189 }
190
191 static int title_enter(struct state *st, struct state *prev)
192 {
193     int id, jd, kd;
194
195     /* Build the title GUI. */
196
197     if ((id = gui_vstack(0)))
198     {
199         gui_label(id, "Neverputt", GUI_LRG, GUI_ALL, 0, 0);
200         gui_space(id);
201
202         if ((jd = gui_harray(id)))
203         {
204             gui_filler(jd);
205
206             if ((kd = gui_varray(jd)))
207             {
208                 gui_start(kd, sgettext("menu^Play"),    GUI_MED, TITLE_PLAY, 1);
209                 gui_state(kd, sgettext("menu^Options"), GUI_MED, TITLE_CONF, 0);
210                 gui_state(kd, sgettext("menu^Exit"),    GUI_MED, TITLE_EXIT, 0);
211             }
212
213             gui_filler(jd);
214         }
215         gui_layout(id, 0, 0);
216     }
217
218     course_init();
219     course_rand();
220
221     return id;
222 }
223
224 static void title_leave(struct state *st, struct state *next, int id)
225 {
226     gui_delete(id);
227 }
228
229 static void title_paint(int id, float t)
230 {
231     game_draw(0, t);
232     gui_paint(id);
233 }
234
235 static void title_timer(int id, float dt)
236 {
237     float g[3] = { 0.f, 0.f, 0.f };
238
239     game_step(g, dt);
240     game_set_fly(fcosf(time_state() / 10.f));
241
242     gui_timer(id, dt);
243 }
244
245 static void title_point(int id, int x, int y, int dx, int dy)
246 {
247     gui_pulse(gui_point(id, x, y), 1.2f);
248 }
249
250 static int title_click(int b, int d)
251 {
252     return d && b == SDL_BUTTON_LEFT ? title_action(gui_token(gui_click())) : 1;
253 }
254
255 static int title_buttn(int b, int d)
256 {
257     if (d)
258     {
259         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
260             return title_action(gui_token(gui_click()));
261         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
262             return title_action(TITLE_EXIT);
263     }
264     return 1;
265 }
266
267 /*---------------------------------------------------------------------------*/
268
269 static int desc_id;
270 static int shot_id;
271
272 #define COURSE_BACK -1
273
274 static int course_action(int i)
275 {
276     if (course_exists(i))
277     {
278         course_goto(i);
279         goto_state(&st_party);
280     }
281     if (i == COURSE_BACK)
282         goto_state(&st_title);
283
284     return 1;
285 }
286
287 static int comp_size(int n, int s)
288 {
289     return n <= s * s ? s : comp_size(n, s + 1);
290 }
291
292 static int comp_cols(int n)
293 {
294     return comp_size(n, 1);
295 }
296
297 static int comp_rows(int n)
298 {
299     int s = comp_size(n, 1);
300
301     return n <= s * (s - 1) ? s - 1 : s;
302 }
303
304 static int course_enter(struct state *st, struct state *prev)
305 {
306     int w = config_get_d(CONFIG_WIDTH);
307     int h = config_get_d(CONFIG_HEIGHT);
308
309     int id, jd, kd, ld, md;
310
311     int i, j, r, c, n;
312
313     n = course_count();
314
315     r = comp_rows(n);
316     c = comp_cols(n);
317
318     if ((id = gui_vstack(0)))
319     {
320         gui_label(id, _("Select Course"), GUI_MED, GUI_ALL, 0, 0);
321         gui_space(id);
322
323         if ((jd = gui_hstack(id)))
324         {
325             shot_id = gui_image(jd, course_shot(0), w / 3, h / 3);
326
327             gui_filler(jd);
328
329             if ((kd = gui_varray(jd)))
330             {
331                 for(i = 0; i < r; i++)
332                 {
333                     if ((ld = gui_harray(kd)))
334                     {
335                         for (j = c - 1; j >= 0; j--)
336                         {
337                             int k = i * c + j;
338
339                             if (k < n)
340                             {
341                                 md = gui_image(ld, course_shot(k),
342                                                w / 3 / c, h / 3 / r);
343                                 gui_active(md, k, 0);
344
345                                 if (k == 0)
346                                     gui_focus(md);
347                             }
348                             else
349                                 gui_space(ld);
350                         }
351                     }
352                 }
353             }
354         }
355
356         gui_space(id);
357         desc_id = gui_multi(id, _(course_desc(0)), GUI_SML, GUI_ALL, gui_yel, gui_wht);
358         gui_space(id);
359
360         if ((jd = gui_hstack(id)))
361         {
362             gui_filler(jd);
363             gui_state(jd, _("Back"), GUI_SML, COURSE_BACK, 0);
364         }
365
366         gui_layout(id, 0, 0);
367     }
368
369     audio_music_fade_to(0.5f, "bgm/inter.ogg");
370
371     return id;
372 }
373
374 static void course_leave(struct state *st, struct state *next, int id)
375 {
376     gui_delete(id);
377 }
378
379 static void course_paint(int id, float t)
380 {
381     game_draw(0, t);
382     gui_paint(id);
383 }
384
385 static void course_timer(int id, float dt)
386 {
387     gui_timer(id, dt);
388 }
389
390 static void course_point(int id, int x, int y, int dx, int dy)
391 {
392     int jd;
393
394     if ((jd = gui_point(id, x, y)))
395     {
396         int i = gui_token(jd);
397
398         if (course_exists(i))
399         {
400             gui_set_image(shot_id, course_shot(i));
401             gui_set_multi(desc_id, _(course_desc(i)));
402         }
403         gui_pulse(jd, 1.2f);
404     }
405 }
406
407 static void course_stick(int id, int a, float v, int bump)
408 {
409     int jd;
410
411     if ((jd = shared_stick_basic(id, a, v, bump)))
412     {
413         int i = gui_token(jd);
414
415         if (course_exists(i))
416         {
417             gui_set_image(shot_id, course_shot(i));
418             gui_set_multi(desc_id, _(course_desc(i)));
419         }
420         gui_pulse(jd, 1.2f);
421     }
422 }
423
424 static int course_click(int b, int d)
425 {
426     return d && b == SDL_BUTTON_LEFT ? course_action(gui_token(gui_click())) : 1;
427 }
428
429 static int course_buttn(int b, int d)
430 {
431     if (d)
432     {
433         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
434             return course_action(gui_token(gui_click()));
435         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
436             return course_action(COURSE_BACK);
437     }
438     return 1;
439 }
440
441 /*---------------------------------------------------------------------------*/
442
443 #define PARTY_T 0
444 #define PARTY_1 1
445 #define PARTY_2 2
446 #define PARTY_3 3
447 #define PARTY_4 4
448 #define PARTY_B 5
449
450 static int party_action(int i)
451 {
452     switch (i)
453     {
454     case PARTY_1:
455         audio_play(AUD_MENU, 1.f);
456         if (hole_goto(1, 1))
457             goto_state(&st_next);
458         break;
459     case PARTY_2:
460         audio_play(AUD_MENU, 1.f);
461         if (hole_goto(1, 2))
462             goto_state(&st_next);
463         break;
464     case PARTY_3:
465         audio_play(AUD_MENU, 1.f);
466         if (hole_goto(1, 3))
467             goto_state(&st_next);
468         break;
469     case PARTY_4:
470         audio_play(AUD_MENU, 1.f);
471         if (hole_goto(1, 4))
472             goto_state(&st_next);
473         break;
474     case PARTY_B:
475         audio_play(AUD_MENU, 1.f);
476         goto_state(&st_course);
477         break;
478     }
479     return 1;
480 }
481
482 static int party_enter(struct state *st, struct state *prev)
483 {
484     int id, jd;
485
486     if ((id = gui_vstack(0)))
487     {
488         gui_label(id, _("Players?"), GUI_MED, GUI_ALL, 0, 0);
489         gui_space(id);
490
491         if ((jd = gui_harray(id)))
492         {
493             int p4 = gui_state(jd, "4", GUI_LRG, PARTY_4, 0);
494             int p3 = gui_state(jd, "3", GUI_LRG, PARTY_3, 0);
495             int p2 = gui_state(jd, "2", GUI_LRG, PARTY_2, 0);
496             int p1 = gui_state(jd, "1", GUI_LRG, PARTY_1, 0);
497
498             gui_set_color(p1, gui_red, gui_wht);
499             gui_set_color(p2, gui_grn, gui_wht);
500             gui_set_color(p3, gui_blu, gui_wht);
501             gui_set_color(p4, gui_yel, gui_wht);
502
503             gui_focus(p1);
504         }
505
506         gui_space(id);
507
508         if ((jd = gui_hstack(id)))
509         {
510             gui_filler(jd);
511             gui_state(jd, _("Back"), GUI_SML, PARTY_B, 0);
512         }
513
514         gui_layout(id, 0, 0);
515     }
516
517     return id;
518 }
519
520 static void party_leave(struct state *st, struct state *next, int id)
521 {
522     gui_delete(id);
523 }
524
525 static void party_paint(int id, float t)
526 {
527     game_draw(0, t);
528     gui_paint(id);
529 }
530
531 static void party_timer(int id, float dt)
532 {
533     gui_timer(id, dt);
534 }
535
536 static void party_point(int id, int x, int y, int dx, int dy)
537 {
538     gui_pulse(gui_point(id, x, y), 1.2f);
539 }
540
541 static int party_click(int b, int d)
542 {
543     return d && b == SDL_BUTTON_LEFT ? party_action(gui_token(gui_click())) : 1;
544 }
545
546 static int party_buttn(int b, int d)
547 {
548     if (d)
549     {
550         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
551             return party_action(gui_token(gui_click()));
552         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
553             return party_action(PARTY_B);
554     }
555     return 1;
556 }
557
558 /*---------------------------------------------------------------------------*/
559
560 static int paused = 0;
561
562 static struct state *st_continue;
563 static struct state *st_quit;
564
565 #define PAUSE_CONTINUE 1
566 #define PAUSE_QUIT     2
567
568 int goto_pause(struct state *s, int e)
569 {
570     if (curr_state() == &st_pause)
571         return 1;
572
573     if (e && !config_tst_d(CONFIG_KEY_PAUSE, SDLK_ESCAPE))
574         return goto_state(s);
575
576     st_continue = curr_state();
577     st_quit = s;
578     paused = 1;
579
580     return goto_state(&st_pause);
581 }
582
583 static int pause_action(int i)
584 {
585     SDL_PauseAudio(0);
586     audio_play(AUD_MENU, 1.0f);
587
588     switch(i)
589     {
590     case PAUSE_CONTINUE:
591         return goto_state(st_continue ? st_continue : &st_title);
592
593     case PAUSE_QUIT:
594         return goto_state(st_quit);
595     }
596     return 1;
597 }
598
599 static int pause_enter(struct state *st, struct state *prev)
600 {
601     int id, jd, td;
602
603     audio_music_fade_out(0.2f);
604
605     if ((id = gui_vstack(0)))
606     {
607         td = gui_label(id, _("Paused"), GUI_LRG, GUI_ALL, 0, 0);
608         gui_space(id);
609
610         if ((jd = gui_harray(id)))
611         {
612             gui_state(jd, _("Quit"), GUI_SML, PAUSE_QUIT, 0);
613             gui_start(jd, _("Continue"), GUI_SML, PAUSE_CONTINUE, 1);
614         }
615
616         gui_pulse(td, 1.2f);
617         gui_layout(id, 0, 0);
618     }
619
620     SDL_PauseAudio(1);
621     hud_init();
622     return id;
623 }
624
625 static void pause_leave(struct state *st, struct state *next, int id)
626 {
627     gui_delete(id);
628     hud_free();
629     audio_music_fade_in(0.5f);
630 }
631
632 static void pause_paint(int id, float t)
633 {
634     game_draw(0, t);
635     gui_paint(id);
636     hud_paint();
637 }
638
639 static void pause_timer(int id, float dt)
640 {
641     gui_timer(id, dt);
642 }
643
644 static void pause_point(int id, int x, int y, int dx, int dy)
645 {
646     gui_pulse(gui_point(id, x, y), 1.2f);
647 }
648
649 static int pause_click(int b, int d)
650 {
651     return d && b == SDL_BUTTON_LEFT ? pause_action(gui_token(gui_click())) : 1;
652 }
653
654 static int pause_keybd(int c, int d)
655 {
656     if (d && config_tst_d(CONFIG_KEY_PAUSE, c))
657         return pause_action(PAUSE_CONTINUE);
658     return 1;
659 }
660
661 static int pause_buttn(int b, int d)
662 {
663     if (d)
664     {
665         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
666             return pause_action(gui_token(gui_click()));
667         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
668             return pause_action(PAUSE_CONTINUE);
669     }
670     return 1;
671 }
672
673 /*---------------------------------------------------------------------------*/
674
675 static int shared_keybd(int c, int d)
676 {
677     if (d)
678     {
679         if (config_tst_d(CONFIG_KEY_PAUSE, c))
680             return goto_pause(&st_over, 0);
681     }
682     return 1;
683 }
684
685 /*---------------------------------------------------------------------------*/
686
687 static int num = 0;
688
689 static int next_enter(struct state *st, struct state *prev)
690 {
691     int id;
692     char str[MAXSTR];
693
694     sprintf(str, _("Hole %02d"), curr_hole());
695
696     if ((id = gui_vstack(0)))
697     {
698         gui_label(id, str, GUI_MED, GUI_ALL, 0, 0);
699         gui_space(id);
700
701         gui_label(id, _("Player"), GUI_SML, GUI_TOP, 0, 0);
702
703         switch (curr_player())
704         {
705         case 1:
706             gui_label(id, "1", GUI_LRG, GUI_BOT, gui_red, gui_wht);
707             if (curr_party() > 1) audio_play(AUD_PLAYER1, 1.f);
708             break;
709         case 2:
710             gui_label(id, "2", GUI_LRG, GUI_BOT, gui_grn, gui_wht);
711             if (curr_party() > 1) audio_play(AUD_PLAYER2, 1.f);
712             break;
713         case 3:
714             gui_label(id, "3", GUI_LRG, GUI_BOT, gui_blu, gui_wht);
715             if (curr_party() > 1) audio_play(AUD_PLAYER3, 1.f);
716             break;
717         case 4:
718             gui_label(id, "4", GUI_LRG, GUI_BOT, gui_yel, gui_wht);
719             if (curr_party() > 1) audio_play(AUD_PLAYER4, 1.f);
720             break;
721         }
722         gui_layout(id, 0, 0);
723     }
724
725     hud_init();
726     game_set_fly(1.f);
727
728     if (paused)
729         paused = 0;
730
731     return id;
732 }
733
734 static void next_leave(struct state *st, struct state *next, int id)
735 {
736     hud_free();
737     gui_delete(id);
738 }
739
740 static void next_paint(int id, float t)
741 {
742     game_draw(0, t);
743     hud_paint();
744     gui_paint(id);
745 }
746
747 static void next_timer(int id, float dt)
748 {
749     gui_timer(id, dt);
750 }
751
752 static void next_point(int id, int x, int y, int dx, int dy)
753 {
754     gui_pulse(gui_point(id, x, y), 1.2f);
755 }
756
757 static int next_click(int b, int d)
758 {
759     return (d && b == SDL_BUTTON_LEFT) ? goto_state(&st_flyby) : 1;
760 }
761
762 static int next_keybd(int c, int d)
763 {
764     if (d)
765     {
766         if (c == SDLK_F12)
767             return goto_state(&st_poser);
768         if (config_tst_d(CONFIG_KEY_PAUSE, c))
769             return goto_pause(&st_over, 0);
770         if ('0' <= c && c <= '9')
771             num = num * 10 + c - '0';
772     }
773     return 1;
774 }
775
776 static int next_buttn(int b, int d)
777 {
778     if (d)
779     {
780         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
781         {
782             if (num > 0 && hole_goto(num, -1))
783             {
784                 num = 0;
785                 return goto_state(&st_next);
786             }
787             return goto_state(&st_flyby);
788         }
789         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
790             return goto_pause(&st_over, 1);
791     }
792     return 1;
793 }
794
795 /*---------------------------------------------------------------------------*/
796
797 static int poser_enter(struct state *st, struct state *prev)
798 {
799     game_set_fly(-1.f);
800     return 0;
801 }
802
803 static void poser_paint(int id, float t)
804 {
805     game_draw(1, t);
806 }
807
808 static int poser_buttn(int b, int d)
809 {
810     if (d)
811     {
812         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
813             return goto_state(&st_next);
814         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
815             return goto_state(&st_next);
816     }
817     return 1;
818 }
819
820 /*---------------------------------------------------------------------------*/
821
822 static int flyby_enter(struct state *st, struct state *prev)
823 {
824     if (paused)
825         paused = 0;
826     else
827         hud_init();
828
829     return 0;
830 }
831
832 static void flyby_leave(struct state *st, struct state *next, int id)
833 {
834     hud_free();
835 }
836
837 static void flyby_paint(int id, float t)
838 {
839     game_draw(0, t);
840     hud_paint();
841 }
842
843 static void flyby_timer(int id, float dt)
844 {
845     float t = time_state();
846
847     if (dt > 0.f && t > 1.f)
848         goto_state(&st_stroke);
849     else
850         game_set_fly(1.f - t);
851
852     gui_timer(id, dt);
853 }
854
855 static int flyby_click(int b, int d)
856 {
857     if (d && b == SDL_BUTTON_LEFT)
858     {
859         game_set_fly(0.f);
860         return goto_state(&st_stroke);
861     }
862     return 1;
863 }
864
865 static int flyby_buttn(int b, int d)
866 {
867     if (d)
868     {
869         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
870         {
871             game_set_fly(0.f);
872             return goto_state(&st_stroke);
873         }
874         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
875             return goto_pause(&st_over, 1);
876     }
877     return 1;
878 }
879
880 /*---------------------------------------------------------------------------*/
881
882 #define TOUCH_SENSITIVITY       20
883 #define LONG_PRESS_TIME 1000 /* one second */
884 #define DOUBLE_TAP_TIME 500
885 static enum {
886     BTN_CLEAR,
887     BTN_PRESS1,
888     BTN_CLICKED,
889     BTN_PRESS2,
890     BTN_DRAGGING
891 } button_state = BTN_CLEAR;
892 static int button_pressed_x = 0;
893 static int button_pressed_y = 0;
894 static Uint32 button_time = 0;
895
896 static int stroke_rotate = 0;
897 static int stroke_mag    = 0;
898
899 static int stroke_enter(struct state *st, struct state *prev)
900 {
901     hud_init();
902     game_clr_mag();
903     config_set_d(CONFIG_CAMERA, 2);
904     video_set_grab(!paused);
905
906     if (paused)
907         paused = 0;
908
909     return 0;
910 }
911
912 static void stroke_leave(struct state *st, struct state *next, int id)
913 {
914     hud_free();
915     video_clr_grab();
916     config_set_d(CONFIG_CAMERA, 0);
917 }
918
919 static void stroke_paint(int id, float t)
920 {
921     game_draw(0, t);
922     hud_paint();
923 }
924
925 static void stroke_timer(int id, float dt)
926 {
927     float g[3] = { 0.f, 0.f, 0.f };
928
929     float k;
930
931     if (button_state == BTN_CLICKED)
932     {
933         int elapsed = SDL_GetTicks() - button_time;
934         if (elapsed > DOUBLE_TAP_TIME)
935         {
936             /* it was a single click: start the simulation */
937             goto_state(&st_roll);
938             button_state = BTN_CLEAR;
939             return;
940         }
941     }
942
943     if (SDL_GetModState() & KMOD_SHIFT ||
944         (joystick && SDL_JoystickGetButton(joystick,
945                                            config_get_d(CONFIG_JOYSTICK_BUTTON_B))))
946         k = 0.25;
947     else
948         k = 1.0;
949
950     game_set_rot(stroke_rotate * k);
951     game_set_mag(stroke_mag * k);
952
953     game_update_view(dt);
954     game_step(g, dt);
955 }
956
957 static void stroke_point(int id, int x, int y, int dx, int dy)
958 {
959     if (button_state == BTN_PRESS1 ||
960         button_state == BTN_PRESS2)
961     {
962         int duration = SDL_GetTicks() - button_time;
963         /* check how much we've moved */
964         if (abs(x - button_pressed_x) > TOUCH_SENSITIVITY ||
965             abs(y - button_pressed_y) > TOUCH_SENSITIVITY ||
966             duration > LONG_PRESS_TIME)
967             button_state = BTN_DRAGGING;
968     }
969     if (button_state != BTN_DRAGGING) return;
970
971     game_set_rot(dx);
972     game_set_mag(dy);
973 }
974
975 static void stroke_stick(int id, int a, float v, int bump)
976 {
977     if (config_tst_d(CONFIG_JOYSTICK_AXIS_X, a))
978         stroke_rotate = 6 * v;
979     else if (config_tst_d(CONFIG_JOYSTICK_AXIS_Y, a))
980         stroke_mag = -6 * v;
981 }
982
983 static int stroke_click(int b, int d)
984 {
985     int ret = 1;
986     Uint32 current_time;
987
988     current_time = SDL_GetTicks();
989     if (d)
990     {
991         int y;
992         SDL_GetMouseState(&button_pressed_x, &y);
993         button_pressed_y = -y + config_get_d(CONFIG_HEIGHT);
994         button_time = current_time;
995         button_state = (button_state == BTN_CLICKED) ? BTN_PRESS2 : BTN_PRESS1;
996     }
997     else
998     {
999         /* is it a double click? */
1000         int duration = current_time - button_time;
1001         if (button_state == BTN_PRESS2)
1002         {
1003             button_state = BTN_CLEAR;
1004             if (duration < DOUBLE_TAP_TIME)
1005                 ret = goto_pause(&st_over, 1);
1006         }
1007         else
1008         {
1009             if (button_state == BTN_PRESS1 && duration < LONG_PRESS_TIME)
1010                 button_state = BTN_CLICKED;
1011             else
1012                 button_state = BTN_CLEAR;
1013         }
1014     }
1015     return ret;
1016 }
1017
1018 static int stroke_buttn(int b, int d)
1019 {
1020     if (d)
1021     {
1022         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1023             return goto_state(&st_roll);
1024         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1025             return goto_pause(&st_over, 1);
1026     }
1027     return 1;
1028 }
1029
1030 /*---------------------------------------------------------------------------*/
1031
1032 static int roll_enter(struct state *st, struct state *prev)
1033 {
1034     hud_init();
1035
1036     if (paused)
1037         paused = 0;
1038     else
1039         game_putt();
1040
1041     return 0;
1042 }
1043
1044 static void roll_leave(struct state *st, struct state *next, int id)
1045 {
1046     hud_free();
1047 }
1048
1049 static void roll_paint(int id, float t)
1050 {
1051     game_draw(0, t);
1052     hud_paint();
1053 }
1054
1055 static void roll_timer(int id, float dt)
1056 {
1057     float g[3] = { 0.0f, -9.8f, 0.0f };
1058
1059     switch (game_step(g, dt))
1060     {
1061     case GAME_STOP: goto_state(&st_stop); break;
1062     case GAME_GOAL: goto_state(&st_goal); break;
1063     case GAME_FALL: goto_state(&st_fall); break;
1064     }
1065 }
1066
1067 static int roll_buttn(int b, int d)
1068 {
1069     if (d)
1070     {
1071         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1072             return goto_pause(&st_over, 1);
1073     }
1074     return 1;
1075 }
1076
1077 /*---------------------------------------------------------------------------*/
1078
1079 static int goal_enter(struct state *st, struct state *prev)
1080 {
1081     int id;
1082
1083     if ((id = gui_label(0, _("It's In!"), GUI_MED, GUI_ALL, gui_grn, gui_grn)))
1084         gui_layout(id, 0, 0);
1085
1086     if (paused)
1087         paused = 0;
1088     else
1089         hole_goal();
1090
1091     hud_init();
1092
1093     return id;
1094 }
1095
1096 static void goal_leave(struct state *st, struct state *next, int id)
1097 {
1098     gui_delete(id);
1099     hud_free();
1100 }
1101
1102 static void goal_paint(int id, float t)
1103 {
1104     game_draw(0, t);
1105     gui_paint(id);
1106     hud_paint();
1107 }
1108
1109 static void goal_timer(int id, float dt)
1110 {
1111     if (time_state() > 3)
1112     {
1113         if (hole_next())
1114             goto_state(&st_next);
1115         else
1116             goto_state(&st_score);
1117     }
1118 }
1119
1120 static int goal_click(int b, int d)
1121 {
1122     if (b == SDL_BUTTON_LEFT && d == 1)
1123     {
1124         if (hole_next())
1125             goto_state(&st_next);
1126         else
1127             goto_state(&st_score);
1128     }
1129     return 1;
1130 }
1131
1132 static int goal_buttn(int b, int d)
1133 {
1134     if (d)
1135     {
1136         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1137         {
1138             if (hole_next())
1139                 goto_state(&st_next);
1140             else
1141                 goto_state(&st_score);
1142         }
1143         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1144             return goto_pause(&st_over, 1);
1145     }
1146     return 1;
1147 }
1148
1149 /*---------------------------------------------------------------------------*/
1150
1151 static int stop_enter(struct state *st, struct state *prev)
1152 {
1153     if (paused)
1154         paused = 0;
1155     else
1156         hole_stop();
1157
1158     hud_init();
1159
1160     return 0;
1161 }
1162
1163 static void stop_leave(struct state *st, struct state *next, int id)
1164 {
1165     hud_free();
1166 }
1167
1168 static void stop_paint(int id, float t)
1169 {
1170     game_draw(0, t);
1171     hud_paint();
1172 }
1173
1174 static void stop_timer(int id, float dt)
1175 {
1176     float g[3] = { 0.f, 0.f, 0.f };
1177
1178     game_update_view(dt);
1179     game_step(g, dt);
1180
1181     if (time_state() > 1)
1182     {
1183         if (hole_next())
1184             goto_state(&st_next);
1185         else
1186             goto_state(&st_score);
1187     }
1188 }
1189
1190 static int stop_click(int b, int d)
1191 {
1192     if (b == SDL_BUTTON_LEFT && d == 1)
1193     {
1194         if (hole_next())
1195             goto_state(&st_next);
1196         else
1197             goto_state(&st_score);
1198     }
1199     return 1;
1200 }
1201
1202 static int stop_buttn(int b, int d)
1203 {
1204     if (d)
1205     {
1206         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1207         {
1208             if (hole_next())
1209                 goto_state(&st_next);
1210             else
1211                 goto_state(&st_score);
1212         }
1213         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1214             return goto_pause(&st_over, 1);
1215     }
1216     return 1;
1217 }
1218
1219 /*---------------------------------------------------------------------------*/
1220
1221 static int fall_enter(struct state *st, struct state *prev)
1222 {
1223     int id;
1224
1225     if ((id = gui_label(0, _("1 Stroke Penalty"), GUI_MED, GUI_ALL, gui_blk, gui_red)))
1226         gui_layout(id, 0, 0);
1227
1228     if (paused)
1229         paused = 0;
1230     else
1231     {
1232         hole_fall();
1233 /*        game_draw(0);*/ /*TODO: is this call ok? */  /* No, it's not. */
1234     }
1235
1236     hud_init();
1237
1238     return id;
1239 }
1240
1241 static void fall_leave(struct state *st, struct state *next, int id)
1242 {
1243     gui_delete(id);
1244     hud_free();
1245 }
1246
1247 static void fall_paint(int id, float t)
1248 {
1249     game_draw(0, t);
1250     gui_paint(id);
1251     hud_paint();
1252 }
1253
1254 static void fall_timer(int id, float dt)
1255 {
1256     if (time_state() > 3)
1257     {
1258         if (hole_next())
1259             goto_state(&st_next);
1260         else
1261             goto_state(&st_score);
1262     }
1263 }
1264
1265 static int fall_click(int b, int d)
1266 {
1267     if (b == SDL_BUTTON_LEFT && d == 1)
1268     {
1269         if (hole_next())
1270             goto_state(&st_next);
1271         else
1272             goto_state(&st_score);
1273     }
1274     return 1;
1275 }
1276
1277 static int fall_buttn(int b, int d)
1278 {
1279     if (d)
1280     {
1281         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1282         {
1283             if (hole_next())
1284                 goto_state(&st_next);
1285             else
1286                 goto_state(&st_score);
1287         }
1288         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1289             return goto_pause(&st_over, 1);
1290     }
1291     return 1;
1292 }
1293
1294 /*---------------------------------------------------------------------------*/
1295
1296 static int score_enter(struct state *st, struct state *prev)
1297 {
1298     audio_music_fade_out(2.f);
1299
1300     if (paused)
1301         paused = 0;
1302
1303     return score_card(_("Scores"), gui_yel, gui_red);
1304 }
1305
1306 static void score_leave(struct state *st, struct state *next, int id)
1307 {
1308     gui_delete(id);
1309 }
1310
1311 static void score_paint(int id, float t)
1312 {
1313     game_draw(0, t);
1314     gui_paint(id);
1315 }
1316
1317 static void score_timer(int id, float dt)
1318 {
1319     gui_timer(id, dt);
1320 }
1321
1322 static int score_click(int b, int d)
1323 {
1324     if (b == SDL_BUTTON_LEFT && d == 1)
1325     {
1326         if (hole_move())
1327             return goto_state(&st_next);
1328         else
1329             return goto_state(&st_title);
1330     }
1331     return 1;
1332 }
1333
1334 static int score_buttn(int b, int d)
1335 {
1336     if (d)
1337     {
1338         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1339         {
1340             if (hole_move())
1341                 goto_state(&st_next);
1342             else
1343                 goto_state(&st_score);
1344         }
1345         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1346             return goto_pause(&st_over, 1);
1347     }
1348     return 1;
1349 }
1350
1351 /*---------------------------------------------------------------------------*/
1352
1353 static int over_enter(struct state *st, struct state *prev)
1354 {
1355     audio_music_fade_out(2.f);
1356     return score_card(_("Final Scores"), gui_yel, gui_red);
1357 }
1358
1359 static void over_leave(struct state *st, struct state *next, int id)
1360 {
1361     gui_delete(id);
1362 }
1363
1364 static void over_paint(int id, float t)
1365 {
1366     game_draw(0, t);
1367     gui_paint(id);
1368 }
1369
1370 static void over_timer(int id, float dt)
1371 {
1372     gui_timer(id, dt);
1373 }
1374
1375 static int over_click(int b, int d)
1376 {
1377     return (d && b == SDL_BUTTON_LEFT) ? goto_state(&st_title) : 1;
1378 }
1379
1380 static int over_buttn(int b, int d)
1381 {
1382     if (d)
1383     {
1384         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
1385             return goto_state(&st_title);
1386         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
1387             return goto_state(&st_title);
1388     }
1389     return 1;
1390 }
1391
1392 /*---------------------------------------------------------------------------*/
1393
1394 struct state st_title = {
1395     title_enter,
1396     title_leave,
1397     title_paint,
1398     title_timer,
1399     title_point,
1400     shared_stick,
1401     NULL,
1402     title_click,
1403     NULL,
1404     title_buttn,
1405     NULL
1406 };
1407
1408 struct state st_course = {
1409     course_enter,
1410     course_leave,
1411     course_paint,
1412     course_timer,
1413     course_point,
1414     course_stick,
1415     NULL,
1416     course_click,
1417     NULL,
1418     course_buttn,
1419     NULL
1420 };
1421
1422 struct state st_party = {
1423     party_enter,
1424     party_leave,
1425     party_paint,
1426     party_timer,
1427     party_point,
1428     shared_stick,
1429     NULL,
1430     party_click,
1431     NULL,
1432     party_buttn,
1433     NULL
1434 };
1435
1436 struct state st_next = {
1437     next_enter,
1438     next_leave,
1439     next_paint,
1440     next_timer,
1441     next_point,
1442     shared_stick,
1443     NULL,
1444     next_click,
1445     next_keybd,
1446     next_buttn,
1447     NULL
1448 };
1449
1450 struct state st_poser = {
1451     poser_enter,
1452     NULL,
1453     poser_paint,
1454     NULL,
1455     NULL,
1456     NULL,
1457     NULL,
1458     NULL,
1459     NULL,
1460     poser_buttn,
1461     NULL
1462 };
1463
1464 struct state st_flyby = {
1465     flyby_enter,
1466     flyby_leave,
1467     flyby_paint,
1468     flyby_timer,
1469     NULL,
1470     NULL,
1471     NULL,
1472     flyby_click,
1473     shared_keybd,
1474     flyby_buttn,
1475     NULL
1476 };
1477
1478 struct state st_stroke = {
1479     stroke_enter,
1480     stroke_leave,
1481     stroke_paint,
1482     stroke_timer,
1483     stroke_point,
1484     stroke_stick,
1485     NULL,
1486     stroke_click,
1487     shared_keybd,
1488     stroke_buttn,
1489     NULL
1490 };
1491
1492 struct state st_roll = {
1493     roll_enter,
1494     roll_leave,
1495     roll_paint,
1496     roll_timer,
1497     NULL,
1498     NULL,
1499     NULL,
1500     NULL,
1501     shared_keybd,
1502     roll_buttn,
1503     NULL
1504 };
1505
1506 struct state st_goal = {
1507     goal_enter,
1508     goal_leave,
1509     goal_paint,
1510     goal_timer,
1511     NULL,
1512     NULL,
1513     NULL,
1514     goal_click,
1515     shared_keybd,
1516     goal_buttn,
1517     NULL
1518 };
1519
1520 struct state st_stop = {
1521     stop_enter,
1522     stop_leave,
1523     stop_paint,
1524     stop_timer,
1525     NULL,
1526     NULL,
1527     NULL,
1528     stop_click,
1529     shared_keybd,
1530     stop_buttn,
1531     NULL
1532 };
1533
1534 struct state st_fall = {
1535     fall_enter,
1536     fall_leave,
1537     fall_paint,
1538     fall_timer,
1539     NULL,
1540     NULL,
1541     NULL,
1542     fall_click,
1543     shared_keybd,
1544     fall_buttn,
1545     NULL
1546 };
1547
1548 struct state st_score = {
1549     score_enter,
1550     score_leave,
1551     score_paint,
1552     score_timer,
1553     NULL,
1554     NULL,
1555     NULL,
1556     score_click,
1557     shared_keybd,
1558     score_buttn,
1559     NULL
1560 };
1561
1562 struct state st_over = {
1563     over_enter,
1564     over_leave,
1565     over_paint,
1566     over_timer,
1567     NULL,
1568     NULL,
1569     NULL,
1570     over_click,
1571     NULL,
1572     over_buttn,
1573     NULL
1574 };
1575
1576 struct state st_pause = {
1577     pause_enter,
1578     pause_leave,
1579     pause_paint,
1580     pause_timer,
1581     pause_point,
1582     shared_stick,
1583     NULL,
1584     pause_click,
1585     pause_keybd,
1586     pause_buttn,
1587     NULL
1588 };