1 /***************************************************************************
2 game.c - description
3 -------------------
4 begin : Mon Aug 14 2000
5 copyright : (C) 2000 by Michael Speck
6 email : kulkanie@gmx.net
7 ***************************************************************************/
8
9 /***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18 #include "game.h"
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include "file.h"
23 #include "cfg.h"
24 #include "menu.h"
25 #include "timer.h"
26
27 Game gm;
28 /* levelset names & levelsets -- levels.h */
29 extern char **ls_lst;
30 extern int ls_n;
31 extern DLst l_sts;
32 /* line counter -- file.c */
33 extern int f_ln;
34 /* config -- cfg.c */
35 extern Cfg cfg;
36 /* Sdl -- sdl.c */
37 extern Sdl sdl;
38 /* profiles -- profile.c */
39 extern DLst prfs;
40 /* terminate game -- sdl.c */
41 extern int trm_gm;
42
43 void modify_score( int *b_lvl, int *b_tm );
44
45 /*
46 initialize game
47 */
G_Ini()48 void G_Ini()
49 {
50 FILE *f;
51 int i;
52 char str[256];
53 int ok = 0;
54 // cursors //
55 char data[32], mask[32];
56 char csr[6][256] = {
57 {
58 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0,
59 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0,
60 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0,
61 0, 0, 0, 0, 0, 2, 1, 2, 2, 1, 2, 0, 0, 0, 0, 0,
62 0, 0, 0, 0, 0, 2, 1, 2, 2, 1, 2, 0, 0, 0, 0, 0,
63 0, 0, 0, 0, 2, 1, 2, 1, 1, 2, 1, 2, 0, 0, 0, 0,
64 0, 0, 0, 0, 2, 1, 2, 1, 1, 2, 1, 2, 0, 0, 0, 0,
65 0, 0, 0, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 0, 0, 0,
66 0, 0, 0, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 0, 0, 0,
67 0, 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 0, 0,
68 0, 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 0, 0,
69 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 0,
70 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 0,
71 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2,
72 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
73 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
74 },
75 {
76 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
77 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
78 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2,
79 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 0,
80 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2, 0,
81 0, 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 0, 0,
82 0, 0, 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2, 0, 0,
83 0, 0, 0, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 0, 0, 0,
84 0, 0, 0, 2, 1, 2, 1, 1, 1, 1, 2, 1, 2, 0, 0, 0,
85 0, 0, 0, 0, 2, 1, 2, 1, 1, 2, 1, 2, 0, 0, 0, 0,
86 0, 0, 0, 0, 2, 1, 2, 1, 1, 2, 1, 2, 0, 0, 0, 0,
87 0, 0, 0, 0, 0, 2, 1, 2, 2, 1, 2, 0, 0, 0, 0, 0,
88 0, 0, 0, 0, 0, 2, 1, 2, 2, 1, 2, 0, 0, 0, 0, 0,
89 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0,
90 0, 0, 0, 0, 0, 0, 2, 1, 1, 2, 0, 0, 0, 0, 0, 0,
91 0, 0, 0, 0, 0, 0, 0, 2, 2, 0, 0, 0, 0, 0, 0, 0,
92 },
93 {
94 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
95 2, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
96 2, 1, 2, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
97 2, 1, 2, 2, 2, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0,
98 2, 1, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 0, 0, 0,
99 2, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 0,
100 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 0,
101 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2,
102 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2,
103 2, 1, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 0,
104 2, 1, 2, 1, 1, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 0,
105 2, 1, 2, 1, 1, 2, 2, 1, 1, 2, 2, 0, 0, 0, 0, 0,
106 2, 1, 2, 2, 2, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0,
107 2, 1, 2, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0,
108 2, 1, 1, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
109 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
110 },
111 {
112 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2,
113 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 2,
114 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 2, 1, 2,
115 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1, 2,
116 0, 0, 0, 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 1, 2,
117 0, 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2,
118 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2,
119 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2,
120 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 2,
121 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 1, 2,
122 0, 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 2,
123 0, 0, 0, 0, 0, 2, 2, 1, 1, 2, 2, 1, 1, 2, 1, 2,
124 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 2, 2, 2, 1, 2,
125 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 2, 1, 2,
126 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 1, 2,
127 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2,
128 },
129 {
130 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,
131 2, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 2,
132 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2,
133 2, 1, 1, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 1, 1, 2,
134 2, 1, 1, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 1, 2, 0,
135 0, 2, 1, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 2, 0, 0,
136 0, 0, 2, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0,
137 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
138 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
139 0, 0, 0, 2, 2, 2, 2, 0, 0, 2, 2, 2, 2, 0, 0, 0,
140 0, 0, 2, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 2, 0, 0,
141 0, 2, 1, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 1, 2, 0,
142 2, 1, 1, 1, 1, 1, 2, 0, 0, 2, 1, 1, 1, 1, 1, 2,
143 2, 1, 1, 1, 1, 2, 0, 0, 0, 0, 2, 1, 1, 1, 1, 2,
144 2, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0, 2, 1, 1, 1, 2,
145 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2,
146 },
147 {
148 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
149 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
150 2, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2,
151 0, 2, 1, 2, 0, 0, 0, 0, 0, 0, 0, 2, 2, 1, 2, 0,
152 0, 2, 1, 1, 2, 2, 2, 0, 0, 2, 2, 1, 1, 1, 2, 0,
153 0, 0, 2, 1, 1, 1, 1, 2, 2, 1, 1, 1, 1, 2, 0, 0,
154 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0,
155 0, 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0, 0,
156 0, 0, 0, 0, 2, 2, 1, 1, 1, 1, 2, 2, 0, 0, 0, 0,
157 0, 0, 0, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 0, 0, 0,
158 0, 0, 2, 1, 2, 2, 1, 1, 1, 1, 2, 2, 1, 2, 0, 0,
159 0, 2, 1, 2, 0, 2, 1, 1, 1, 1, 2, 0, 2, 1, 2, 0,
160 0, 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2, 0,
161 2, 1, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 2,
162 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2,
163 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
164 }
165 };
166
167 // initialize dyn list l_sts
168 DL_Ini(&l_sts);
169 l_sts.flgs = DL_AUTODEL;
170 l_sts.cb = L_DelSt;
171 // load level sets
172 printf("loading levelsets...\n");
173 for (i = 0; i < ls_n; i++) {
174 printf("%s... ", ls_lst[i]);
175 sprintf(str, "%s/levels/%s", SRC_DIR, ls_lst[i]);
176 f = fopen(str, "r");
177 if (f != 0) {
178 f_ln = 1;
179 if (L_LdSt(f)) {
180 ok = 1;
181 strcpy(((LSet*)l_sts.tl.p->d)->nm, ls_lst[i]);
182 }
183 else
184 L_AddInvSt(ls_lst[i]);
185 fclose(f);
186 }
187 else {
188 L_AddInvSt(ls_lst[i]);
189 printf("WARNING: levelset not found...\n");
190 }
191 }
192
193 // found something ? //
194 if (!ok) {
195 printf("ERROR: no valid level set found; need at least one level set...\n");
196 exit(1);
197 }
198
199 /* clear gm struct */
200 //memset( &gm, 0, sizeof( gm ) );
201
202 // initialize gfx set
203 DL_Ini(&gm.g_sts);
204 gm.g_sts.flgs = DL_AUTODEL;
205 gm.g_sts.cb = G_DelGSt;
206 // load gfx sets
207 G_LdGSts();
208
209 // load board
210 gm.s_brd = SS_Ld("gfx/board.bmp", SDL_SWSURFACE);
211 SDL_SetColorKey(gm.s_brd, 0, 0);
212 // load lights
213 gm.s_lghts = SS_Ld("gfx/lights.bmp", SDL_SWSURFACE);
214 // load marbles
215 gm.s_mrb = SS_Ld("gfx/marbles.bmp", SDL_SWSURFACE);
216 // load figure
217 gm.s_fig = SS_Ld("gfx/figure.bmp", SDL_SWSURFACE);
218 // load marble frame
219 gm.s_mf = SS_Ld("gfx/m_frame.bmp", SDL_SWSURFACE);
220 // load marble select frame
221 gm.s_msf = SS_Ld("gfx/m_sframe.bmp", SDL_SWSURFACE);
222 // background //
223 gm.s_bkgd = 0;
224
225 // load fonts
226 gm.f_sml = SF_LdFxd("gfx/f_small.bmp", 32, 96, 8);
227 gm.f_wht = SF_LdFxd("gfx/f_white.bmp", 32, 96, 10);
228 gm.f_rd = SF_LdFxd("gfx/f_red.bmp", 32, 96, 10);
229
230 // level
231 gm.c_lvl = 0;
232
233 // marble
234 gm.m_v = 0.15;
235 gm.m_a.p = 0;
236 gm.m_a.f = 4;
237 gm.m_a.c = 0.016 + 0.008;
238 gm.m_a.w = gm.m_a.h = 32;
239 gm.m_act = M_EMPTY;
240 gm.m_o_x = gm.m_o_y = -1;
241 gm.m_warp = 0;
242
243 // marble select frame
244 gm.msf_a.f = 4;
245 gm.msf_a.w = gm.msf_a.h = 40;
246 gm.msf_a.c = 0.02;
247 gm.msf_a.p = 0;
248
249 // marble frame
250 gm.mf_a.f = 4;
251 gm.mf_a.w = gm.mf_a.h = 40;
252 gm.mf_a.c = 0.02;
253 gm.mf_a.p = 0;
254
255 // layout
256 gm.b_x = 640 - 200;
257 gm.f_x = 35;
258 gm.f_y = 145;
259 gm.i_x = 20;
260 gm.i_y = 25;
261 gm.t_x = 40;
262 gm.t_y = 105;
263 gm.s_x = 15;
264 gm.s_y = 290;
265
266 // geometry
267 gm.t_w = gm.t_h = 32;
268 gm.f_w = gm.f_h = 12;
269 gm.f_fw = gm.f_fh = 130;
270 gm.scr_w = 640;
271 gm.scr_h = 480;
272 gm.brd_w = 200;
273 gm.s_w = 170;
274 gm.s_h = 175;
275 gm.c_off = 12;
276
277 // cursors
278 memset(data, 0, sizeof(data));
279 gm.c_u = gm.c_d = gm.c_l = gm.c_r = gm.c_s = gm.c_w = 0;
280 gm.c_n = SDL_GetCursor();
281 Cr_Ld(csr[0], data, mask);
282 gm.c_u = SDL_CreateCursor(data, mask, 16, 16, 8, 8);
283 Cr_Ld(csr[1], data, mask);
284 gm.c_d = SDL_CreateCursor(data, mask, 16, 16, 8, 8);
285 Cr_Ld(csr[2], data, mask);
286 gm.c_r = SDL_CreateCursor(data, mask, 16, 16, 8, 8);
287 Cr_Ld(csr[3], data, mask);
288 gm.c_l = SDL_CreateCursor(data, mask, 16, 16, 8, 8);
289 Cr_Ld(csr[4], data, mask);
290 gm.c_s = SDL_CreateCursor(data, mask, 16, 16, 8, 8);
291 Cr_Ld(csr[5], data, mask);
292 gm.c_w = SDL_CreateCursor(data, mask, 16, 16, 8, 8);
293
294 // map animations
295 gm.m_ani = 0;
296
297 // oneway animation info
298 gm.ma_ow_a.f = 4;
299 gm.ma_ow_a.c = 0.008;
300 gm.ma_ow_a.p = 0;
301 gm.ma_ow_a.w = gm.t_w;
302 gm.ma_ow_a.h = gm.t_h;
303
304 // teleport information
305 gm.ma_tlp_a.f = 4;
306 gm.ma_tlp_a.c = 0.008;
307 gm.ma_tlp_a.p = 0;
308 gm.ma_tlp_a.w = gm.t_w;
309 gm.ma_tlp_a.h = gm.t_h;
310 gm.tlp_a = 32;
311
312 // sounds
313 #ifdef SOUND
314 gm.wv_tlp = sound_chunk_load("teleport.wav");
315 gm.wv_sel = sound_chunk_load("select.wav");
316 gm.wv_stp = sound_chunk_load("stop.wav");
317 gm.wv_clk = sound_chunk_load("click.wav");
318 gm.wv_exp = sound_chunk_load("explode.wav");
319 gm.wv_alm = sound_chunk_load("alarm.wav");
320 gm.wv_arw = sound_chunk_load("arrow.wav");
321 gm.wv_scr = sound_chunk_load("score.wav");
322 #endif
323
324 // shrapnells
325 DL_Ini(&gm.shr);
326 gm.shr.flgs = DL_AUTODEL;
327 gm.shr.cb = Shr_Del;
328 gm.shr_a_c = 0.1;
329
330 // credits
331 gm.cr_a_c = 0.1;
332 gm.cr_tm = 3000;
333 gm.cr_y = 10;
334
335 // shnapshot
336 gm.snap = 0;
337 }
338
339 /*
340 terminate game
341 */
G_Trm()342 void G_Trm()
343 {
344 // release gfx
345 if (gm.s_brd) SDL_FreeSurface(gm.s_brd);
346 if (gm.s_lghts) SDL_FreeSurface(gm.s_lghts);
347 if (gm.s_mrb) SDL_FreeSurface(gm.s_mrb);
348 if (gm.s_fig) SDL_FreeSurface(gm.s_fig);
349 if (gm.s_mf) SDL_FreeSurface(gm.s_mf);
350 if (gm.s_msf) SDL_FreeSurface(gm.s_msf);
351 // release fonts
352 if (gm.f_sml) SF_Fr(gm.f_sml);
353 if (gm.f_wht) SF_Fr(gm.f_wht);
354 if (gm.f_rd) SF_Fr(gm.f_rd);
355 // release dynlists
356 DL_Clr(&gm.g_sts);
357 DL_Clr(&l_sts);
358 DL_Clr(&gm.shr);
359 // cursors //
360 if (gm.c_u) SDL_FreeCursor(gm.c_u);
361 if (gm.c_d) SDL_FreeCursor(gm.c_d);
362 if (gm.c_l) SDL_FreeCursor(gm.c_l);
363 if (gm.c_r) SDL_FreeCursor(gm.c_r);
364 if (gm.c_s) SDL_FreeCursor(gm.c_s);
365 if (gm.c_w) SDL_FreeCursor(gm.c_w);
366 // free map animations //
367 if (gm.m_ani)
368 free(gm.m_ani);
369 // sounds
370 #ifdef SOUND
371 if (gm.wv_tlp) sound_chunk_free(&gm.wv_tlp);
372 if (gm.wv_sel) sound_chunk_free(&gm.wv_sel);
373 if (gm.wv_stp) sound_chunk_free(&gm.wv_stp);
374 if (gm.wv_clk) sound_chunk_free(&gm.wv_clk);
375 if (gm.wv_exp) sound_chunk_free(&gm.wv_exp);
376 if (gm.wv_alm) sound_chunk_free(&gm.wv_alm);
377 if (gm.wv_arw) sound_chunk_free(&gm.wv_arw);
378 if (gm.wv_scr) sound_chunk_free(&gm.wv_scr);
379 #endif
380 }
381
382 /*
383 open a new game
384 */
G_Opn()385 int G_Opn()
386 {
387 Prf *p;
388 DL_E *e;
389 int flgs = SDL_SWSURFACE;
390
391 // get current level set
392 gm.c_l_st = (LSet*)DL_Get(&l_sts, cfg.ls);
393
394 // check if current level set is valid
395 if (!G_CkLSt()) {
396 // restore menu
397 MM_Shw(MM_RSZ);
398
399 return 0;
400 }
401
402 // current profile
403 gm.c_prf = (Prf*)DL_Get(&prfs, cfg.prf);
404
405 // current set info
406 gm.c_s_inf = Prf_RegLS(gm.c_prf, gm.c_l_st);
407
408 // dim & resize
409 if (cfg.dim)
410 SDL_DIM();
411 if (cfg.fscr)
412 flgs = flgs | SDL_FULLSCREEN;
413 Sdl_StVdMd(gm.scr_w, gm.scr_h, 16, flgs);
414
415 // create background
416 gm.s_bkgd = SS_Crt(gm.scr_w, gm.scr_h, SDL_SWSURFACE);
417 SDL_SetColorKey(gm.s_bkgd, 0, 0);
418
419 // get highest score
420 gm.hi_scr = 0;
421 e = prfs.hd.n;
422 while (e != &prfs.tl) {
423 p = (Prf*)e->d;
424 if (p->scr > gm.hi_scr)
425 gm.hi_scr = p->scr;
426 e = e->n;
427 }
428
429 // clear old chapter
430 gm.o_ch = -1;
431
432 // init first level
433 L_Ini(0, 0);
434
435 return 1;
436 }
437
438 /*
439 close game
440 */
G_Cls()441 void G_Cls()
442 {
443 // dim
444 if (!trm_gm && cfg.dim)
445 SDL_DIM();
446
447 // free background
448 if (gm.s_bkgd) SDL_FreeSurface(gm.s_bkgd);
449
450 // free level
451 free(gm.c_lvl);
452 gm.c_lvl = 0;
453
454 // restore cursor
455 SDL_SetCursor(gm.c_n);
456
457 // show menu
458 MM_Shw(MM_RSZ);
459 }
460
461 /*
462 game's main loop
463 */
G_Run()464 void G_Run()
465 {
466 int leave = 0;
467 int restart = 0;
468 int ms;
469 SDL_Event ev;
470 SDL_Surface *buf;
471 int flgs;
472 int restore_pos;
473 int tm_rel = 0;
474 int ign_c_stat = 0;
475 int bonus_level, bonus_moves; /* bonus for level completion and remaining moves */
476
477 while (!trm_gm) {
478 // clear input
479 while (SDL_PollEvent(&ev));
480 // main loop
481 while (!leave && !trm_gm && !gm.l_done && !restart) {
482 // don't consume all cpu time
483 SDL_Delay( 5 );
484
485 restore_pos = 0; // do not restore old position
486 ign_c_stat = 0; // do not ignore cursor state
487 // get input
488 if (SDL_PollEvent(&ev)) {
489 switch (ev.type) {
490 case SDL_QUIT:
491 trm_gm = 1;
492 break;
493 case SDL_KEYUP:
494 switch (ev.key.keysym.sym) {
495 case SDLK_TAB:
496 SnapShot();
497 break;
498 case SDLK_ESCAPE:
499 if (G_CfmQut())
500 leave = 1;
501 break;
502 case SDLK_p:
503 G_Ps();
504 break;
505 case SDLK_r:
506 if (G_CfmRst())
507 restart = 1;
508 break;
509 case SDLK_f:
510 buf = SS_Crt(gm.scr_w, gm.scr_h, SDL_SWSURFACE);
511 D_FDST(buf);
512 D_FSRC(sdl.scr);
513 SS_Blt();
514 cfg.fscr = !cfg.fscr;
515 flgs = SDL_SWSURFACE;
516 if (cfg.fscr)
517 flgs = flgs | SDL_FULLSCREEN;
518 Sdl_StVdMd(gm.scr_w, gm.scr_h, 16, flgs);
519 D_FDST(sdl.scr);
520 D_FSRC(buf);
521 SS_Blt();
522 Sdl_FUpd();
523 break;
524 default:
525 /* if no marble is selected we don't have to check anything */
526 if ( !gm.m_sel )
527 break;
528 /* warp? */
529 if (gm.m_mv && (ev.key.keysym.sym == cfg.k_right || ev.key.keysym.sym == cfg.k_left || ev.key.keysym.sym == cfg.k_up || ev.key.keysym.sym == cfg.k_down)) {
530 gm.m_warp = 1;
531 break;
532 }
533 // undo key
534 if (ev.key.keysym.sym == cfg.k_undo) {
535 restore_pos = 1;
536 #ifdef SOUND
537 sound_play(gm.wv_clk);
538 #endif
539 }
540 // up key
541 if (ev.key.keysym.sym == cfg.k_up && (gm.m_vd & MD_U) && !gm.m_mv) {
542 ign_c_stat = 1;
543 gm.c_stat = C_U;
544 Mr_IniMv();
545 #ifdef SOUND
546 sound_play(gm.wv_clk);
547 #endif
548 }
549 // down key
550 if (ev.key.keysym.sym == cfg.k_down && (gm.m_vd & MD_D) && !gm.m_mv) {
551 ign_c_stat = 1;
552 gm.c_stat = C_D;
553 Mr_IniMv();
554 #ifdef SOUND
555 sound_play(gm.wv_clk);
556 #endif
557 }
558 // left key
559 if (ev.key.keysym.sym == cfg.k_left && (gm.m_vd & MD_L) && !gm.m_mv) {
560 ign_c_stat = 1;
561 gm.c_stat = C_L;
562 Mr_IniMv();
563 #ifdef SOUND
564 sound_play(gm.wv_clk);
565 #endif
566 }
567 // right key
568 if (ev.key.keysym.sym == cfg.k_right && (gm.m_vd & MD_R) && !gm.m_mv) {
569 ign_c_stat = 1;
570 gm.c_stat = C_R;
571 Mr_IniMv();
572 #ifdef SOUND
573 sound_play(gm.wv_clk);
574 #endif
575 }
576 break;
577 }
578 break;
579 case SDL_MOUSEBUTTONDOWN:
580 break;
581 case SDL_MOUSEBUTTONUP:
582 if ( ev.button.button == 1 && gm.m_mv &&
583 ( gm.c_l_st->limit_type == MOVES ) ) {
584 gm.m_warp = 1;
585 break;
586 }
587 gm.bttn[ev.button.button] = 1;
588 if (ev.button.button == 1) {
589 if (gm.c_stat == C_SEL)
590 Mr_Sel(ev.button.x, ev.button.y);
591 else
592 if (gm.m_sel && !gm.m_mv) {
593 // start movement of selected marble
594 Mr_IniMv();
595 }
596 }
597 else
598 if (gm.m_sel && !gm.m_mv)
599 Mr_Rel(ev.button.x, ev.button.y);
600 break;
601 case SDL_MOUSEMOTION:
602 if ( !ign_c_stat )
603 Cr_Cng(ev.motion.x, ev.motion.y);
604 gm.o_mx = ev.motion.x;
605 gm.o_my = ev.motion.y;
606 break;
607 default:
608 break;
609 }
610 }
611
612 // hide
613 if (!leave && !restart) {
614 Mr_Hd();
615 MF_Hd();
616 Tm_Hd();
617 Inf_Hd();
618 Shr_Hd();
619 Cr_Hd();
620 }
621
622 // update
623 ms = T_Gt();
624 MA_Upd(ms);
625 if (restore_pos)
626 Mr_ResPos();
627 if ( !Mr_Upd(ms) )
628 restart = 1;
629 MF_Upd(ms);
630 Shr_Upd(ms);
631 Cr_Upd(ms);
632 if (!Tm_Upd(ms))
633 restart = 1;
634 if (Inf_Upd() && G_CfmWrp()) {
635 gm.c_ch = gm.w_c;
636 gm.c_l_id = gm.w_l;
637 restart = 1;
638 }
639
640 // show
641 if (!leave && !restart)
642 MA_Shw();
643 if (!leave && !restart) {
644 Mr_Shw();
645 }
646 if (!leave && !restart && !gm.l_done) {
647 MF_Shw();
648 Tm_Shw();
649 Inf_Shw();
650 Shr_Shw();
651 Cr_Shw();
652
653 // refresh
654 Sdl_UpdR();
655 }
656 else
657 sdl.rnum = 0; // reset redraw regions
658
659 // reset buttonstate
660 memset(gm.bttn, 0, sizeof(gm.bttn));
661 }
662
663 // leave ?
664 if (leave)
665 break;
666
667 // init next level
668 if (gm.l_done || restart) {
669
670 if (gm.l_done) {
671
672 // figure animation
673 FA_Run();
674 // bonus summary
675 if ( !gm.c_s_inf->cmp[gm.c_ch * gm.c_s_inf->l_num + gm.c_l_id] ) {
676
677 /* level wasn't completed until now so gain score for it */
678 bonus_level = LB_COMPLETED;
679 bonus_moves = gm.c_lvl->tm * LB_PER_MOVE;
680 modify_score( &bonus_level, &bonus_moves );
681 BS_Run( bonus_level, bonus_moves );
682 tm_rel = ( 1000 * gm.c_lvl->tm ) / gm.c_l_st->ch[gm.c_ch].lvls[gm.c_l_id].tm;
683 Prf_Upd(gm.c_prf, gm.c_s_inf, gm.c_ch * gm.c_l_st->l_num + gm.c_l_id, tm_rel, bonus_level + bonus_moves );
684
685 }
686
687 }
688
689 if (cfg.dim)
690 SDL_DIM();
691 if (!restart)
692 if (!L_FndNxt()) // game finished ?
693 break;
694 L_Ini(gm.c_ch, gm.c_l_id);
695 restart = 0;
696 }
697 }
698 // save profiles
699 Prf_Sv();
700 }
701
702 /*
703 load all gfx sets
704 */
G_LdGSts()705 void G_LdGSts()
706 {
707 char d_nm[256];
708 char path[256+64];
709 DIR *dir = 0;
710 struct dirent *e;
711 struct stat s;
712 GSet *g_st;
713
714 printf("loading graphics sets...\n");
715
716 // create directory string //
717 sprintf(d_nm, "%s/gfx", SRC_DIR);
718
719 // find and open directory //
720 if ((dir = opendir(d_nm)) == 0) {
721 fprintf(stderr, "ERROR: can't find directory '%s'\n", d_nm);
722 exit(1);
723 }
724
725 // well, let's check for directories //
726 while ((e = readdir(dir)) != 0) {
727 sprintf(path, "%s/%s", d_nm, e->d_name);
728 stat(path, &s);
729 if (S_ISDIR(s.st_mode) && e->d_name[0] != '.') {
730 printf("'%s'... \n", e->d_name);
731 // load gfx //
732 g_st = (GSet*)malloc(sizeof(GSet));
733 memset(g_st, 0, sizeof(GSet));
734 strcpy(g_st->nm, e->d_name);
735 g_st->ok = 1;
736
737 sprintf(path, "gfx/%s/%s", e->d_name, "background.bmp");
738 g_st->s_bkgd = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL);
739 SDL_SetColorKey(g_st->s_bkgd, 0, 0);
740
741 sprintf(path, "gfx/%s/%s", e->d_name, "wall.bmp");
742 if ((g_st->s_wl = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
743 g_st->ok = 0;
744
745 sprintf(path, "gfx/%s/%s", e->d_name, "floor.bmp");
746 if ((g_st->s_flr = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
747 g_st->ok = 0;
748
749 sprintf(path, "gfx/%s/%s", e->d_name, "arrow_r.bmp");
750 if ((g_st->s_r_arw = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
751 g_st->ok = 0;
752
753 sprintf(path, "gfx/%s/%s", e->d_name, "arrow_l.bmp");
754 if ((g_st->s_l_arw = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
755 g_st->ok = 0;
756
757 sprintf(path, "gfx/%s/%s", e->d_name, "arrow_u.bmp");
758 if ((g_st->s_u_arw = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
759 g_st->ok = 0;
760
761 sprintf(path, "gfx/%s/%s", e->d_name, "arrow_d.bmp");
762 if ((g_st->s_d_arw = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
763 g_st->ok = 0;
764
765 sprintf(path, "gfx/%s/%s", e->d_name, "barrier_lr.bmp");
766 if ((g_st->s_lr_bar = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
767 g_st->ok = 0;
768
769 sprintf(path, "gfx/%s/%s", e->d_name, "barrier_ud.bmp");
770 if ((g_st->s_ud_bar = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
771 g_st->ok = 0;
772
773 sprintf(path, "gfx/%s/%s", e->d_name, "teleport0.bmp");
774 if ((g_st->s_tlp_0 = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
775 g_st->ok = 0;
776
777 sprintf(path, "gfx/%s/%s", e->d_name, "teleport1.bmp");
778 if ((g_st->s_tlp_1 = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
779 g_st->ok = 0;
780
781 sprintf(path, "gfx/%s/%s", e->d_name, "teleport2.bmp");
782 if ((g_st->s_tlp_2 = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
783 g_st->ok = 0;
784
785 sprintf(path, "gfx/%s/%s", e->d_name, "teleport3.bmp");
786 if ((g_st->s_tlp_3 = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
787 g_st->ok = 0;
788
789 sprintf(path, "gfx/%s/%s", e->d_name, "wall_crumble.bmp");
790 if ((g_st->s_crmbl = SS_Ld(path, SDL_SWSURFACE | SDL_NONFATAL)) == 0)
791 g_st->ok = 0;
792
793 if (g_st->ok) {
794 printf("ok\n");
795 // opaque
796 SDL_SetColorKey(g_st->s_flr, 0, 0);
797 SDL_SetColorKey(g_st->s_wl, 0, 0);
798 }
799 DL_Add(&gm.g_sts, g_st);
800 }
801 }
802 closedir(dir);
803 }
804
805
806 /*
807 delete a gset
808 */
G_DelGSt(void * p)809 void G_DelGSt(void *p)
810 {
811 GSet *st = (GSet*)p;
812 if (st->s_bkgd) SDL_FreeSurface(st->s_bkgd);
813 if (st->s_wl) SDL_FreeSurface(st->s_wl);
814 if (st->s_flr) SDL_FreeSurface(st->s_flr);
815 if (st->s_u_arw) SDL_FreeSurface(st->s_u_arw);
816 if (st->s_d_arw) SDL_FreeSurface(st->s_d_arw);
817 if (st->s_r_arw) SDL_FreeSurface(st->s_r_arw);
818 if (st->s_l_arw) SDL_FreeSurface(st->s_l_arw);
819 if (st->s_lr_bar) SDL_FreeSurface(st->s_lr_bar);
820 if (st->s_ud_bar) SDL_FreeSurface(st->s_ud_bar);
821 if (st->s_tlp_0) SDL_FreeSurface(st->s_tlp_0);
822 if (st->s_tlp_1) SDL_FreeSurface(st->s_tlp_1);
823 if (st->s_tlp_2) SDL_FreeSurface(st->s_tlp_2);
824 if (st->s_tlp_3) SDL_FreeSurface(st->s_tlp_3);
825 if (st->s_crmbl) SDL_FreeSurface(st->s_crmbl);
826 free(st);
827 }
828
829 /*
830 pause game
831 */
G_Ps()832 void G_Ps()
833 {
834 SFnt *ft = gm.f_sml;
835 SDL_Surface *buf;
836 char str[256];
837 SDL_Event e;
838 int leave = 0;
839 int flgs;
840 int mx = gm.o_mx, my = gm.o_my;
841
842 // save screen //
843 buf = SS_Crt(gm.scr_w, gm.scr_h, SDL_SWSURFACE);
844 SDL_SetColorKey(buf, 0, 0);
845 D_FDST(buf);
846 D_FSRC(sdl.scr);
847 SS_Blt();
848
849 // cursor
850 SDL_SetCursor(gm.c_n);
851
852 // fill with black
853 D_FDST(sdl.scr);
854 SS_Fill(0x0);
855
856 // write info
857 ft->algn = TA_X_C | TA_Y_C;
858 sprintf(str, "Game paused");
859 SF_Wrt(ft, sdl.scr, gm.scr_w / 2, gm.scr_h / 2, str, 0);
860
861 Sdl_FUpd();
862
863 // wait for 'p'
864 while (!leave) {
865 SDL_WaitEvent(&e);
866 switch (e.type) {
867 case SDL_QUIT:
868 trm_gm = 1;
869 leave = 1;
870 break;
871 case SDL_KEYUP:
872 if (e.key.keysym.sym == SDLK_p)
873 leave = 1;
874 if (e.key.keysym.sym == SDLK_f) {
875 cfg.fscr = !cfg.fscr;
876 flgs = SDL_SWSURFACE;
877 if (cfg.fscr)
878 flgs = flgs | SDL_FULLSCREEN;
879 Sdl_StVdMd(gm.scr_w, gm.scr_h, 16, flgs);
880 D_FDST(sdl.scr);
881 SS_Fill(0x0);
882 SF_Wrt(ft, sdl.scr, gm.scr_w / 2, gm.scr_h / 2, str, 0);
883 Sdl_FUpd();
884 }
885 break;
886 case SDL_MOUSEMOTION:
887 mx = e.motion.x;
888 my = e.motion.y;
889 break;
890 }
891 }
892
893 // restore screen
894 D_FDST(sdl.scr);
895 D_FSRC(buf);
896 SS_Blt();
897 Sdl_FUpd();
898 SDL_FreeSurface(buf);
899
900 // cursor
901 Cr_Cng(mx, my);
902
903 //reset time //
904 T_Rst();
905 }
906
907 /*
908 check if the figure has been completed
909 */
G_CkFgr()910 void G_CkFgr()
911 {
912 int i, j, k, l;
913 Lvl *lvl = gm.c_lvl;
914
915 for (i = 0; i < lvl->m_w - lvl->f_w; i++)
916 for (j = 0; j < lvl->m_h - lvl->f_h; j++) {
917 gm.l_done = 1;
918 for (k = 0; k < lvl->f_w; k++) {
919 for (l = 0; l < lvl->f_h; l++) {
920 if (lvl->fgr[k][l] != -1)
921 if (lvl->map[i + k][j + l].m != lvl->fgr[k][l]) {
922 gm.l_done = 0;
923 break;
924 }
925 }
926 if (!gm.l_done)
927 break;
928 }
929 if (gm.l_done)
930 return;
931 }
932 }
933
934 /*
935 confirm warp
936 */
G_CfmWrp()937 int G_CfmWrp()
938 {
939 SFnt *ft = gm.f_sml;
940 SDL_Surface *buf;
941 SDL_Event e;
942 char str[256];
943 int leave = 0, ret = 0;
944 int mx = gm.o_mx, my = gm.o_my;
945
946 // save screen //
947 buf = SS_Crt(gm.scr_w, gm.scr_h, SDL_SWSURFACE);
948 SDL_SetColorKey(buf, 0, 0);
949 D_FDST(buf);
950 D_FSRC(sdl.scr);
951 SS_Blt();
952
953 // cursor
954 SDL_SetCursor(gm.c_n);
955
956 // fill with black
957 D_FDST(sdl.scr);
958 SS_Fill(0x0);
959
960 // write info
961 ft->algn = TA_X_C | TA_Y_T;
962 sprintf(str, "Your current position is level %i of chapter %i.", gm.c_l_id + 1, gm.c_ch + 1);
963 SF_Wrt(ft, sdl.scr, gm.scr_w / 2, 200, str, 0);
964 sprintf(str, "Do you really want to enter level %i of chapter %i?", gm.w_l + 1, gm.w_c + 1);
965 SF_Wrt(ft, sdl.scr, gm.scr_w / 2, 200 + 15, str, 0);
966 sprintf(str, "(All changes in the current level will be lost!)");
967 SF_Wrt(ft, sdl.scr, gm.scr_w / 2, 200 + 30, str, 0);
968 sprintf(str, "(press y/n)");
969 SF_Wrt(ft, sdl.scr, gm.scr_w / 2, 200 + 50, str, 0);
970
971 Sdl_FUpd();
972
973 #ifdef SOUND
974 sound_play(gm.wv_clk);
975 #endif
976 while (!leave) {
977 SDL_WaitEvent(&e);
978 switch (e.type) {
979 case SDL_QUIT:
980 trm_gm = leave = 1;
981 break;
982 case SDL_KEYUP:
983 switch (e.key.keysym.sym) {
984 case SDLK_y:
985 ret = 1;
986 leave = 1;
987 break;
988 case SDLK_n:
989 ret = 0;
990 leave = 1;
991 break;
992 default:
993 break;
994 }
995 break;
996 case SDL_MOUSEBUTTONUP:
997 switch (e.button.button) {
998 case 1:
999 ret = 1;
1000 leave = 1;
1001 break;
1002 default:
1003 ret = 0;
1004 leave = 1;
1005 break;
1006 }
1007 break;
1008 case SDL_MOUSEMOTION:
1009 mx = e.motion.x;
1010 my = e.motion.y;
1011 break;
1012 }
1013 }
1014 #ifdef SOUND
1015 sound_play(gm.wv_clk);
1016 #endif
1017
1018 // restore screen
1019 if (cfg.dim)
1020 SDL_DIM();
1021 if (!ret) {
1022 D_FDST(sdl.scr);
1023 D_FSRC(buf);
1024 SS_Blt();
1025 if (cfg.dim)
1026 SDL_UNDIM();
1027 else
1028 Sdl_FUpd();
1029
1030 // cursor
1031 Cr_Cng(mx, my);
1032
1033 }
1034 SDL_FreeSurface(buf);
1035
1036 // reset time //
1037 T_Rst();
1038
1039 return ret;
1040 }
1041
1042 /*
1043 confirm quit
1044 */
G_CfmQut()1045 int G_CfmQut()
1046 {
1047 SFnt *ft = gm.f_sml;
1048 SDL_Surface *buf;
1049 SDL_Event e;
1050 char str[256];
1051 int leave = 0, ret = 0;
1052 int mx = gm.o_mx, my = gm.o_my;
1053
1054 // save screen //
1055 buf = SS_Crt(gm.scr_w, gm.scr_h, SDL_SWSURFACE);
1056 SDL_SetColorKey(buf, 0, 0);
1057 D_FDST(buf);
1058 D_FSRC(sdl.scr);
1059 SS_Blt();
1060
1061 // cursor
1062 SDL_SetCursor(gm.c_n);
1063
1064 // fill with black
1065 D_FDST(sdl.scr);
1066 SS_Fill(0x0);
1067
1068 // write info
1069 ft->algn = TA_X_C | TA_Y_C;
1070 sprintf(str, "Do you really want to quit? (y/n)");
1071 SF_Wrt(ft, sdl.scr, gm.scr_w / 2, gm.scr_h / 2, str, 0);
1072
1073 Sdl_FUpd();
1074
1075 #ifdef SOUND
1076 sound_play(gm.wv_clk);
1077 #endif
1078 while (!leave) {
1079 SDL_WaitEvent(&e);
1080 switch (e.type) {
1081 case SDL_QUIT:
1082 trm_gm = leave = 1;
1083 break;
1084 case SDL_KEYUP:
1085 switch (e.key.keysym.sym) {
1086 case SDLK_ESCAPE:
1087 case SDLK_y:
1088 ret = 1;
1089 leave = 1;
1090 break;
1091 case SDLK_n:
1092 ret = 0;
1093 leave = 1;
1094 break;
1095 default:
1096 break;
1097 }
1098 break;
1099 case SDL_MOUSEBUTTONUP:
1100 switch (e.button.button) {
1101 case 1:
1102 ret = 1;
1103 leave = 1;
1104 break;
1105 default:
1106 ret = 0;
1107 leave = 1;
1108 break;
1109 }
1110 break;
1111 }
1112 }
1113 #ifdef SOUND
1114 sound_play(gm.wv_clk);
1115 #endif
1116
1117 // restore screen
1118 if (!ret) {
1119 if (cfg.dim)
1120 SDL_DIM();
1121 D_FDST(sdl.scr);
1122 D_FSRC(buf);
1123 SS_Blt();
1124 if (cfg.dim)
1125 SDL_UNDIM();
1126 else
1127 Sdl_FUpd();
1128
1129 // cursor
1130 Cr_Cng(mx, my);
1131
1132 }
1133 SDL_FreeSurface(buf);
1134
1135 // reset time //
1136 T_Rst();
1137
1138 return ret;
1139 }
1140
1141 /*
1142 confirm quit
1143 */
G_CfmRst()1144 int G_CfmRst()
1145 {
1146 SFnt *ft = gm.f_sml;
1147 SDL_Surface *buf;
1148 SDL_Event e;
1149 char str[256];
1150 int leave = 0, ret = 0;
1151 int mx = gm.o_mx, my = gm.o_my;
1152
1153 // save screen //
1154 buf = SS_Crt(gm.scr_w, gm.scr_h, SDL_SWSURFACE);
1155 SDL_SetColorKey(buf, 0, 0);
1156 D_FDST(buf);
1157 D_FSRC(sdl.scr);
1158 SS_Blt();
1159
1160 // cursor
1161 SDL_SetCursor(gm.c_n);
1162
1163 // fill with black
1164 D_FDST(sdl.scr);
1165 SS_Fill(0x0);
1166
1167 // write info
1168 ft->algn = TA_X_C | TA_Y_C;
1169 sprintf(str, "Do you really want to restart? (y/n)");
1170 SF_Wrt(ft, sdl.scr, gm.scr_w / 2, gm.scr_h / 2, str, 0);
1171
1172 Sdl_FUpd();
1173
1174 #ifdef SOUND
1175 sound_play(gm.wv_clk);
1176 #endif
1177 while (!leave) {
1178 SDL_WaitEvent(&e);
1179 switch (e.type) {
1180 case SDL_QUIT:
1181 trm_gm = leave = 1;
1182 break;
1183 case SDL_KEYUP:
1184 switch (e.key.keysym.sym) {
1185 case SDLK_r:
1186 case SDLK_y:
1187 ret = 1;
1188 leave = 1;
1189 break;
1190 case SDLK_n:
1191 ret = 0;
1192 leave = 1;
1193 break;
1194 default:
1195 break;
1196 }
1197 break;
1198 case SDL_MOUSEBUTTONUP:
1199 switch (e.button.button) {
1200 case 1:
1201 ret = 1;
1202 leave = 1;
1203 break;
1204 default:
1205 ret = 0;
1206 leave = 1;
1207 break;
1208 }
1209 break;
1210 }
1211 }
1212 #ifdef SOUND
1213 sound_play(gm.wv_clk);
1214 #endif
1215
1216 // restore screen
1217 if (cfg.dim)
1218 SDL_DIM();
1219 if (!ret) {
1220 D_FDST(sdl.scr);
1221 D_FSRC(buf);
1222 SS_Blt();
1223 if (cfg.dim)
1224 SDL_UNDIM();
1225 else
1226 Sdl_FUpd();
1227
1228 // cursor
1229 Cr_Cng(mx, my);
1230
1231 }
1232 SDL_FreeSurface(buf);
1233
1234 // reset time //
1235 T_Rst();
1236
1237 return ret;
1238 }
1239
1240 /*
1241 check if level set can be played and ask for confirmation if it got errors
1242 */
G_CkLSt()1243 int G_CkLSt()
1244 {
1245 char str[256];
1246 SFnt *ft = gm.f_sml;
1247 SDL_Event e;
1248
1249 if (gm.c_l_st->ch == 0) {
1250 D_FDST(sdl.scr);
1251 SS_Fill(0x0);
1252 sprintf(str, "This level set cannot be played.\n");
1253 ft->algn = TA_X_C | TA_Y_C;
1254 SF_Wrt(ft, sdl.scr, sdl.scr->w / 2, sdl.scr->h / 2, str, 0);
1255 Sdl_FUpd();
1256 Sdl_WtFrClk();
1257 return 0;
1258 }
1259 if (!gm.c_l_st->ok) {
1260 D_FDST(sdl.scr);
1261 SS_Fill(0x0);
1262 sprintf(str, "This level set has errors. Play anyway? (y/n)\n");
1263 ft->algn = TA_X_C | TA_Y_C;
1264 SF_Wrt(ft, sdl.scr, sdl.scr->w / 2, sdl.scr->h / 2, str, 0);
1265 Sdl_FUpd();
1266 while (1) {
1267 if (SDL_WaitEvent(&e))
1268 switch (e.type) {
1269 case SDL_KEYUP:
1270 switch (e.key.keysym.sym) {
1271 case SDLK_ESCAPE:
1272 case SDLK_n:
1273 return 0;
1274 case SDLK_y:
1275 return 1;
1276 default:
1277 break;
1278 }
1279 case SDL_MOUSEBUTTONUP:
1280 switch (e.button.button) {
1281 case 1:
1282 return 1;
1283 default:
1284 return 0;
1285 break;
1286 }
1287 break;
1288 }
1289 }
1290 }
1291 return 1;
1292 }
1293
1294 // marble //
1295 /*
1296 hide current marble
1297 */
Mr_Hd()1298 void Mr_Hd()
1299 {
1300 if (!gm.m_sel) return;
1301 D_DST(sdl.scr, (int)gm.m_x, (int)gm.m_y, gm.t_w, gm.t_h);
1302 D_SRC(gm.s_bkgd, (int)gm.m_x, (int)gm.m_y);
1303 SS_Blt();
1304 Sdl_AddR((int)gm.m_x, (int)gm.m_y, gm.t_w, gm.t_h);
1305 }
1306
1307 /*
1308 show current marble
1309 */
Mr_Shw()1310 void Mr_Shw()
1311 {
1312 if (!gm.m_sel) return;
1313 D_DST(sdl.scr, (int)gm.m_x, (int)gm.m_y, gm.t_w, gm.t_h);
1314 D_SRC(gm.s_mrb, (int)gm.m_a.p * gm.m_a.w, gm.m_id * gm.t_h);
1315 SS_Blt();
1316 Sdl_AddR((int)gm.m_x, (int)gm.m_y, gm.t_w, gm.t_h);
1317 }
1318
1319 /*
1320 update current marble
1321 return 0 if times out( moves )
1322 */
Mr_Upd(int ms)1323 int Mr_Upd(int ms)
1324 {
1325 float c; // change
1326 int stp = 0; // marble stopped ?
1327
1328 if (!gm.m_sel || !gm.m_mv) return 1;
1329
1330 // marble animation (frame)
1331 switch (gm.m_d) {
1332 case 1:
1333 case 2:
1334 gm.m_a.p += gm.m_a.c * ms;
1335 if (gm.m_a.p >= gm.m_a.f)
1336 gm.m_a.p = 0;
1337 break;
1338 case 0:
1339 case 3:
1340 gm.m_a.p -= gm.m_a.c * ms;
1341 if (gm.m_a.p <= 0)
1342 gm.m_a.p = gm.m_a.f;
1343 break;
1344 }
1345
1346 c = ms * gm.m_v;
1347 switch (gm.m_d) {
1348 case 0:
1349 gm.m_y -= c;
1350 if (gm.m_y <= gm.m_ty) {
1351 Mr_Stp();
1352 stp = 1;
1353 }
1354 break;
1355 case 1:
1356 gm.m_x += c;
1357 if (gm.m_x >= gm.m_tx) {
1358 Mr_Stp();
1359 stp = 1;
1360 }
1361 break;
1362 case 2:
1363 gm.m_y += c;
1364 if (gm.m_y >= gm.m_ty) {
1365 Mr_Stp();
1366 stp = 1;
1367 }
1368 break;
1369 case 3:
1370 gm.m_x -= c;
1371 if (gm.m_x <= gm.m_tx) {
1372 Mr_Stp();
1373 stp = 1;
1374 }
1375 break;
1376 }
1377
1378 // warp???
1379 if ( gm.m_warp ) {
1380 gm.m_x = gm.m_tx; gm.m_y = gm.m_ty;
1381 Mr_Stp();
1382 stp = 1;
1383 gm.m_warp = 0;
1384 }
1385
1386 // check time if move limit //
1387 if ( stp && gm.c_l_st->limit_type == MOVES &&
1388 gm.m_act != M_TLP_0 && gm.m_act != M_TLP_1 &&
1389 gm.m_act != M_TLP_2 && gm.m_act != M_TLP_3) {
1390
1391 gm.c_lvl->tm--;
1392 if ( gm.c_lvl->tm <= 0 && !gm.l_done /* completion with last move is okay */ )
1393 return 0;
1394
1395 }
1396
1397 // stopped and awaiting action ?
1398 if (stp && gm.m_act != M_EMPTY)
1399 Mr_Act();
1400 else
1401 if (stp) {
1402 #ifdef SOUND
1403 sound_play(gm.wv_stp);
1404 #endif
1405 }
1406
1407 return 1;
1408 }
1409
1410 /*
1411 select a marble
1412 */
Mr_Sel(int x,int y)1413 void Mr_Sel(int x, int y)
1414 {
1415 int mx, my;
1416
1417 mx = (x - gm.l_x) / gm.t_w;
1418 my = (y - gm.l_y) / gm.t_h;
1419
1420 if (gm.m_sel) {
1421 gm.mf_a.p = gm.msf_a.p = 0;
1422 Mr_Ins();
1423 }
1424
1425 // set selected
1426 gm.m_sel = 1;
1427 // get map position
1428 gm.m_mx = mx;
1429 gm.m_my = my;
1430 // check valid moving directions
1431 Mr_CkVDir(mx, my);
1432 // delete marble from background
1433 L_DrwMpTl(mx, my);
1434 // get position in screen
1435 gm.m_x = mx * gm.t_w + gm.l_x;
1436 gm.m_y = my * gm.t_h + gm.l_y;
1437 // get id //
1438 gm.m_id = gm.c_lvl->map[mx][my].m;
1439 // delete marble from map
1440 gm.c_lvl->map[mx][my].m = -1;
1441 // save old position
1442 gm.m_o_x = (int)gm.m_x;
1443 gm.m_o_y = (int)gm.m_y;
1444 gm.m_o_move_count = gm.c_lvl->tm;
1445
1446 #ifdef SOUND
1447 sound_play(gm.wv_sel);
1448 #endif
1449 }
1450
1451 /*
1452 release a marble
1453 */
Mr_Rel(int x,int y)1454 void Mr_Rel(int x, int y)
1455 {
1456 Mr_Ins();
1457 gm.m_sel = 0;
1458 SDL_SetCursor(gm.c_n);
1459 gm.m_o_x = gm.m_o_y = -1;
1460 }
1461
1462 /*
1463 initialize movement
1464 */
Mr_IniMv()1465 void Mr_IniMv()
1466 {
1467 int x_a = 0, y_a = 0, tx, ty;
1468 int t_fnd = 0;
1469
1470 // direction
1471 gm.m_d = gm.c_stat -2;
1472 if (gm.m_d < 0 || gm.m_d > 4)
1473 return;
1474
1475 // direction verified; activate movement
1476 gm.m_mv = 1;
1477
1478 // store position if no action
1479 if ( gm.m_act == M_EMPTY ) {
1480 gm.m_o_x = (int)gm.m_x;
1481 gm.m_o_y = (int)gm.m_y;
1482 gm.m_o_move_count = gm.c_lvl->tm;
1483 }
1484
1485 // clear previous action
1486 gm.m_act = M_EMPTY;
1487
1488 // compute target position
1489 switch (gm.m_d) {
1490 case 0: y_a = -1; break;
1491 case 1: x_a = 1; break;
1492 case 2: y_a = 1; break;
1493 case 3: x_a = -1; break;
1494 }
1495 tx = gm.m_mx + x_a; ty = gm.m_my + y_a;
1496 while ( // target already found
1497 !t_fnd &&
1498 // wall
1499 gm.c_lvl->map[tx][ty].t != M_WALL &&
1500 // crumbling wall
1501 gm.c_lvl->map[tx][ty].t != M_CRUMBLE &&
1502 // marble
1503 gm.c_lvl->map[tx][ty].m == -1 &&
1504 // up
1505 !((gm.c_lvl->map[tx][ty].t == M_OW_D || gm.c_lvl->map[tx][ty].t == M_OW_D_C || gm.c_lvl->map[tx][ty].t == M_OW_L_C || gm.c_lvl->map[tx][ty].t == M_OW_R_C) && y_a == -1) &&
1506 // down
1507 !((gm.c_lvl->map[tx][ty].t == M_OW_U || gm.c_lvl->map[tx][ty].t == M_OW_U_C || gm.c_lvl->map[tx][ty].t == M_OW_L_C || gm.c_lvl->map[tx][ty].t == M_OW_R_C) && y_a == 1) &&
1508 // right
1509 !((gm.c_lvl->map[tx][ty].t == M_OW_L || gm.c_lvl->map[tx][ty].t == M_OW_L_C || gm.c_lvl->map[tx][ty].t == M_OW_U_C || gm.c_lvl->map[tx][ty].t == M_OW_D_C) && x_a == 1) &&
1510 // left
1511 !((gm.c_lvl->map[tx][ty].t == M_OW_R || gm.c_lvl->map[tx][ty].t == M_OW_R_C || gm.c_lvl->map[tx][ty].t == M_OW_U_C || gm.c_lvl->map[tx][ty].t == M_OW_D_C) && x_a == -1)
1512 ) {
1513
1514 // check action
1515 switch (gm.c_lvl->map[tx][ty].t) {
1516 case M_TLP_0:
1517 case M_TLP_1:
1518 case M_TLP_2:
1519 case M_TLP_3:
1520 t_fnd = 1;
1521 gm.m_act = gm.c_lvl->map[tx][ty].t;
1522 break;
1523 case M_OW_U:
1524 if (y_a != -1) {
1525 gm.m_act = M_OW_U;
1526 t_fnd = 1;
1527 }
1528 break;
1529 case M_OW_D:
1530 if (y_a != 1) {
1531 gm.m_act = M_OW_D;
1532 t_fnd = 1;
1533 }
1534 break;
1535 case M_OW_L:
1536 if (x_a != -1) {
1537 gm.m_act = M_OW_L;
1538 t_fnd = 1;
1539 }
1540 break;
1541 case M_OW_R:
1542 if (x_a != 1) {
1543 gm.m_act = M_OW_R;
1544 t_fnd = 1;
1545 }
1546 break;
1547 }
1548 tx += x_a;
1549 ty += y_a;
1550 }
1551
1552 // crumbling wall
1553 if (gm.c_lvl->map[tx][ty].t == M_CRUMBLE)
1554 gm.m_act = M_CRUMBLE;
1555
1556 tx -= x_a;
1557 ty -= y_a;
1558
1559 gm.m_tx = tx * gm.t_w + gm.l_x;
1560 gm.m_ty = ty * gm.t_h + gm.l_y;
1561
1562 // wait cursor
1563 SDL_SetCursor(gm.c_w);
1564 }
1565
1566 /*
1567 stop a marble
1568 */
Mr_Stp()1569 void Mr_Stp()
1570 {
1571 int mx, my;
1572
1573 // position in screen
1574 gm.m_x = gm.m_tx;
1575 gm.m_y = gm.m_ty;
1576
1577 mx = (gm.m_x - gm.l_x) / gm.t_w;
1578 my = (gm.m_y - gm.l_y) / gm.t_h;
1579
1580 // position in map
1581 gm.m_mx = mx;
1582 gm.m_my = my;
1583
1584 // check valid moving directions
1585 Mr_CkVDir(mx, my);
1586
1587 gm.m_mv = 0;
1588 gm.m_a.p = 0;
1589
1590 // check cursor //
1591 Cr_Cng(gm.o_mx, gm.o_my);
1592
1593 // if no action check if the figure is completed
1594 if (gm.m_act == M_EMPTY || gm.m_act == M_CRUMBLE) {
1595
1596 gm.c_lvl->map[mx][my].m = gm.m_id;
1597 G_CkFgr();
1598 gm.c_lvl->map[mx][my].m = -1;
1599 }
1600 }
1601
1602 /*
1603 insert a marble into map
1604 */
Mr_Ins()1605 void Mr_Ins()
1606 {
1607 int mx, my, x, y;
1608
1609 mx = (gm.m_x - gm.l_x) / gm.t_w;
1610 my = (gm.m_y - gm.l_y) / gm.t_h;
1611 x = mx * gm.t_w + gm.l_x;
1612 y = my * gm.t_h + gm.l_y;
1613
1614 //hide frame
1615 MF_Hd();
1616 // draw to background
1617 D_DST(gm.s_bkgd, x, y, gm.t_w, gm.t_h);
1618 D_SRC(gm.s_mrb, 0, gm.m_id * gm.t_h);
1619 SS_Blt();
1620 // to screen
1621 D_DST(sdl.scr, x, y, gm.t_w, gm.t_h);
1622 D_SRC(gm.s_mrb, 0, gm.m_id * gm.t_h);
1623 SS_Blt();
1624 // and to map
1625 gm.c_lvl->map[mx][my].m = gm.m_id;
1626 }
1627
1628 /*
1629 check valid directions
1630 */
Mr_CkVDir(int mx,int my)1631 void Mr_CkVDir(int mx, int my)
1632 {
1633 gm.m_vd = 0;
1634 if ( gm.c_lvl->map[mx][my].t != M_OW_D_C && gm.c_lvl->map[mx][my].t != M_OW_U_C && gm.c_lvl->map[mx - 1][my].t != M_WALL && gm.c_lvl->map[mx - 1][my].t != M_CRUMBLE && gm.c_lvl->map[mx - 1][my].m == -1 && gm.c_lvl->map[mx - 1][my].t != M_OW_R && gm.c_lvl->map[mx - 1][my].t != M_OW_R_C && gm.c_lvl->map[mx - 1][my].t != M_OW_U_C && gm.c_lvl->map[mx - 1][my].t != M_OW_D_C)
1635 gm.m_vd = gm.m_vd | MD_L;
1636 if ( gm.c_lvl->map[mx][my].t != M_OW_D_C && gm.c_lvl->map[mx][my].t != M_OW_U_C && gm.c_lvl->map[mx + 1][my].t != M_WALL && gm.c_lvl->map[mx + 1][my].t != M_CRUMBLE && gm.c_lvl->map[mx + 1][my].m == -1 && gm.c_lvl->map[mx + 1][my].t != M_OW_L && gm.c_lvl->map[mx + 1][my].t != M_OW_L_C && gm.c_lvl->map[mx + 1][my].t != M_OW_U_C && gm.c_lvl->map[mx + 1][my].t != M_OW_D_C)
1637 gm.m_vd = gm.m_vd | MD_R;
1638 if ( gm.c_lvl->map[mx][my].t != M_OW_L_C && gm.c_lvl->map[mx][my].t != M_OW_R_C && gm.c_lvl->map[mx][my - 1].t != M_WALL && gm.c_lvl->map[mx][my - 1].t != M_CRUMBLE && gm.c_lvl->map[mx][my - 1].m == -1 && gm.c_lvl->map[mx][my - 1].t != M_OW_D && gm.c_lvl->map[mx][my - 1].t != M_OW_D_C && gm.c_lvl->map[mx][my - 1].t != M_OW_L_C && gm.c_lvl->map[mx][my - 1].t != M_OW_R_C)
1639 gm.m_vd = gm.m_vd | MD_U;
1640 if ( gm.c_lvl->map[mx][my].t != M_OW_L_C && gm.c_lvl->map[mx][my].t != M_OW_R_C && gm.c_lvl->map[mx][my + 1].t != M_WALL && gm.c_lvl->map[mx][my + 1].t != M_CRUMBLE && gm.c_lvl->map[mx][my + 1].m == -1 && gm.c_lvl->map[mx][my + 1].t != M_OW_U && gm.c_lvl->map[mx][my + 1].t != M_OW_U_C && gm.c_lvl->map[mx][my + 1].t != M_OW_L_C && gm.c_lvl->map[mx][my + 1].t != M_OW_R_C)
1641 gm.m_vd = gm.m_vd | MD_D;
1642 }
1643
1644 /*
1645 handle actions!
1646 */
Mr_Act()1647 void Mr_Act()
1648 {
1649 int x_a = 0, y_a = 0, ow = 0, mx = gm.m_mx, my = gm.m_my, tx, ty;
1650 int i, j;
1651
1652 // crumbling wall ?
1653 if (gm.m_act == M_CRUMBLE) {
1654 tx = mx + (gm.m_d == 1 ? 1 : gm.m_d == 3 ? -1 : 0);
1655 ty = my + (gm.m_d == 0 ? -1 : gm.m_d == 2 ? 1 : 0);
1656 if (gm.c_lvl->map[tx][ty].t == M_CRUMBLE) {
1657 #ifdef SOUND
1658 sound_play(gm.wv_stp);
1659 #endif
1660 if (gm.c_lvl->map[tx][ty].id > 0)
1661 gm.c_lvl->map[tx][ty].id--;
1662 else {
1663 Wl_Exp(gm.l_x + tx * gm.t_w, gm.l_y + ty * gm.t_h, gm.m_d);
1664 gm.c_lvl->map[tx][ty].t = M_FLOOR;
1665 // check moving direction
1666 Mr_CkVDir(gm.m_mx, gm.m_my);
1667 Cr_Cng(gm.o_mx, gm.o_my);
1668 // reset restore position
1669 gm.m_o_x = gm.m_tx;
1670 gm.m_o_y = gm.m_ty;
1671 gm.m_o_move_count = gm.c_lvl->tm;
1672 #ifdef SOUND
1673 sound_play(gm.wv_exp);
1674 #endif
1675 }
1676 // draw to background
1677 L_DrwMpTl(tx, ty);
1678 // draw to screen
1679 D_DST(sdl.scr, gm.l_x + tx * gm.t_w, gm.l_y + ty * gm.t_h, gm.t_w, gm.t_h);
1680 D_SRC(gm.s_bkgd, gm.l_x + tx * gm.t_w, gm.l_y + ty * gm.t_h);
1681 SS_Blt();
1682 // add refresh rect
1683 Sdl_AddR(gm.l_x + tx * gm.t_w, gm.l_y + ty * gm.t_h, gm.t_w, gm.t_h);
1684 }
1685 // no action
1686 // gm.m_act = M_EMPTY;
1687 return;
1688 }
1689
1690 // oneway ?
1691 switch (gm.m_act) {
1692 case M_OW_U:
1693 y_a = -1;
1694 ow = 1;
1695 gm.c_stat = C_U;
1696 break;
1697 case M_OW_D:
1698 y_a = 1;
1699 ow = 1;
1700 gm.c_stat = C_D;
1701 break;
1702 case M_OW_R:
1703 x_a = 1;
1704 ow = 1;
1705 gm.c_stat = C_R;
1706 break;
1707 case M_OW_L:
1708 x_a = -1;
1709 ow = 1;
1710 gm.c_stat = C_L;
1711 break;
1712 }
1713 if (ow) {
1714 /* mx += x_a; my += y_a;
1715 while (gm.c_lvl->map[mx][my].m != -1) {
1716 mx += x_a;
1717 my += y_a;
1718 }
1719 mx -= x_a; my -= y_a;
1720 if (mx != gm.m_mx || my != gm.m_my) {
1721 Mr_Ins();
1722 Mr_Sel(gm.l_x + mx * gm.t_w, gm.l_y + my * gm.t_h);
1723 }*/
1724 #ifdef SOUND
1725 sound_play(gm.wv_arw);
1726 #endif
1727 Mr_IniMv();
1728 return;
1729 }
1730
1731 // teleport ?
1732 if (gm.m_act >= M_TLP_0 && gm.m_act <= M_TLP_3) {
1733 for (i = 0; i < gm.c_lvl->m_w; i++) {
1734 for (j = 0; j < gm.c_lvl->m_h; j++)
1735 if (gm.c_lvl->map[i][j].t == gm.m_act && (i != gm.m_mx || j != gm.m_my)) {
1736 // only warp if destination is empty //
1737 if (gm.c_lvl->map[i][j].m == -1) {
1738 gm.m_mx = i;
1739 gm.m_my = j;
1740 gm.m_x = gm.m_mx * gm.t_w + gm.l_x;
1741 gm.m_y = gm.m_my * gm.t_h + gm.l_y;
1742 #ifdef SOUND
1743 sound_play(gm.wv_tlp);
1744 #endif
1745 }
1746 gm.c_stat = gm.m_d + 2; // restore c_stat for movement initialization
1747 // initate movement
1748 Mr_IniMv();
1749
1750 /* // check if the figure is completed
1751 gm.c_lvl->map[gm.m_mx][gm.m_my].m = gm.m_id;
1752 G_CkFgr();
1753 gm.c_lvl->map[gm.m_mx][gm.m_my].m = -1;*/
1754
1755 return;
1756 }
1757 }
1758 }
1759
1760 // gm.m_act = M_EMPTY;
1761 }
1762
1763 /*
1764 restore old position
1765 */
Mr_ResPos()1766 void Mr_ResPos()
1767 {
1768 if ( !gm.m_sel || gm.m_o_x == -1 ) return;
1769
1770 gm.m_act = M_EMPTY;
1771 gm.m_tx = gm.m_o_x;
1772 gm.m_ty = gm.m_o_y;
1773 if ( gm.c_l_st->limit_type == MOVES )
1774 gm.c_lvl->tm = gm.m_o_move_count;
1775 Mr_Stp();
1776 }
1777
1778 // timer //
1779 /*
1780 hide time
1781 */
Tm_Hd()1782 void Tm_Hd()
1783 {
1784 int w = gm.brd_w - gm.t_x * 2;
1785 int h = gm.f_wht->h;
1786
1787 D_DST(sdl.scr, gm.t_x + gm.b_x, gm.t_y, w, h);
1788 D_SRC(gm.s_bkgd, gm.t_x + gm.b_x, gm.t_y);
1789 SS_Blt();
1790 Sdl_AddR(gm.t_x + gm.b_x, gm.t_y, w, h);
1791 }
1792
1793 /*
1794 show time
1795 */
Tm_Shw()1796 void Tm_Shw()
1797 {
1798 SFnt *ft;
1799 char str_tm[16];
1800 char str_sec[4];
1801 int tm;
1802
1803 // adjust time //
1804 if ( gm.c_l_st->limit_type == TIME )
1805 tm = gm.c_lvl->tm / 1000;
1806 else
1807 tm = gm.c_lvl->tm;
1808
1809 // select font
1810 ft = gm.f_wht;
1811 if ( gm.c_l_st->limit_type == TIME && tm <= 30 )
1812 ft = gm.f_rd;
1813 else
1814 if ( gm.c_l_st->limit_type == MOVES && tm <= 10 )
1815 ft = gm.f_rd;
1816
1817 // draw "time"
1818 ft->algn = TA_X_L | TA_Y_T;
1819 if ( gm.c_l_st->limit_type == TIME )
1820 SF_Wrt(ft, sdl.scr, gm.t_x + gm.b_x, gm.t_y, "Time:", 0);
1821 else
1822 SF_Wrt(ft, sdl.scr, gm.t_x + gm.b_x, gm.t_y, "Moves:", 0);
1823
1824 // compute and draw time str
1825 if ( gm.c_l_st->limit_type == TIME ) {
1826
1827 sprintf(str_tm, "%i:", tm / 60);
1828 sprintf(str_sec, "%i", tm % 60);
1829 if (strlen(str_sec) < 2)
1830 strcat(str_tm, "0");
1831 strcat(str_tm, str_sec);
1832
1833 }
1834 else
1835 sprintf( str_tm, "%i", tm );
1836
1837 ft->algn = TA_X_R | TA_Y_T;
1838 SF_Wrt(ft, sdl.scr, gm.scr_w - gm.t_x, gm.t_y, str_tm, 0);
1839
1840 Sdl_AddR(gm.t_x + gm.b_x, gm.t_y, gm.b_x - gm.t_x*2, ft->h);
1841 }
1842
1843 /*
1844 update time
1845 return 0 if time out
1846 */
Tm_Upd(int ms)1847 int Tm_Upd(int ms)
1848 {
1849 #ifdef SOUND
1850 int old_sec = gm.c_lvl->tm / 1000;
1851 #endif
1852
1853 gm.blink_time += ms;
1854
1855 // if limit_type is MOVES, time is ignored //
1856 if ( gm.c_l_st->limit_type == MOVES ) return 1;
1857
1858 gm.c_lvl->tm -= ms;
1859
1860 // new second ?
1861 #ifdef SOUND
1862 if ( old_sec != gm.c_lvl->tm / 1000 && old_sec <= 30 )
1863 sound_play(gm.wv_alm);
1864 #endif
1865
1866 if (gm.c_lvl->tm < 0) {
1867 gm.c_lvl->tm = 0;
1868 return 0;
1869 }
1870 return 1;
1871 }
1872
1873 // level info //
1874 /*
1875 hide level info
1876 */
Inf_Hd()1877 void Inf_Hd()
1878 {
1879 D_DST(sdl.scr, gm.b_x + gm.s_x, gm.s_y + gm.s_h - 20, gm.s_w, 20);
1880 D_SRC(gm.s_bkgd, gm.b_x + gm.s_x, gm.s_y + gm.s_h - 20);
1881 SS_Blt();
1882 Sdl_AddR(gm.b_x + gm.s_x, gm.s_y + gm.s_h - 20, gm.s_w, 20);
1883 }
1884
1885 /*
1886 update level info
1887 */
Inf_Upd()1888 int Inf_Upd()
1889 {
1890 int x, y;
1891
1892 x = (gm.o_mx - gm.c_x - gm.b_x) / L_SIZE;
1893 y = (gm.o_my - gm.c_y) / L_SIZE;
1894
1895 if (gm.o_mx < gm.c_x + gm.b_x || gm.o_my < gm.c_y || x >= gm.c_l_st->l_num || y >= gm.c_l_st->c_num) {
1896 sprintf(gm.inf_str, "Tier %i, Puzzle %i", gm.c_ch + 1, gm.c_l_id + 1);
1897 return 0;
1898 }
1899 if (!gm.c_s_inf->cmp[y * gm.c_s_inf->l_num + x] && !gm.c_s_inf->c_opn[y]) {
1900 sprintf(gm.inf_str, "Access Denied");
1901 return 0;
1902 }
1903 sprintf(gm.inf_str, "Tier %i, Puzzle %i", y + 1, x + 1);
1904 if (gm.bttn[1]) {
1905 gm.w_c = y;
1906 gm.w_l = x;
1907 return 1;
1908 }
1909 return 0;
1910 }
1911
1912 /*
1913 show level info
1914 */
Inf_Shw()1915 void Inf_Shw()
1916 {
1917 gm.f_sml->algn = TA_X_C | TA_Y_B;
1918 SF_Wrt(gm.f_sml, sdl.scr, gm.b_x + gm.brd_w / 2, gm.s_y + gm.s_h - 5, gm.inf_str, 0);
1919 }
1920
1921 // cursor
1922 /*
1923 load cursor
1924 */
Cr_Ld(char * src,char * d,char * m)1925 void Cr_Ld(char *src, char *d, char*m)
1926 {
1927 int w=16, h = 16;
1928 int i, j, k;
1929 char b_d, b_m;
1930 int p;
1931
1932 k = 0;
1933 for (j = 0; j < w * h; j += 8, k++) {
1934 p = 1;
1935 b_d = b_m = 0;
1936 // create byte
1937 for (i = 7; i >= 0; i--) {
1938 switch (src[j + i]) {
1939 case 2:
1940 b_d += p;
1941 case 1:
1942 b_m += p;
1943 break;
1944 }
1945 p *= 2;
1946 }
1947 // add to mask
1948 d[k] = b_d;
1949 m[k] = b_m;
1950 }
1951 }
1952
1953 /*
1954 change cursors appearing
1955 */
Cr_Cng(int x,int y)1956 void Cr_Cng(int x, int y)
1957 {
1958 int mx, my, cx, cy;
1959
1960 if (gm.m_mv) {
1961 if (x > gm.scr_w - gm.brd_w)
1962 SDL_SetCursor(gm.c_n);
1963 else
1964 SDL_SetCursor(gm.c_w);
1965 return;
1966 }
1967
1968 mx = (x - gm.l_x) / gm.t_w;
1969 my = (y - gm.l_y) / gm.t_h;
1970
1971 if ( mx >= 0 && my >= 0 && mx < gm.c_lvl->m_w && my < gm.c_lvl->m_h
1972 && (gm.c_lvl->map[mx][my].m != - 1 || (gm.m_mx == mx && gm.m_my == my))) {
1973 // on marble
1974 SDL_SetCursor(gm.c_s);
1975 gm.c_stat = C_SEL;
1976 }
1977 else
1978 if (!gm.m_sel || x > gm.scr_w - gm.brd_w) {
1979 // nothing selected
1980 SDL_SetCursor(gm.c_n);
1981 gm.c_stat = C_NONE;
1982 }
1983 else {
1984 // up, left, right, down
1985 cx = x - (gm.m_mx * gm.t_w + gm.l_x + gm.t_w / 2);
1986 cy = y - (gm.m_my * gm.t_h + gm.l_y + gm.t_h / 2);
1987 if (abs(cx) > abs(cy)) {
1988 if (cx > 0) {
1989 if (gm.m_vd & MD_R) {
1990 SDL_SetCursor(gm.c_r);
1991 gm.c_stat = C_R;
1992 }
1993 else {
1994 SDL_SetCursor(gm.c_n);
1995 gm.c_stat = C_NONE;
1996 }
1997 }
1998 else {
1999 if (gm.m_vd & MD_L) {
2000 SDL_SetCursor(gm.c_l);
2001 gm.c_stat = C_L;
2002 }
2003 else {
2004 SDL_SetCursor(gm.c_n);
2005 gm.c_stat = C_NONE;
2006 }
2007 }
2008 }
2009 else {
2010 if (cy > 0) {
2011 if (gm.m_vd & MD_D) {
2012 SDL_SetCursor(gm.c_d);
2013 gm.c_stat = C_D;
2014 }
2015 else {
2016 SDL_SetCursor(gm.c_n);
2017 gm.c_stat = C_NONE;
2018 }
2019 }
2020 else {
2021 if (gm.m_vd & MD_U) {
2022 SDL_SetCursor(gm.c_u);
2023 gm.c_stat = C_U;
2024 }
2025 else {
2026 SDL_SetCursor(gm.c_n);
2027 gm.c_stat = C_NONE;
2028 }
2029 }
2030 }
2031 }
2032 }
2033
2034 // frame //
2035 /*
2036 hide marble frame
2037 */
MF_Hd()2038 void MF_Hd()
2039 {
2040 int x, y, w, h;
2041
2042 if (!gm.m_sel) return;
2043
2044 // get size
2045 if (gm.msf_a.p == gm.msf_a.f) {
2046 w = gm.mf_a.w;
2047 h = gm.mf_a.h;
2048 }
2049 else {
2050 w = gm.msf_a.w;
2051 h = gm.msf_a.h;
2052 }
2053
2054 // get position
2055 x = gm.m_x + (gm.t_w - w) / 2;
2056 y = gm.m_y + (gm.t_h - h) / 2;
2057
2058 // hide
2059 D_DST(sdl.scr, x, y, w, h);
2060 D_SRC(gm.s_bkgd, x, y);
2061 SS_Blt();
2062 Sdl_AddR(x - 1, y - 1, w + 1, h + 1);
2063 }
2064
2065 /*
2066 update marble frame
2067 */
MF_Upd(int ms)2068 void MF_Upd(int ms)
2069 {
2070 if (!gm.m_sel) {
2071 gm.mf_a.p = gm.msf_a.p = 0;
2072 return;
2073 }
2074 if (gm.msf_a.p != gm.msf_a.f) {
2075 // still select animation
2076 gm.msf_a.p += gm.msf_a.c * ms;
2077 if (gm.msf_a.p >= gm.msf_a.f)
2078 gm.msf_a.p = gm.msf_a.f;
2079 }
2080 else {
2081 gm.mf_a.p += gm.mf_a.c * ms;
2082 if (gm.mf_a.p >= gm.mf_a.f)
2083 gm.mf_a.p = 0;
2084 }
2085 }
2086
2087 /*
2088 show marble frame
2089 */
MF_Shw()2090 void MF_Shw()
2091 {
2092 int x, y;
2093 AInf *a;
2094 SDL_Surface *s;
2095
2096 if (!gm.m_sel) return;
2097
2098 // get animation info
2099 if (gm.msf_a.p == gm.msf_a.f) {
2100 a = &gm.mf_a;
2101 s = gm.s_mf;
2102 }
2103 else {
2104 a = &gm.msf_a;
2105 s = gm.s_msf;
2106 }
2107
2108 // get position
2109 x = gm.m_x + (gm.t_w - a->w) / 2;
2110 y = gm.m_y + (gm.t_h - a->h) / 2;
2111
2112 // show
2113 D_DST(sdl.scr, x, y, a->w, a->h);
2114 D_SRC(s, (int)a->p * a->w, 0);
2115 SS_Blt();
2116 Sdl_AddR(x, y, a->w, a->h);
2117 }
2118
2119 // map animations //
2120 /*
2121 get position and type of all animations
2122 */
MA_Ini()2123 void MA_Ini()
2124 {
2125 int i, j;
2126
2127 // free and reallocate m_ani
2128 if (gm.m_ani)
2129 free(gm.m_ani);
2130 gm.m_ani = (MAni*)malloc(sizeof(MAni) * gm.c_lvl->m_w * gm.c_lvl->m_h);
2131 gm.ma_num = 0;
2132
2133 // parse level map
2134 for (i = 0; i < gm.c_lvl->m_w; i++)
2135 for (j = 0; j < gm.c_lvl->m_h; j++)
2136 switch (gm.c_lvl->map[i][j].t) {
2137 case M_OW_U:
2138 case M_OW_D:
2139 case M_OW_L:
2140 case M_OW_R:
2141 case M_OW_U_C:
2142 case M_OW_D_C:
2143 case M_OW_L_C:
2144 case M_OW_R_C:
2145 gm.m_ani[gm.ma_num].x = i;
2146 gm.m_ani[gm.ma_num].y = j;
2147 gm.m_ani[gm.ma_num].t = gm.c_lvl->map[i][j].t;
2148 gm.m_ani[gm.ma_num].a = &gm.ma_ow_a;
2149 gm.ma_num++;
2150 break;
2151 case M_TLP_0:
2152 case M_TLP_1:
2153 case M_TLP_2:
2154 case M_TLP_3:
2155 gm.m_ani[gm.ma_num].x = i;
2156 gm.m_ani[gm.ma_num].y = j;
2157 gm.m_ani[gm.ma_num].t = gm.c_lvl->map[i][j].t;
2158 gm.m_ani[gm.ma_num].a = &gm.ma_tlp_a;
2159 gm.ma_num++;
2160 break;
2161 default:
2162 break;
2163 }
2164 }
2165
MA_Upd(int ms)2166 void MA_Upd(int ms)
2167 {
2168 if (!cfg.ani) return;
2169
2170 gm.ma_ow_a.p += (float)ms * gm.ma_ow_a.c;
2171 if (gm.ma_ow_a.p >= gm.ma_ow_a.f)
2172 gm.ma_ow_a.p = 0;
2173
2174 gm.ma_tlp_a.p += (float)ms * gm.ma_tlp_a.c;
2175 if (gm.ma_tlp_a.p >= gm.ma_tlp_a.f)
2176 gm.ma_tlp_a.p = 0;
2177 }
2178
2179 /*
2180 show map animations
2181 */
MA_Shw()2182 void MA_Shw()
2183 {
2184 int i;
2185 int x, y;
2186
2187 if (!cfg.ani) return;
2188
2189 for (i = 0; i < gm.ma_num; i++) {
2190 // get position in screen
2191 x = gm.l_x + gm.m_ani[i].x * gm.t_w;
2192 y = gm.l_y + gm.m_ani[i].y * gm.t_h;
2193
2194 // draw empty floor
2195 D_DST(sdl.scr, x, y, gm.t_w, gm.t_h);
2196 D_SRC(gm.c_g_st->s_flr, 0, 0);
2197 SS_Blt();
2198
2199 // oneway
2200 D_DST(sdl.scr, x, y, gm.t_w, gm.t_h);
2201 switch (gm.m_ani[i].t) {
2202 case M_OW_R:
2203 case M_OW_R_C:
2204 D_SRC(gm.c_g_st->s_r_arw, (int)gm.m_ani[i].a->p * gm.t_w, 0);
2205 SS_Blt();
2206 break;
2207 case M_OW_L:
2208 case M_OW_L_C:
2209 D_SRC(gm.c_g_st->s_l_arw, (int)gm.m_ani[i].a->p * gm.t_w, 0);
2210 SS_Blt();
2211 break;
2212 case M_OW_U:
2213 case M_OW_U_C:
2214 D_SRC(gm.c_g_st->s_u_arw, 0, (int)gm.m_ani[i].a->p * gm.t_h);
2215 SS_Blt();
2216 break;
2217 case M_OW_D:
2218 case M_OW_D_C:
2219 D_SRC(gm.c_g_st->s_d_arw, 0, (int)gm.m_ani[i].a->p * gm.t_h);
2220 SS_Blt();
2221 break;
2222 }
2223 D_DST(sdl.scr, x, y, gm.t_w, gm.t_h);
2224 switch (gm.m_ani[i].t) {
2225 case M_OW_U_C:
2226 case M_OW_D_C:
2227 D_SRC(gm.c_g_st->s_lr_bar, 0, 0);
2228 SS_Blt();
2229 break;
2230 case M_OW_L_C:
2231 case M_OW_R_C:
2232 D_SRC(gm.c_g_st->s_ud_bar, 0, 0);
2233 SS_Blt();
2234 break;
2235 }
2236
2237 // teleport
2238 D_DST(sdl.scr, x, y, gm.t_w, gm.t_h);
2239 switch (gm.m_ani[i].t) {
2240 case M_TLP_0:
2241 D_SRC(gm.c_g_st->s_tlp_0, (int)gm.m_ani[i].a->p * gm.t_w, 0);
2242 SS_ABlt(gm.tlp_a);
2243 break;
2244 case M_TLP_1:
2245 D_SRC(gm.c_g_st->s_tlp_1, (int)gm.m_ani[i].a->p * gm.t_w, 0);
2246 SS_ABlt(gm.tlp_a);
2247 break;
2248 case M_TLP_2:
2249 D_SRC(gm.c_g_st->s_tlp_2, (int)gm.m_ani[i].a->p * gm.t_w, 0);
2250 SS_ABlt(gm.tlp_a);
2251 break;
2252 case M_TLP_3:
2253 D_SRC(gm.c_g_st->s_tlp_3, (int)gm.m_ani[i].a->p * gm.t_w, 0);
2254 SS_ABlt(gm.tlp_a);
2255 break;
2256 }
2257
2258 // marble on animation
2259 if (gm.c_lvl->map[gm.m_ani[i].x][gm.m_ani[i].y].m != -1 &&
2260 ( ((gm.blink_time / 250) & 1) || gm.l_done ) ) {
2261 D_DST(sdl.scr, x, y, gm.t_w, gm.t_h);
2262 D_SRC(gm.s_mrb, 0, gm.c_lvl->map[gm.m_ani[i].x][gm.m_ani[i].y].m * gm.t_w);
2263 SS_Blt();
2264 }
2265
2266 // refresh rect
2267 Sdl_AddR(x, y, gm.t_w, gm.t_h);
2268 }
2269 }
2270
2271 // shrapnells //
2272 /*
2273 add new shrapnell
2274 */
Shr_Add(int x,int y,int w,int h,Vec d,SDL_Surface * s_shr)2275 void Shr_Add(int x, int y, int w, int h, Vec d, SDL_Surface *s_shr)
2276 {
2277 Shr *s;
2278
2279 s = (Shr*)malloc(sizeof(Shr));
2280 s->d = d;
2281 s->x = x;
2282 s->y = y;
2283 s->w = w;
2284 s->h = h;
2285 s->a = 0;
2286 if ( s_shr )
2287 s->s_shr = s_shr;
2288 else {
2289
2290 s->s_shr = SS_Crt(w, h, SDL_SWSURFACE);
2291 D_DST(s->s_shr, 0, 0, w, h);
2292 D_SRC(sdl.scr, x, y);
2293 SS_Blt();
2294
2295 }
2296
2297 DL_Add(&gm.shr, s);
2298 }
2299
2300 /*
2301 delete shrapnell
2302 */
Shr_Del(void * p)2303 void Shr_Del(void *p)
2304 {
2305 Shr *s = (Shr*)p;
2306 if ( s->s_shr ) SDL_FreeSurface(s->s_shr);
2307 free(p);
2308 }
2309
2310 /*
2311 hide shrapnell
2312 */
Shr_Hd()2313 void Shr_Hd()
2314 {
2315 DL_E *e = gm.shr.hd.n;
2316 Shr *s;
2317
2318 while ( e != &gm.shr.tl ) {
2319
2320 s = (Shr*)e->d;
2321
2322 D_DST(sdl.scr, (int)s->x, (int)s->y, s->w, s->h);
2323 D_SRC(gm.s_bkgd, (int)s->x, (int)s->y);
2324 SS_Blt();
2325 Sdl_AddR((int)s->x, (int)s->y, s->w, s->h);
2326
2327 e = e->n;
2328
2329 }
2330
2331 }
2332
2333 /*
2334 update shrapnell
2335 */
Shr_Upd(int ms)2336 void Shr_Upd(int ms)
2337 {
2338 DL_E *n, *e = gm.shr.hd.n;
2339 Shr *s;
2340
2341 while ( e != &gm.shr.tl ) {
2342
2343 n = e->n;
2344
2345 s = (Shr*)e->d;
2346
2347 s->x += s->d.x * (float)ms;
2348 s->y += s->d.y * (float)ms;
2349 s->a += gm.shr_a_c * (float)ms;
2350
2351 if (s->a >= 255)
2352 DL_DelE(&gm.shr, e);
2353
2354 e = n;
2355
2356 }
2357 }
2358
2359 /*
2360 show shrapnell
2361 */
Shr_Shw()2362 void Shr_Shw()
2363 {
2364 DL_E *e = gm.shr.hd.n;
2365 Shr *s;
2366
2367 while ( e != &gm.shr.tl ) {
2368
2369 s = (Shr*)e->d;
2370
2371 D_DST(sdl.scr, (int)s->x, (int)s->y, s->w, s->h);
2372 D_SRC(s->s_shr, 0, 0);
2373 SS_ABlt(s->a);
2374 Sdl_AddR((int)s->x, (int)s->y, s->w, s->h);
2375
2376 e = e->n;
2377
2378 }
2379
2380 }
2381
2382 // wall //
2383 /*
2384 explode crumble wall into lot of pieces
2385 */
Wl_Exp(int x,int y,int d)2386 void Wl_Exp(int x, int y, int d)
2387 {
2388 int i, j;
2389 int sz = 4;
2390 Vec v;
2391 int x_r, x_off, y_r, y_off; // direction values
2392 SDL_Surface *s_shr;
2393
2394 if ( !cfg.ani ) return;
2395
2396 x_r = y_r = 200;
2397 x_off = y_off = 100;
2398
2399 // adjust direction values
2400 switch (d) {
2401
2402 case 0:
2403 y_r = y_off = 100;
2404 break;
2405
2406 case 1:
2407 x_r = 100;
2408 x_off = 0;
2409 break;
2410
2411 case 2:
2412 y_r = 100;
2413 y_off = 0;
2414 break;
2415
2416 case 3:
2417 x_r = x_off = 100;
2418 break;
2419
2420 }
2421
2422 for ( i = 0; i < gm.t_w; i += sz )
2423 for ( j = 0; j < gm.t_h; j += sz ) {
2424
2425 v.x = (float)((rand() % x_r ) - x_off) / 1000;
2426 v.y = (float)((rand() % y_r ) - y_off) / 1000;
2427
2428 s_shr = SS_Crt(sz, sz, SDL_SWSURFACE);
2429 D_DST(s_shr, 0, 0, sz, sz);
2430 D_SRC(gm.c_g_st->s_crmbl, i, j);
2431 SS_Blt();
2432
2433 Shr_Add(x + i, y + j, sz, sz, v, s_shr);
2434
2435 }
2436 }
2437
2438 // figure animation //
2439 /*
2440 main animation function; select and explode marbles one by one
2441 */
FA_Run()2442 void FA_Run()
2443 {
2444 int i, j, k;
2445 int m_cnt = 0; // marble count
2446 int m_pos[gm.c_lvl->f_w * gm.c_lvl->f_h][2], b;
2447 int ms;
2448 SDL_Event e;
2449 int leave = 0;
2450 int tm, c_tm; // time in ms
2451
2452 if (!cfg.ani) return;
2453
2454 if (gm.m_sel)
2455 Mr_Ins();
2456
2457 // count marbles and get position
2458 for ( i = 0; i < gm.c_lvl->m_w; i++ )
2459 for (j = 0; j < gm.c_lvl->m_h; j++ )
2460 if ( gm.c_lvl->map[i][j].m != - 1 ) {
2461
2462 m_pos[m_cnt][0] = i;
2463 m_pos[m_cnt][1] = j;
2464 m_cnt++;
2465
2466 }
2467
2468 // unsort positions
2469 for ( k = 0; k < m_cnt * 5; k++) {
2470
2471 i = rand() % m_cnt;
2472 j = rand() % m_cnt;
2473
2474 b = m_pos[i][0];
2475 m_pos[i][0] = m_pos[j][0];
2476 m_pos[j][0] = b;
2477 b = m_pos[i][1];
2478 m_pos[i][1] = m_pos[j][1];
2479 m_pos[j][1] = b;
2480
2481 }
2482
2483 // explosions
2484 MF_Hd();
2485 T_Rst();
2486 tm = 250;
2487 c_tm = 0;
2488 m_cnt--;
2489 SDL_SetCursor(gm.c_w);
2490 while ( (m_cnt >= 0 || gm.shr.cntr > 0) && !trm_gm && !leave ) {
2491
2492 // termination ?
2493 if (SDL_PollEvent(&e)) {
2494 switch (e.type) {
2495 case SDL_QUIT:
2496 trm_gm = 1;
2497 break;
2498 case SDL_MOUSEBUTTONUP:
2499 case SDL_KEYUP:
2500 if (e.key.keysym.sym == SDLK_TAB)
2501 SnapShot();
2502 else
2503 leave = 1;
2504 break;
2505 }
2506 }
2507
2508 // show shrapnells
2509 Shr_Hd();
2510 ms = T_Gt();
2511 c_tm -= ms;
2512 MA_Upd(ms);
2513 Shr_Upd(ms);
2514 MA_Shw();
2515 Shr_Shw();
2516 Tm_Shw();
2517 Inf_Shw();
2518 Sdl_UpdR();
2519
2520 //add new shrapnells
2521 if (m_cnt >= 0 && c_tm <= 0) {
2522
2523 FA_Add(m_pos[m_cnt][0],
2524 m_pos[m_cnt][1],
2525 gm.c_lvl->map[m_pos[m_cnt][0]][m_pos[m_cnt][1]].m);
2526 c_tm = tm;
2527 m_cnt--;
2528 #ifdef SOUND
2529 sound_play(gm.wv_exp);
2530 #endif
2531
2532 }
2533
2534 }
2535
2536 }
2537
2538 /*
2539 add shrapnells at x,y with marble-id m
2540 */
FA_Add(int mx,int my,int m)2541 void FA_Add(int mx, int my, int m)
2542 {
2543 int x, y;
2544 int i, j;
2545 int sz = 4; // size
2546 SDL_Surface *s_shr;
2547 Vec v;
2548
2549 x = gm.l_x + mx * gm.t_w;
2550 y = gm.l_y + my * gm.t_h;
2551
2552 // delete from screne
2553 gm.c_lvl->map[mx][my].m = -1;
2554 L_DrwMpTl(mx, my);
2555 Sdl_AddR(x, y, gm.t_w, gm.t_h);
2556
2557 // create shrapnells
2558 for ( i = 0; i < gm.t_w; i += sz )
2559 for ( j = 0; j < gm.t_h; j += sz ) {
2560
2561 v.x = (float)((rand() % 200 ) - 100) / 1000;
2562 v.y = (float)((rand() % 200 ) - 100) / 1000;
2563
2564 s_shr = SS_Crt(sz, sz, SDL_SWSURFACE);
2565 D_DST(s_shr, 0, 0, sz, sz);
2566 D_SRC(gm.s_mrb, i, gm.t_h * m + j);
2567 SS_Blt();
2568
2569 Shr_Add(x + i, y + j, sz, sz, v, s_shr);
2570
2571 }
2572 }
2573
2574 // credits //
2575 /*
2576 initiate credits
2577 */
Cr_Ini()2578 void Cr_Ini()
2579 {
2580 gm.cr_st = 0;
2581 gm.cr_a = 255;
2582 gm.cr_c_tm = gm.cr_tm;
2583 sprintf(gm.cr_str, "'%s' (Author: %s)", gm.c_l_st->ch[gm.c_ch].nm, gm.c_l_st->ch[gm.c_ch].authr);
2584 gm.cr_w = SF_TxtW(gm.f_sml, gm.cr_str);
2585 gm.cr_h = gm.f_sml->h;
2586 gm.cr_x = (gm.scr_w - gm.brd_w - gm.cr_w) / 2;
2587 }
2588
2589 /*
2590 hide credits
2591 */
Cr_Hd()2592 void Cr_Hd()
2593 {
2594 if ( gm.cr_st == 3 ) return;
2595
2596 D_DST(sdl.scr, gm.cr_x, gm.cr_y, gm.cr_w, gm.cr_h);
2597 D_SRC(gm.s_bkgd, gm.cr_x, gm.cr_y);
2598 SS_Blt();
2599 }
2600
2601 /*
2602 update credits
2603 */
Cr_Upd(int ms)2604 void Cr_Upd(int ms)
2605 {
2606 if ( gm.cr_st == 3 ) return;
2607
2608 switch ( gm.cr_st ) {
2609
2610 case 0:
2611 // undim
2612 gm.cr_a -= gm.cr_a_c * (float)ms;
2613 if ( gm.cr_a <= 0 ) {
2614
2615 gm.cr_a = 0;
2616 gm.cr_st = 1;
2617
2618 }
2619 break;
2620
2621 case 1:
2622 // just show till timeout
2623 gm.cr_c_tm -= ms;
2624 if ( gm.cr_c_tm <= 0 )
2625 gm.cr_st = 2;
2626 break;
2627
2628 case 2:
2629 // undim
2630 gm.cr_a += gm.cr_a_c * (float)ms;
2631 if ( gm.cr_a >= 255 ) {
2632
2633 gm.cr_a = 255;
2634 gm.cr_st = 3;
2635
2636 }
2637 break;
2638
2639 }
2640 }
2641
2642 /*
2643 show credits
2644 */
Cr_Shw()2645 void Cr_Shw()
2646 {
2647 if ( gm.cr_st == 3) return;
2648
2649 gm.f_sml->algn = TA_X_L | TA_Y_T;
2650 SF_Wrt(gm.f_sml, sdl.scr, gm.cr_x, gm.cr_y, gm.cr_str, (int)gm.cr_a);
2651 Sdl_AddR(gm.cr_x, gm.cr_y, gm.cr_w, gm.cr_h);
2652 }
2653
2654 // modify score //
modify_score(int * b_lvl,int * b_tm)2655 void modify_score( int *b_lvl, int *b_tm )
2656 {
2657 /* modify score according to difficulty level */
2658 switch (cfg.diff) {
2659 case DIFF_EASY:
2660 *b_lvl /= 2;
2661 *b_tm /= 2;
2662 break;
2663 case DIFF_NORMAL: break;
2664 case DIFF_HARD:
2665 *b_lvl *= 2;
2666 *b_tm *= 2;
2667 break;
2668 case DIFF_BRAINSTORM:
2669 *b_tm *= 5;
2670 *b_lvl *= 5;
2671 break;
2672 }
2673 }
2674
2675 // bonus summary //
2676 /*
2677 give a bonus summary
2678 */
BS_Run(float b_lvl,float b_tm)2679 void BS_Run(float b_lvl, float b_tm)
2680 {
2681 SDL_Surface *buf;
2682 SDL_Event e;
2683 int leave = 0;
2684 int coff, cy; // level completed
2685 int toff, ty; // time bonus
2686 int soff, sy; // score
2687 int ms;
2688 int sw = 80, sh = gm.f_sml->h; // string width, height
2689 float b_c = 1.0; // bonus change
2690 float scr = gm.c_prf->scr;
2691 int end_scr;
2692 int old_scr;
2693
2694 end_scr = gm.c_prf->scr + (int)b_lvl + (int)b_tm;
2695
2696 // normal cursor
2697 SDL_SetCursor(gm.c_n);
2698
2699 // darken screen
2700 buf = SS_Crt(gm.scr_w, gm.scr_h, SDL_SWSURFACE);
2701 SDL_SetColorKey(buf, 0, 0);
2702 D_FDST(buf);
2703 SS_Fill(0x0);
2704 D_FDST(sdl.scr);
2705 D_FSRC(buf);
2706 SS_ABlt(128);
2707 SDL_FreeSurface(buf);
2708 D_FDST(gm.s_bkgd);
2709 D_FSRC(sdl.scr);
2710 SS_Blt();
2711
2712 // positions
2713 cy = 200; coff = 200;
2714 ty = 220; toff = 200;
2715 sy = 250; soff = 200;
2716
2717 // info
2718 gm.f_sml->algn = TA_X_L | TA_Y_T;
2719 SF_Wrt(gm.f_sml, sdl.scr, coff, cy, "Level Bonus:", 0);
2720 SF_Wrt(gm.f_sml, sdl.scr, toff, ty, "Move Bonus:", 0);
2721 SF_Wrt(gm.f_sml, sdl.scr, soff, sy, "Total Score:", 0);
2722 Sdl_FUpd();
2723
2724 // show bonus first time
2725 gm.f_sml->algn = TA_X_R | TA_Y_T;
2726 BS_Shw(gm.scr_w - soff, sy, (int)scr);
2727 Sdl_UpdR();
2728 SDL_Delay(500);
2729 BS_Shw(gm.scr_w - coff, cy, (int)b_lvl);
2730 Sdl_UpdR();
2731 #ifdef SOUND
2732 sound_play(gm.wv_exp);
2733 #endif
2734 SDL_Delay(500);
2735 BS_Shw(gm.scr_w - toff, ty, (int)b_tm);
2736 Sdl_UpdR();
2737 #ifdef SOUND
2738 sound_play(gm.wv_exp);
2739 #endif
2740 SDL_Delay(500);
2741
2742 T_Rst();
2743 while ( !leave ) {
2744
2745 // break?
2746 if ( SDL_PollEvent(&e) )
2747 switch ( e.type ) {
2748
2749 case SDL_QUIT:
2750 trm_gm = 1;
2751 break;
2752
2753 case SDL_MOUSEBUTTONUP:
2754 case SDL_KEYUP:
2755 leave = 1;
2756 break;
2757
2758 }
2759
2760 // time
2761 ms = T_Gt();
2762
2763 // hide
2764 BS_Hd(gm.scr_w - coff - sw, cy, sw, sh);
2765 BS_Hd(gm.scr_w - toff - sw, ty, sw, sh);
2766 BS_Hd(gm.scr_w - soff - sw, sy, sw, sh);
2767
2768 // update
2769 old_scr = (int)scr;
2770 if ( b_lvl > 0 ) {
2771
2772 b_lvl -= b_c * (float)ms;
2773 scr += b_c * (float)ms;
2774 if ( b_lvl < 0 )
2775 b_lvl = 0;
2776
2777 }
2778 if ( b_tm > 0 ) {
2779
2780 b_tm -= b_c * (float)ms;
2781 scr += b_c * (float)ms;
2782 if ( b_tm < 0 )
2783 b_tm = 0;
2784
2785 }
2786 if ( (int)scr >= end_scr)
2787 scr = end_scr;
2788 if (b_lvl == 0 && b_tm == 0)
2789 scr = end_scr;
2790 #ifdef SOUND
2791 if ( (old_scr / 50) != (int)scr / 50 )
2792 sound_play(gm.wv_scr);
2793 #endif
2794
2795 // show
2796 BS_Shw(gm.scr_w - coff, cy, (int)b_lvl);
2797 BS_Shw(gm.scr_w - toff, ty, (int)b_tm);
2798 BS_Shw(gm.scr_w - soff, sy, (int)scr);
2799
2800 Sdl_UpdR();
2801 }
2802 }
2803
2804 /*
2805 hide number
2806 */
BS_Hd(int x,int y,int w,int h)2807 void BS_Hd(int x, int y, int w, int h)
2808 {
2809 D_DST(sdl.scr, x, y, w, h);
2810 D_SRC(gm.s_bkgd, x, y);
2811 SS_Blt();
2812 Sdl_AddR(x, y, w, h);
2813 }
2814
2815 /*
2816 show number
2817 */
BS_Shw(int x,int y,int v)2818 void BS_Shw(int x, int y, int v)
2819 {
2820 char str[10];
2821
2822 sprintf(str, "%i", v);
2823 SF_Wrt(gm.f_sml, sdl.scr, x, y, str, 0);
2824 Sdl_AddR(x - SF_TxtW(gm.f_sml, str), y, SF_TxtW(gm.f_sml, str), gm.f_sml->h);
2825 }
2826
2827 // snap shot //
2828 /*
2829 take a screenshot
2830 */
SnapShot()2831 void SnapShot()
2832 {
2833 char filename[32];
2834 #ifdef SOUND
2835 sound_play(gm.wv_clk);
2836 #endif
2837 sprintf(filename, "snapshot_%i.bmp", gm.snap++);
2838 SDL_SaveBMP(sdl.scr, filename);
2839 }
2840