Several changes either directly or indirectly related to the recording
[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 /* Currently playing level. */
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(const struct level *l, int m)
41 {
42     struct level_game *lg = &current_level_game;
43
44     memset(lg, 0, sizeof (struct level_game));
45
46     lg->mode  = m;
47     lg->level = l;
48     lg->balls = 3;
49
50     lg->goal = (lg->mode == MODE_PRACTICE) ? 0 : lg->level->goal;
51     lg->time = (lg->mode == MODE_PRACTICE) ? 0 : lg->level->time;
52
53     /* Clear other fields. */
54
55     lg->status = GAME_NONE;
56     lg->coins = 0;
57     lg->timer = lg->time;
58     lg->coin_rank = lg->goal_rank = lg->time_rank =
59         lg->score_rank = lg->times_rank = 3;
60
61     lg->win = lg->dead = lg->unlock = 0;
62     lg->next_level = NULL;
63
64     return demo_play_init(USER_REPLAY_FILE, lg->level, lg);
65 }
66
67 /*---------------------------------------------------------------------------*/
68
69 const struct level_game *curr_lg(void)
70 {
71     return &current_level_game;
72 }
73
74 int count_extra_balls(int old_score, int coins)
75 {
76     return ((old_score % 100) + coins) / 100;
77 }
78
79 void level_stat(int status, int clock, int coins)
80 {
81     struct level_game *lg = &current_level_game;
82
83     int mode = lg->mode;
84     int timer = (mode == MODE_PRACTICE) ? clock : lg->time - clock;
85
86     char player[MAXNAM];
87
88     config_get_s(CONFIG_PLAYER, player, MAXNAM);
89
90     lg->status = status;
91     lg->coins = coins;
92     lg->timer = timer;
93
94     if (mode == MODE_CHALLENGE)
95     {
96         /* sum time */
97         lg->times += timer;
98
99         /* sum coins an earn extra balls */
100         if (status == GAME_GOAL || lg->level->is_bonus)
101         {
102             lg->balls += count_extra_balls(lg->score, coins);
103             lg->score += coins;
104         }
105
106         /* lose ball and game */
107         else
108         {
109             lg->dead = (lg->balls <= 0);
110             lg->balls--;
111         }
112     }
113
114     set_finish_level(lg, player);
115
116     demo_play_stat(lg);
117 }
118
119 void level_stop(void)
120 {
121     demo_play_stop();
122 }
123
124 int level_next(void)
125 {
126     struct level_game *lg = &current_level_game;
127
128     level_stop();
129     lg->level = lg->next_level;
130     return level_play(lg->level, lg->mode);
131 }
132
133 int level_same(void)
134 {
135     level_stop();
136     return level_play(curr_lg()->level, curr_lg()->mode);
137 }
138
139 void level_update_player_name(void)
140 {
141     char player[MAXNAM];
142
143     config_get_s(CONFIG_PLAYER, player, MAXNAM);
144
145     score_change_name(&current_level_game, player);
146 }
147
148 /*---------------------------------------------------------------------------*/
149