Use mktime() to normalize the computed local time structure. HACK
[neverball] / ball / levels.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERBALL 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 #include <assert.h>
19
20 #include "level.h"
21 #include "levels.h"
22 #include "game.h"
23 #include "demo.h"
24 #include "audio.h"
25 #include "config.h"
26 #include "set.h"
27
28 /*---------------------------------------------------------------------------*/
29
30 /* The level currently playing */
31 static struct level_game current_level_game;
32
33 /*---------------------------------------------------------------------------*/
34
35 int level_replay(const char *filename)
36 {
37     return demo_replay_init(filename, &current_level_game);
38 }
39
40 int level_play_go(void)
41 /* Start to play the current level */
42 {
43     struct level_game *lg = &current_level_game;
44     const struct level *l = lg->level;
45     int mode = lg->mode;
46
47     assert(l != NULL);
48
49     lg->goal = (mode == MODE_PRACTICE) ? 0 : l->goal;
50     lg->time = (mode == MODE_PRACTICE) ? 0 : l->time;
51
52     /* clear other fields */
53     lg->state = GAME_NONE;
54     lg->coins = 0;
55     lg->timer = lg->time;
56     lg->coin_rank = lg->goal_rank = lg->time_rank =
57         lg->score_rank = lg->times_rank = 3;
58     lg->win = lg->dead = lg->unlock = 0;
59     lg->next_level = NULL;
60
61     return demo_play_init(USER_REPLAY_FILE, l, lg);
62 }
63
64 /* Prepare to play a level sequence from the `i'th level */
65
66 void level_play(const struct level *l, int m)
67 {
68     struct level_game *lg = &current_level_game;
69
70     memset(lg, 0, sizeof (struct level_game));
71
72     lg->mode  = m;
73     lg->level = l;
74     lg->balls = 3;
75 }
76
77 /*---------------------------------------------------------------------------*/
78
79 const struct level_game *curr_lg(void)
80 {
81     return &current_level_game;
82 }
83
84 int count_extra_balls(int old_score, int coins)
85 {
86     int modulo = old_score % 100;
87     int sum    = modulo + coins;
88     return sum / 100;
89 }
90
91 /* Stop the current playing level */
92
93 void level_stop(int state, int state_value, int clock, int coins)
94 {
95     struct level_game *lg = &current_level_game;
96     int mode = lg->mode;
97     int timer = (mode == MODE_PRACTICE
98                  || mode == MODE_SINGLE) ? clock : lg->time - clock;
99
100     lg->state = state;
101     lg->coins = coins;
102     lg->timer = timer;
103     lg->state_value = state_value;
104
105     /* Performs challenge mode opperations */
106     if (mode == MODE_CHALLENGE)
107     {
108         /* sum time */
109         lg->times += timer;
110
111         /* sum coins an earn extra balls */
112         if (state == GAME_GOAL || state == GAME_SPEC || lg->level->is_bonus)
113         {
114             lg->balls += count_extra_balls(lg->score, coins);
115             lg->score += coins;
116         }
117
118         /* lose ball and game */
119         else                    /* if ((state == GAME_TIME || state == GAME_FALL) && !lg->level->is_bonus) */
120         {
121             lg->dead = (lg->balls <= 0);
122             lg->balls--;
123         }
124     }
125
126     /* Update high-scores and next level */
127     set_finish_level(lg, config_simple_get_s(CONFIG_PLAYER));
128
129     /* stop demo recording */
130     demo_play_stop(lg);
131 }
132
133 void level_next(void)
134 {
135     struct level_game *lg = &current_level_game;
136     lg->level = lg->next_level;
137 }
138
139 void level_update_player_name(void)
140 {
141     score_change_name(&current_level_game, config_simple_get_s(CONFIG_PLAYER));
142 }
143
144 /*---------------------------------------------------------------------------*/
145