1 /***************************************************************************
2 levels.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 <math.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <dirent.h>
25 #include "levels.h"
26 #include "dynlist.h"
27 #include "game.h"
28 #include "file.h"
29 #include "sdl.h"
30 #include "timer.h"
31 #include "cfg.h"
32
33 /* game struct -- game.c */
34 extern Game gm;
35 /* line counter -- file.c */
36 extern int f_ln;
37 /* Sdl -- sdl.c */
38 extern Sdl sdl;
39 /* profiles -- profile.c */
40 extern DLst prfs;
41 /* config -- cfg.c */
42 extern Cfg cfg;
43
44 char **ls_lst = 0;
45 int ls_n = 0;
46 DLst l_sts;
47
48 /*
49 count and create a list with all loadable filenames found in SRC_DIR/levels
50 */
L_CrtLst()51 void L_CrtLst()
52 {
53 int i;
54 char d_nm[256];
55 char path[256+64];
56 DIR *dir = 0;
57 struct dirent *e;
58 struct stat s;
59
60 ls_n = 0;
61
62 // create directory string //
63 sprintf(d_nm, "%s/levels", SRC_DIR);
64
65 // find and open directory //
66 if ((dir = opendir(d_nm)) == 0) {
67 fprintf(stderr, "ERROR: can't find directory '%s'\n", d_nm);
68 exit(1);
69 }
70
71 printf("searching for level sets...\n");
72 // well, let's check the count the entries //
73 while ((e = readdir(dir)) != 0) {
74 sprintf(path, "%s/%s", d_nm, e->d_name);
75 stat(path, &s);
76 if (S_ISREG(s.st_mode)) {
77 (ls_n)++;
78 printf("'%s'\n", e->d_name);
79 }
80 }
81
82 if (ls_n == 0) {
83 fprintf(stderr, "ERROR: '%s' seems to be empty\n", d_nm);
84 closedir(dir);
85 exit(1);
86 }
87 else
88 printf("...total of %i\n", ls_n);
89
90 // now we'll create the list //
91 rewinddir(dir);
92 ls_lst = malloc(sizeof(char*) * (ls_n));
93 for (i = 0; i < ls_n; i++) {
94 do {
95 e = readdir(dir);
96 if (e == 0) continue;
97 sprintf(path, "%s/%s", d_nm, e->d_name);
98 stat(path, &s);
99 } while (!S_ISREG(s.st_mode));
100 ls_lst[i] = malloc(strlen(e->d_name) + 1);
101 strcpy(ls_lst[i], e->d_name);
102 }
103
104 // close dir //
105 closedir(dir);
106 }
107
108 /*
109 free list memory
110 */
L_DelLst()111 void L_DelLst()
112 {
113 int i;
114 if (!ls_lst) return;
115 for (i = 0; i < ls_n; i++)
116 free(ls_lst[i]);
117 free(ls_lst);
118 }
119
120 /*
121 callback for dynlist l_sts to delete a level set
122 */
L_DelSt(void * p)123 void L_DelSt(void *p)
124 {
125 int i;
126 LSet *st = (LSet*)p;
127 if (st->ch) {
128 for (i = 0; i < st->c_num; i++)
129 free(st->ch[i].lvls);
130 free(st->ch);
131 }
132 free(p);
133 }
134
135 /*
136 add an empty and invalid entry
137 */
L_AddInvSt(char * nm)138 void L_AddInvSt(char *nm)
139 {
140 LSet *st = malloc(sizeof(LSet));
141 st->c_num = 0;
142 st->ch = 0;
143 st->ok = 0;
144 strcpy(st->nm, nm);
145 DL_Add(&l_sts, st);
146 }
147
148 /*
149 set marble, type and id of a map tile
150 */
L_StMpT(MapT * tl,int m,int t,int id)151 void L_StMpT(MapT *tl, int m, int t, int id)
152 {
153 tl->m = m;
154 tl->t = t;
155 tl->id = id;
156 }
157
158 /*
159 parse and add a new lset from file f
160 */
L_LdSt(FILE * f)161 int L_LdSt(FILE *f)
162 {
163 int i, j, k, l;
164 char val[64];
165 char str[512];
166 LSet *st = malloc(sizeof(LSet));
167
168 // info section //
169 F_GetE(f, str, F_SUB | F_VAL);
170 if (!F_CkE(str, F_SUB, "<info>", 0)) {
171 printf("ERROR: line %i: '<info>' expected\n", f_ln);
172 free(st);
173 return 0;
174 }
175 // levels per chapter //
176 F_GetE(f, str, F_VAL);
177 if (!F_CkE(str, F_VAL, "levels", val)) {
178 printf("ERROR: line %i: 'levels' expected\n", f_ln);
179 free(st);
180 return 0;
181 }
182 st->l_num = atoi(val);
183 // chapters //
184 F_GetE(f, str, F_VAL);
185 if (!F_CkE(str, F_VAL, "chapters", val)) {
186 printf("ERROR: line %i: 'chapters' expected\n", f_ln);
187 free(st);
188 return 0;
189 }
190 st->c_num = atoi(val);
191 // limit type //
192 F_GetE(f, str, F_VAL);
193 if (!F_CkE(str, F_VAL, "limit", val)) {
194 printf("ERROR: line %i: 'limit' expected\n", f_ln);
195 free(st);
196 return 0;
197 }
198 if ( !strncmp( "time", val, 4 ) )
199 st->limit_type = TIME;
200 else
201 st->limit_type = MOVES;
202 // info section //
203 F_GetE(f, str, F_SUB | F_VAL);
204 if (!F_CkE(str, F_SUB, "</info>", 0)) {
205 printf("ERROR: line %i: '</info>' expected\n", f_ln);
206 free(st);
207 return 0;
208 }
209
210 // get memory
211 st->ch = malloc( sizeof(Chptr) * st->c_num );
212 for (i = 0; i < st->c_num; i++)
213 st->ch[i].lvls = malloc( sizeof(Lvl) * st->l_num );
214
215 // chapters
216 for (i = 0; i < st->c_num; i++) {
217 // chapter start //
218 F_GetE(f, str, F_SUB | F_VAL);
219 if (!F_CkE(str, F_SUB, "<chapter>", 0)) {
220 printf("ERROR: line %i: '<chapter>' expected\n", f_ln);
221 goto failure;
222 }
223 // name //
224 F_GetE(f, str, F_VAL);
225 if (!F_CkE(str, F_VAL, "name", st->ch[i].nm)) {
226 printf("ERROR: line %i: 'name' expected\n", f_ln);
227 goto failure;
228 }
229 // author //
230 F_GetE(f, str, F_VAL);
231 if (!F_CkE(str, F_VAL, "author", st->ch[i].authr)) {
232 printf("ERROR: line %i: 'author' expected\n", f_ln);
233 goto failure;
234 }
235 // gset //
236 F_GetE(f, str, F_VAL);
237 if (!F_CkE(str, F_VAL, "gfx_set", st->ch[i].g_st)) {
238 printf("ERROR: line %i: 'gfx_set' expected\n", f_ln);
239 goto failure;
240 }
241 // open for play ? //
242 F_GetE(f, str, F_VAL);
243 if (!F_CkE(str, F_VAL, "open", val)) {
244 printf("ERROR: line %i: 'open' expected\n", f_ln);
245 goto failure;
246 }
247 st->ch[i].opn = atoi(val);
248
249 // levels //
250 for (j = 0; j < st->l_num; j++) {
251 // level start //
252 F_GetE(f, str, F_SUB | F_VAL);
253 if (!F_CkE(str, F_SUB, "<level>", 0)) {
254 printf("ERROR: line %i: '<level>' expected\n", f_ln);
255 goto failure;
256 }
257 // time //
258 F_GetE(f, str, F_VAL);
259 if (!F_CkE(str, F_VAL, "limit", val)) {
260 printf("ERROR: line %i: 'limit' expected\n", f_ln);
261 goto failure;
262 }
263 st->ch[i].lvls[j].tm = atoi(val);
264 // map width //
265 F_GetE(f, str, F_VAL);
266 if (!F_CkE(str, F_VAL, "map_w", val)) {
267 printf("ERROR: line %i: 'map_w' expected\n", f_ln);
268 goto failure;
269 }
270 if ((st->ch[i].lvls[j].m_w = atoi(val)) > L_MAX_W || atoi(val) < L_MIN_W) {
271 printf("ERROR: line %i: 'map_w' out of range (%i-%i): %i\n", f_ln, L_MIN_W, L_MAX_W, atoi(val));
272 goto failure;
273 }
274 // map height //
275 F_GetE(f, str, F_VAL);
276 if (!F_CkE(str, F_VAL, "map_h", val)) {
277 printf("ERROR: line %i: 'map_h' expected\n", f_ln);
278 goto failure;
279 }
280 if ((st->ch[i].lvls[j].m_h = atoi(val)) > L_MAX_H || atoi(val) < L_MIN_H) {
281 printf("ERROR: line %i: 'map_w' out of range (%i-%i): %i\n", f_ln, L_MIN_H, L_MAX_H, atoi(val));
282 goto failure;
283 }
284 // figure width //
285 F_GetE(f, str, F_VAL);
286 if (!F_CkE(str, F_VAL, "fig_w", val)) {
287 printf("ERROR: line %i: 'fig_w' expected\n", f_ln);
288 goto failure;
289 }
290 st->ch[i].lvls[j].f_w = atoi(val);
291 if ((st->ch[i].lvls[j].f_w = atoi(val)) > F_MAX_W || atoi(val) < F_MIN_W) {
292 printf("ERROR: line %i: 'fig_w' out of range (%i-%i): %i\n", f_ln, F_MIN_W, F_MAX_W, atoi(val));
293 goto failure;
294 }
295 // figure height //
296 F_GetE(f, str, F_VAL);
297 if (!F_CkE(str, F_VAL, "fig_h", val)) {
298 printf("ERROR: line %i: 'fig_h' expected\n", f_ln);
299 goto failure;
300 }
301 if ((st->ch[i].lvls[j].f_h = atoi(val)) > F_MAX_H || atoi(val) < F_MIN_H) {
302 printf("ERROR: line %i: 'fig_h' out of range (%i-%i): %i\n", f_ln, F_MIN_H, F_MAX_H, atoi(val));
303 goto failure;
304 }
305
306 // figure start //
307 F_GetE(f, str, F_SUB | F_VAL);
308 if (!F_CkE(str, F_SUB, "<figure>", 0)) {
309 printf("ERROR: line %i: '<figure>' expected\n", f_ln);
310 goto failure;
311 }
312 // figure //
313 for (k = 0; k < st->ch[i].lvls[j].f_h; k++) {
314 F_GetE(f, str, F_VAL);
315 for (l = 0; l < st->ch[i].lvls[j].f_w; l++) {
316 if (str[l] >= '0' && str[l] <= '9')
317 st->ch[i].lvls[j].fgr[l][k] = str[l] - 48;
318 else
319 if (str[l] != 32)
320 printf("WARNING: line %i: bad figure marble '%c'\n", f_ln, str[l]);
321 else
322 st->ch[i].lvls[j].fgr[l][k] = -1;
323 }
324 }
325 // figure end //
326 F_GetE(f, str, F_SUB | F_VAL);
327 if (!F_CkE(str, F_SUB, "</figure>", 0)) {
328 printf("ERROR: line %i: '</figure>' expected\n", f_ln);
329 goto failure;
330 }
331
332 // map start //
333 F_GetE(f, str, F_SUB | F_VAL);
334 if (!F_CkE(str, F_SUB, "<map>", 0)) {
335 printf("ERROR: line %i: '<map>' expected\n", f_ln);
336 goto failure;
337 }
338 // map
339 for (k = 0; k < st->ch[i].lvls[j].m_h; k++) {
340 memset(str, 0, 256);
341 F_GetE(f, str, F_VAL);
342 for (l = 0; l < st->ch[i].lvls[j].m_w; l++) {
343 if (str[l] >= '0' && str[l] <= '9')
344 L_StMpT(&st->ch[i].lvls[j].map[l][k], str[l] - 48, M_FLOOR, 0);
345 else
346 switch (str[l]) {
347 case 'a':
348 case 'b':
349 case 'c':
350 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_WALL, str[l] - 97);
351 break;
352 case ' ':
353 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_FLOOR, 0);
354 break;
355 case 'u':
356 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_U, 0);
357 break;
358 case 'd':
359 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_D, 0);
360 break;
361 case 'r':
362 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_R, 0);
363 break;
364 case 'l':
365 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_L, 0);
366 break;
367 case 'U':
368 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_U_C, 0);
369 break;
370 case 'D':
371 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_D_C, 0);
372 break;
373 case 'R':
374 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_R_C, 0);
375 break;
376 case 'L':
377 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_L_C, 0);
378 break;
379 case 'w':
380 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_TLP_0, 0);
381 break;
382 case 'x':
383 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_TLP_1, 0);
384 break;
385 case 'y':
386 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_TLP_2, 0);
387 break;
388 case 'z':
389 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_TLP_3, 0);
390 break;
391 case 'A':
392 case 'B':
393 case 'C':
394 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_CRUMBLE, str[l] - 65);
395 break;
396 default:
397 L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_EMPTY, 0);
398 break;
399 }
400 }
401 }
402 // map end //
403 F_GetE(f, str, F_SUB | F_VAL);
404 if (!F_CkE(str, F_SUB, "</map>", 0)) {
405 printf("ERROR: line %i: '</map>' expected\n", f_ln);
406 goto failure;
407 }
408
409 // level end //
410 F_GetE(f, str, F_SUB | F_VAL);
411 if (!F_CkE(str, F_SUB, "</level>", 0)) {
412 printf("ERROR: line %i: '</level>' expected\n", f_ln);
413 goto failure;
414 }
415 }
416
417 // chapter end //
418 F_GetE(f, str, F_SUB);
419 if (!F_CkE(str, F_SUB, "</chapter>", 0)) {
420 printf("ERROR: line %i: '</chapter>' expected\n", f_ln);
421 goto failure;
422 }
423 }
424
425 // return 1 in any case cuz 0 assumes that an empty set must be added
426 printf("ok\n");
427 DL_Add(&l_sts, st);
428 st->ok = 1;
429 return 1;
430
431 failure:
432 DL_Add(&l_sts, st);
433 // L_DelSt(st);
434 st->ok = 0;
435 return 1;
436 }
437
438 /*
439 initialize level l
440 */
L_Ini(int c,int l)441 void L_Ini(int c, int l)
442 {
443 char *nm;
444 DL_E *e;
445 int gst_ok = 0;
446 int px, py, i, j, k;
447 Lvl *lp;
448 char str[64];
449 int off;
450 char *str_num[] = {"1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10."};
451 float mv_mod;
452
453 // show credit when new chapter
454 if ( gm.o_ch == -1 || gm.o_ch != c )
455 Cr_Ini();
456
457 // set level & chapter index
458 gm.o_ch = c;
459 gm.c_ch = c;
460 gm.c_l_id = l;
461 gm.l_done = 0;
462
463 // set open flag
464 gm.c_s_inf->c_opn[gm.c_ch] = 1;
465
466 // copy current level
467 if (gm.c_lvl) free(gm.c_lvl);
468 gm.c_lvl = malloc(sizeof(Lvl));
469 memcpy(gm.c_lvl, &gm.c_l_st->ch[gm.c_ch].lvls[gm.c_l_id], sizeof(Lvl));
470
471 // load gfx set
472 nm = gm.c_l_st->ch[gm.c_ch].g_st;
473 e = gm.g_sts.hd.n;
474 while (e != &gm.g_sts.tl) {
475 if (!strncmp(nm, ((GSet*)e->d)->nm, strlen(nm)) && ((GSet*)e->d)->ok) {
476 gm.c_g_st = (GSet*)e->d;
477 gst_ok = 1;
478 break;
479 }
480 e = e->n;
481 }
482 if (!gst_ok) {
483 printf("WARNING: unknown or unuseable gfx set '%s';\nsearching for a good one...\n", nm);
484 // find first useable set
485 e = gm.g_sts.hd.n;
486 while (e != &gm.g_sts.tl) {
487 if (((GSet*)e->d)->ok) {
488 gm.c_g_st = (GSet*)e->d;
489 printf("'%s' used instead\n", gm.c_g_st->nm);
490 gst_ok = 1;
491 break;
492 }
493 e = e->n;
494 }
495 if (!gst_ok) {
496 printf("ERROR: no good gfx set found...\n");
497 exit(1);
498 }
499 }
500
501 // set bkgd picture
502 if (gm.c_g_st->s_bkgd) {
503 for (j = 0; j < gm.scr_w - gm.brd_w; j += gm.c_g_st->s_bkgd->w)
504 for (k = 0; k < gm.scr_h; k += gm.c_g_st->s_bkgd->h) {
505 D_DST(gm.s_bkgd, j, k, gm.c_g_st->s_bkgd->w, gm.c_g_st->s_bkgd->h);
506 D_SRC(gm.c_g_st->s_bkgd, 0, 0);
507 SS_Blt();
508 }
509 }
510 else {
511 D_DST(gm.s_bkgd, 0, 0, gm.scr_w - gm.brd_w, gm.scr_h);
512 SS_Fill(0x0);
513 }
514
515 // add board
516 D_DST(gm.s_bkgd, gm.s_bkgd->w - gm.s_brd->w, 0, gm.s_brd->w, gm.s_brd->h);
517 D_SRC(gm.s_brd, 0, 0);
518 SS_Blt();
519
520 // add static level gfx
521 lp = &gm.c_l_st->ch[gm.c_ch].lvls[gm.c_l_id];
522 gm.l_x = (gm.scr_w - gm.brd_w - lp->m_w * gm.t_w) / 2;
523 gm.l_y = (gm.scr_h - lp->m_h * gm.t_h) / 2;
524 for (i = 0; i < lp->m_w; i++)
525 for (j = 0; j < lp->m_h; j++)
526 L_DrwMpTl(i, j);
527
528 // add marbles
529 for (i = 0; i < lp->m_w; i++)
530 for (j = 0; j < lp->m_h; j++)
531 if (lp->map[i][j].m != - 1) {
532 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w, gm.l_y + j * gm.t_h, gm.t_w, gm.t_h);
533 D_SRC(gm.s_mrb, 0, lp->map[i][j].m * gm.t_h);
534 SS_Blt();
535 }
536
537 // add figure
538 px = gm.b_x + gm.f_x + (gm.f_fw - lp->f_w * gm.f_h) / 2;
539 py = gm.f_y + (gm.f_fh - lp->f_h * gm.f_h)/ 2;
540 for (i = 0; i < lp->f_w; i++)
541 for (j = 0; j < lp->f_h; j++)
542 if (lp->fgr[i][j] != -1) {
543 D_DST(gm.s_bkgd, px + i * gm.f_w, py + j * gm.f_h, gm.f_w, gm.f_h);
544 D_SRC(gm.s_fig, 0, lp->fgr[i][j] * gm.f_h);
545 SS_Blt();
546 }
547
548 // add player info
549 off = gm.f_sml->h + 2;
550 gm.f_sml->algn = TA_X_L | TA_Y_T;
551 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.i_x + gm.b_x, gm.i_y, "Player:", 0);
552 gm.f_sml->algn = TA_X_R | TA_Y_T;
553 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.scr_w - gm.i_x, gm.i_y, gm.c_prf->nm, 0);
554 gm.f_sml->algn = TA_X_L | TA_Y_T;
555 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.i_x + gm.b_x, gm.i_y + off, "Score:", 0);
556 gm.f_sml->algn = TA_X_R | TA_Y_T;
557 sprintf(str, "%i", gm.c_prf->scr);
558 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.scr_w - gm.i_x, gm.i_y + off, str, 0);
559 gm.f_sml->algn = TA_X_L | TA_Y_T;
560 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.i_x + gm.b_x, gm.i_y + off*2 + 5, "HighScore:", 0);
561 gm.f_sml->algn = TA_X_R | TA_Y_T;
562 sprintf(str, "%i", gm.hi_scr);
563 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.scr_w - gm.i_x, gm.i_y + off*2 + 5, str, 0);
564
565 // add name of levelset above set info
566 gm.f_sml->algn = TA_X_C | TA_Y_T;
567 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.b_x + gm.brd_w / 2, gm.s_y + 5, gm.c_l_st->nm, 0);
568
569 // compute position of first chapter
570 gm.c_x = 50; // changed
571 gm.c_y = gm.s_y + (gm.s_h - gm.c_l_st->c_num * L_SIZE) / 2;
572
573 // add chapter numbers
574 gm.f_sml->algn = TA_X_L | TA_Y_T;
575 for (i = 0; i < gm.c_l_st->c_num; i++) {
576 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.b_x + gm.c_x - 30, gm.c_y + i * L_SIZE, str_num[i], 0);
577 }
578
579 // draw chapter lights
580 for (j = 0; j < gm.c_l_st->c_num; j++)
581 for (i = 0; i < gm.c_l_st->l_num; i++) {
582 D_DST(gm.s_bkgd, gm.b_x + gm.c_x + i * L_SIZE, gm.c_y + j * L_SIZE, L_SIZE, L_SIZE);
583 if (!gm.c_s_inf->c_opn[j]) {
584 D_SRC(gm.s_lghts, L_RED * L_SIZE, 0);
585 }
586 else
587 if ( gm.c_s_inf->cmp[j * gm.c_l_st->l_num + i] ) {
588 D_SRC(gm.s_lghts, L_GREEN * L_SIZE, 0);
589 }
590 else {
591 D_SRC(gm.s_lghts, L_ORANGE * L_SIZE, 0);
592 }
593 SS_Blt();
594 }
595 // current level is white
596 D_DST(gm.s_bkgd, gm.b_x + gm.c_x + l * L_SIZE, gm.c_y + c * L_SIZE, L_SIZE, L_SIZE);
597 D_SRC(gm.s_lghts, L_WHITE * L_SIZE, 0);
598 SS_Blt();
599
600 // initiate animations
601
602 MA_Ini();
603
604 // undim
605 D_FDST(sdl.scr);
606 D_FSRC(gm.s_bkgd);
607 SS_Blt();
608 if (cfg.dim)
609 SDL_UNDIM();
610 else
611 Sdl_FUpd();
612
613 // reset timer
614 T_Rst();
615
616 // reset marble and frame
617 gm.m_mv = 0;
618 gm.m_sel = 0;
619 gm.mf_a.p = 0;
620 gm.msf_a.p = 0;
621 gm.m_act = M_EMPTY;
622 gm.m_mx = gm.m_my = -1;
623
624 if ( gm.c_l_st->limit_type == TIME ) {
625 /* set time from seconds to milliseconds if time used */
626 gm.c_lvl->tm *= 1000;
627 gm.c_lvl->tm+=1000;
628 }
629 else {
630 /* gm.c_lvl->tm containts the move limit. this is modified according
631 to the difficulty levels */
632 switch ( cfg.diff ) {
633 case DIFF_EASY:
634 mv_mod = (int)ceil((float)gm.c_lvl->tm * 0.2 * ( 5 - gm.c_ch ) );
635 gm.c_lvl->tm += mv_mod;
636 if ( gm.c_lvl->tm % 2 ) gm.c_lvl->tm++;
637 break;
638 case DIFF_NORMAL:
639 mv_mod = (int)ceil((float)gm.c_lvl->tm * 0.1 * ( 5 - gm.c_ch ) );
640 gm.c_lvl->tm += mv_mod;
641 if ( gm.c_lvl->tm % 2 ) gm.c_lvl->tm++;
642 break;
643 case DIFF_HARD:
644 mv_mod = (int)ceil((float)gm.c_lvl->tm * 0.05 * ( 5 - gm.c_ch ) );
645 gm.c_lvl->tm += mv_mod;
646 if ( gm.c_lvl->tm % 2 ) gm.c_lvl->tm++;
647 break;
648 case DIFF_BRAINSTORM:
649 break;
650 }
651 }
652
653 // init blink time //
654 gm.blink_time = 0;
655
656 // cursor state
657 gm.c_stat = C_NONE;
658 SDL_SetCursor(gm.c_n);
659
660 // reset shrapnells
661 DL_Clr(&gm.shr);
662 }
663
664 /*
665 draw a map tile to gm.s_bkgd with x,y position in the map using current map
666 */
L_DrwMpTl(int i,int j)667 void L_DrwMpTl(int i, int j)
668 {
669 switch (gm.c_lvl->map[i][j].t) {
670 case M_WALL:
671 // add wall shadow on right side ? //
672 if ( i + 1 >= gm.c_lvl->m_w || gm.c_lvl->map[i + 1][j].t == M_EMPTY ) {
673
674 D_DST(gm.s_bkgd, gm.l_x + (i + 1) * gm.t_w, gm.l_y + j * gm.t_h, 1, gm.t_h + 1);
675 SS_Fill(0x0);
676
677 }
678 // add wall shadow on bottom ? //
679 if ( j + 1 >= gm.c_lvl->m_h || gm.c_lvl->map[i][j + 1].t == M_EMPTY ) {
680
681 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w, gm.l_y + (j + 1) * gm.t_h, gm.t_w + 1, 1);
682 SS_Fill(0x0);
683
684 }
685 // add wall shadow on left side ? //
686 if ( (i == 0)
687 || ((i - 1 >= gm.c_lvl->m_w) || gm.c_lvl->map[i - 1][j].t == M_EMPTY )) {
688 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w - 1, gm.l_y + j * gm.t_h, 1, gm.t_h + 1);
689 SS_Fill(0x0);
690
691 }
692 // add wall shadow on top ? //
693 if ( (j == 0)
694 || ((j - 1 >= gm.c_lvl->m_h) || gm.c_lvl->map[i][j - 1].t == M_EMPTY )) {
695 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w, gm.l_y + j * gm.t_h - 1, gm.t_w + 1, 1);
696 SS_Fill(0x0);
697
698 }
699 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w, gm.l_y + j * gm.t_h, gm.t_w, gm.t_h);
700 D_SRC(gm.c_g_st->s_wl, gm.c_lvl->map[i][j].id * gm.t_w, 0);
701 SS_Blt();
702 break;
703 case M_CRUMBLE:
704
705 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w, gm.l_y + j * gm.t_h, gm.t_w, gm.t_h);
706 D_SRC(gm.c_g_st->s_flr, 0, 0);
707 SS_Blt();
708
709 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w, gm.l_y + j * gm.t_h, gm.t_w, gm.t_h);
710 D_SRC(gm.c_g_st->s_crmbl, gm.c_lvl->map[i][j].id * gm.t_w, 0);
711 SS_Blt();
712
713 gm.f_sml->algn = TA_X_R | TA_Y_B;
714 switch (gm.c_lvl->map[i][j].id) {
715 case 0:
716 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.l_x + (i + 1) * gm.t_w - 1, gm.l_y + (j + 1) * gm.t_h - 1, "1", 0);
717 break;
718 case 1:
719 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.l_x + (i + 1) * gm.t_w - 1, gm.l_y + (j + 1) * gm.t_h - 1, "2", 0);
720 break;
721 case 2:
722 SF_Wrt(gm.f_sml, gm.s_bkgd, gm.l_x + (i + 1) * gm.t_w - 1, gm.l_y + (j + 1) * gm.t_h - 1, "3", 0);
723 break;
724 }
725
726 break;
727 case M_EMPTY:
728 break;
729 default:
730 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w, gm.l_y + j * gm.t_h, gm.t_w, gm.t_h);
731 D_SRC(gm.c_g_st->s_flr, 0, 0);
732 SS_Blt();
733 break;
734 }
735
736 // static animations ? //
737 if (!cfg.ani) {
738 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w, gm.l_y + j * gm.t_h, gm.t_w, gm.t_h);
739 switch (gm.c_lvl->map[i][j].t) {
740 case M_OW_U:
741 case M_OW_U_C:
742 D_SRC(gm.c_g_st->s_u_arw, 0, 0);
743 SS_Blt();
744 break;
745 case M_OW_D:
746 case M_OW_D_C:
747 D_SRC(gm.c_g_st->s_d_arw, 0, 0);
748 SS_Blt();
749 break;
750 case M_OW_L:
751 case M_OW_L_C:
752 D_SRC(gm.c_g_st->s_l_arw, 0, 0);
753 SS_Blt();
754 break;
755 case M_OW_R:
756 case M_OW_R_C:
757 D_SRC(gm.c_g_st->s_r_arw, 0, 0);
758 SS_Blt();
759 break;
760 }
761 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w, gm.l_y + j * gm.t_h, gm.t_w, gm.t_h);
762 switch (gm.c_lvl->map[i][j].t) {
763 case M_OW_U_C:
764 case M_OW_D_C:
765 D_SRC(gm.c_g_st->s_lr_bar, 0, 0);
766 SS_Blt();
767 break;
768 case M_OW_L_C:
769 case M_OW_R_C:
770 D_SRC(gm.c_g_st->s_ud_bar, 0, 0);
771 SS_Blt();
772 break;
773 }
774
775 D_DST(gm.s_bkgd, gm.l_x + i * gm.t_w, gm.l_y + j * gm.t_h, gm.t_w, gm.t_h);
776 switch (gm.c_lvl->map[i][j].t) {
777 case M_TLP_0:
778 D_SRC(gm.c_g_st->s_tlp_0, 0, 0);
779 SS_ABlt(gm.tlp_a);
780 break;
781 case M_TLP_1:
782 D_SRC(gm.c_g_st->s_tlp_1, 0, 0);
783 SS_ABlt(gm.tlp_a);
784 break;
785 case M_TLP_2:
786 D_SRC(gm.c_g_st->s_tlp_2, 0, 0);
787 SS_ABlt(gm.tlp_a);
788 break;
789 case M_TLP_3:
790 D_SRC(gm.c_g_st->s_tlp_3, 0, 0);
791 SS_ABlt(gm.tlp_a);
792 break;
793 }
794 }
795 }
796
797 /*
798 proceed to next valid level
799 */
L_FndNxt()800 int L_FndNxt()
801 {
802 int i, j;
803
804 // proceed to next level
805 gm.c_l_id++;
806 if (gm.c_l_id >= gm.c_l_st->l_num) {
807 gm.c_l_id = 0;
808 gm.c_ch++;
809 // check if this chapter can be entered or if this was the last chapter if not take first unsolved level found
810 if (gm.c_ch >= gm.c_l_st->c_num || !gm.c_l_st->ch[gm.c_ch].opn) {
811 for (i = 0; i < gm.c_ch; i++)
812 for (j = 0; j < gm.c_l_st->l_num; j++)
813 if (!gm.c_s_inf->cmp[i * gm.c_l_st->l_num + j]) {
814 // not all levels completed jump back to first unsolved level
815 gm.c_ch = i;
816 gm.c_l_id = j;
817 return 1;
818 }
819 if (gm.c_ch >= gm.c_l_st->c_num)
820 return 0;
821 else
822 return 1;
823 }
824 }
825 else {
826 // check if all levels of this chapter has been solved
827 for (i = 0; i <= gm.c_ch; i++)
828 for (j = 0; j < gm.c_l_st->l_num; j++)
829 if (!gm.c_s_inf->cmp[i * gm.c_l_st->l_num + j]) {
830 return 1;
831 }
832 // yes! open next chapter
833 if ( gm.c_ch < gm.c_l_st->c_num - 1 )
834 gm.c_s_inf->c_opn[gm.c_ch + 1] = 1;
835 }
836 return 1;
837 }
838