Another strong code change. This one focusses Set management:
[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
19 #include "level.h"
20 #include "levels.h"
21 #include "image.h"
22 #include "game.h"
23 #include "geom.h"
24 #include "demo.h"
25 #include "audio.h"
26 #include "config.h"
27 #include "set.h"
28
29 /*---------------------------------------------------------------------------*/
30
31 /* The level currently playing */
32 static struct level_game current_level_game;
33
34 /*---------------------------------------------------------------------------*/
35
36 int level_replay(const char *filename)
37 {
38     return demo_replay_init(filename, &current_level_game); 
39 }
40
41 static struct level single_level; /* a level without set */
42
43 int level_play_go(void)
44 /* Start to play the current level */
45 {
46     struct level_game *lg = &current_level_game;
47     int mode  = lg->mode;
48     const struct level *l;
49
50     if (curr_set())
51         l = get_level(lg->level);
52     else
53         l = &single_level;          
54     
55     lg->goal = (mode == MODE_PRACTICE) ? 0 : l->goal;
56     lg->time = (mode == MODE_PRACTICE) ? 0 : l->time;
57     
58     /* clear other fields */
59     lg->state = GAME_NONE;
60     lg->coins = 0;
61     lg->timer = lg->time;
62     lg->coin_rank = lg->goal_rank = lg->time_rank = 
63             lg->score_rank = lg-> times_rank = 3;
64     lg->next_level = 0;
65     
66     return demo_play_init(USER_REPLAY_FILE, l, lg);
67 }
68
69
70 void level_play_single(const char *filename)
71 /* Prepare to play a single level */
72 {
73     struct level *l = &single_level;
74
75     current_level_game.mode  = MODE_SINGLE;
76     current_level_game.level = 0;
77     
78     strncpy(l->file, filename, MAXSTR);
79     l->back[0] = '\0';
80     l->grad[0] = '\0';
81     l->song[0] = '\0';
82     l->shot[0] = '\0';
83     l->goal    = 0;
84     l->time    = 0;
85 }
86
87 void level_play(int i, int m)
88 /* Prepare to play a level sequence from the `i'th level */
89 {
90     current_level_game.mode = m;
91     current_level_game.level = i;
92
93     current_level_game.score = 0;
94     current_level_game.balls = 3;
95     current_level_game.times = 0;
96 }
97
98 /*---------------------------------------------------------------------------*/
99
100 const struct level_game * curr_lg(void)
101 {
102     return &current_level_game;
103 }
104
105 int count_extra_balls(int old_score, int coins)
106 {
107     int modulo = old_score % 100;
108     int sum    = modulo + coins;
109     return sum / 100;
110 }
111
112 void level_stop(int state, int clock, int coins)
113 /* Stop the current playing level */
114 {
115     struct level_game * lg = &current_level_game;
116     int mode = lg->mode;
117     int timer = (mode == MODE_PRACTICE || mode == MODE_SINGLE) ? clock : lg->time - clock;
118
119     lg->state = state;
120     lg->coins = coins;
121     lg->timer = timer;
122    
123     /* Performs challenge mode opperations */ 
124     if (mode == MODE_CHALLENGE)
125     {
126         /* sum time */
127         lg->times += timer; 
128             
129         /* sum coins an earn extra balls */
130         if (state == GAME_GOAL)
131         {
132             lg->balls += count_extra_balls(lg->score, coins);
133             lg->score += coins;
134         }
135
136         /* lose ball */
137         if (state == GAME_TIME || state == GAME_FALL)
138             lg->balls--;
139     }
140     
141     /* Update high-scores and next level */
142     if (state == GAME_GOAL && curr_set())
143         set_finish_level(lg, config_simple_get_s(CONFIG_PLAYER));
144     else
145         lg->next_level = -1;
146
147     /* stop demo recording */   
148     demo_play_stop(lg);
149 }
150
151 int level_dead(void)
152 {
153     int mode = current_level_game.mode;
154     int balls = current_level_game.balls;
155     return (mode == MODE_CHALLENGE) && (balls <= 0);
156 }
157
158 void level_next(void)
159 {
160     current_level_game.level = current_level_game.next_level;
161 }
162
163 void level_update_player_name(void)
164 {
165     score_change_name(&current_level_game, config_simple_get_s(CONFIG_PLAYER));
166 }
167
168 /*---------------------------------------------------------------------------*/
169