add magic to sol files and allow simple loading without texture and other things...
[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 static struct level single_level; /* a level without set */
41
42 int level_play_go(void)
43 /* Start to play the current level */
44 {
45     struct level_game *lg = &current_level_game;
46     const struct level *l = lg->level;
47     int mode = lg->mode;
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->next_level = 0;
59     
60     return demo_play_init(USER_REPLAY_FILE, l, lg);
61 }
62
63
64 void level_play_single(const char *filename)
65 /* Prepare to play a single level */
66 {
67     struct level *l = &single_level;
68     
69     l->back[0] = '\0';
70     l->grad[0] = '\0';
71     l->song[0] = '\0';
72     l->shot[0] = '\0';
73     l->goal    = 0;
74     l->time    = 0;
75     
76     level_load(filename, l);
77     
78     level_play(l, MODE_SINGLE);
79 }
80
81 void level_play(const struct level *l, int m)
82 /* Prepare to play a level sequence from the `i'th level */
83 {
84     current_level_game.mode = m;
85     current_level_game.level = l;
86
87     current_level_game.score = 0;
88     current_level_game.balls = 3;
89     current_level_game.times = 0;
90 }
91
92 /*---------------------------------------------------------------------------*/
93
94 const struct level_game * curr_lg(void)
95 {
96     return &current_level_game;
97 }
98
99 int count_extra_balls(int old_score, int coins)
100 {
101     int modulo = old_score % 100;
102     int sum    = modulo + coins;
103     return sum / 100;
104 }
105
106 void level_stop(int state, int clock, int coins)
107 /* Stop the current playing level */
108 {
109     struct level_game * lg = &current_level_game;
110     int mode = lg->mode;
111     int timer = (mode == MODE_PRACTICE || mode == MODE_SINGLE) ? clock : lg->time - clock;
112
113     lg->state = state;
114     lg->coins = coins;
115     lg->timer = timer;
116    
117     /* Performs challenge mode opperations */ 
118     if (mode == MODE_CHALLENGE)
119     {
120         /* sum time */
121         lg->times += timer; 
122             
123         /* sum coins an earn extra balls */
124         if (state == GAME_GOAL)
125         {
126             lg->balls += count_extra_balls(lg->score, coins);
127             lg->score += coins;
128         }
129
130         /* lose ball */
131         if (state == GAME_TIME || state == GAME_FALL)
132             lg->balls--;
133     }
134     
135     /* Update high-scores and next level */
136     if (state == GAME_GOAL && curr_set())
137         set_finish_level(lg, config_simple_get_s(CONFIG_PLAYER));
138     else
139         lg->next_level = NULL;
140
141     /* stop demo recording */   
142     demo_play_stop(lg);
143 }
144
145 int level_dead(void)
146 {
147     int mode = current_level_game.mode;
148     int balls = current_level_game.balls;
149     return (mode == MODE_CHALLENGE) && (balls <= 0);
150 }
151
152 void level_next(void)
153 {
154     struct level_game *lg = &current_level_game;
155     lg->level = lg->next_level;
156 }
157
158 void level_update_player_name(void)
159 {
160     score_change_name(&current_level_game, config_simple_get_s(CONFIG_PLAYER));
161 }
162
163 /*---------------------------------------------------------------------------*/
164