Files
commandergenius/project/jni/application/lmarbles-1.0.8/src/levels.c
2010-12-24 12:05:03 +00:00

838 lines
27 KiB
C

/***************************************************************************
levels.c - description
-------------------
begin : Mon Aug 14 2000
copyright : (C) 2000 by Michael Speck
email : kulkanie@gmx.net
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include "levels.h"
#include "dynlist.h"
#include "game.h"
#include "file.h"
#include "sdl.h"
#include "timer.h"
#include "cfg.h"
/* game struct -- game.c */
extern Game gm;
/* line counter -- file.c */
extern int f_ln;
/* Sdl -- sdl.c */
extern Sdl sdl;
/* profiles -- profile.c */
extern DLst prfs;
/* config -- cfg.c */
extern Cfg cfg;
char **ls_lst = 0;
int ls_n = 0;
DLst l_sts;
/*
count and create a list with all loadable filenames found in SRC_DIR/levels
*/
void L_CrtLst()
{
int i;
char d_nm[256];
char path[256+64];
DIR *dir = 0;
struct dirent *e;
struct stat s;
ls_n = 0;
// create directory string //
sprintf(d_nm, "%s/levels", SRC_DIR);
// find and open directory //
if ((dir = opendir(d_nm)) == 0) {
fprintf(stderr, "ERROR: can't find directory '%s'\n", d_nm);
exit(1);
}
printf("searching for level sets...\n");
// well, let's check the count the entries //
while ((e = readdir(dir)) != 0) {
sprintf(path, "%s/%s", d_nm, e->d_name);
stat(path, &s);
if (S_ISREG(s.st_mode)) {
(ls_n)++;
printf("'%s'\n", e->d_name);
}
}
if (ls_n == 0) {
fprintf(stderr, "ERROR: '%s' seems to be empty\n", d_nm);
closedir(dir);
exit(1);
}
else
printf("...total of %i\n", ls_n);
// now we'll create the list //
rewinddir(dir);
ls_lst = malloc(sizeof(char*) * (ls_n));
for (i = 0; i < ls_n; i++) {
do {
e = readdir(dir);
if (e == 0) continue;
sprintf(path, "%s/%s", d_nm, e->d_name);
stat(path, &s);
} while (!S_ISREG(s.st_mode));
ls_lst[i] = malloc(strlen(e->d_name) + 1);
strcpy(ls_lst[i], e->d_name);
}
// close dir //
closedir(dir);
}
/*
free list memory
*/
void L_DelLst()
{
int i;
if (!ls_lst) return;
for (i = 0; i < ls_n; i++)
free(ls_lst[i]);
free(ls_lst);
}
/*
callback for dynlist l_sts to delete a level set
*/
void L_DelSt(void *p)
{
int i;
LSet *st = (LSet*)p;
if (st->ch) {
for (i = 0; i < st->c_num; i++)
free(st->ch[i].lvls);
free(st->ch);
}
free(p);
}
/*
add an empty and invalid entry
*/
void L_AddInvSt(char *nm)
{
LSet *st = malloc(sizeof(LSet));
st->c_num = 0;
st->ch = 0;
st->ok = 0;
strcpy(st->nm, nm);
DL_Add(&l_sts, st);
}
/*
set marble, type and id of a map tile
*/
void L_StMpT(MapT *tl, int m, int t, int id)
{
tl->m = m;
tl->t = t;
tl->id = id;
}
/*
parse and add a new lset from file f
*/
int L_LdSt(FILE *f)
{
int i, j, k, l;
char val[64];
char str[512];
LSet *st = malloc(sizeof(LSet));
// info section //
F_GetE(f, str, F_SUB | F_VAL);
if (!F_CkE(str, F_SUB, "<info>", 0)) {
printf("ERROR: line %i: '<info>' expected\n", f_ln);
free(st);
return 0;
}
// levels per chapter //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "levels", val)) {
printf("ERROR: line %i: 'levels' expected\n", f_ln);
free(st);
return 0;
}
st->l_num = atoi(val);
// chapters //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "chapters", val)) {
printf("ERROR: line %i: 'chapters' expected\n", f_ln);
free(st);
return 0;
}
st->c_num = atoi(val);
// limit type //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "limit", val)) {
printf("ERROR: line %i: 'limit' expected\n", f_ln);
free(st);
return 0;
}
if ( !strncmp( "time", val, 4 ) )
st->limit_type = TIME;
else
st->limit_type = MOVES;
// info section //
F_GetE(f, str, F_SUB | F_VAL);
if (!F_CkE(str, F_SUB, "</info>", 0)) {
printf("ERROR: line %i: '</info>' expected\n", f_ln);
free(st);
return 0;
}
// get memory
st->ch = malloc( sizeof(Chptr) * st->c_num );
for (i = 0; i < st->c_num; i++)
st->ch[i].lvls = malloc( sizeof(Lvl) * st->l_num );
// chapters
for (i = 0; i < st->c_num; i++) {
// chapter start //
F_GetE(f, str, F_SUB | F_VAL);
if (!F_CkE(str, F_SUB, "<chapter>", 0)) {
printf("ERROR: line %i: '<chapter>' expected\n", f_ln);
goto failure;
}
// name //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "name", st->ch[i].nm)) {
printf("ERROR: line %i: 'name' expected\n", f_ln);
goto failure;
}
// author //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "author", st->ch[i].authr)) {
printf("ERROR: line %i: 'author' expected\n", f_ln);
goto failure;
}
// gset //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "gfx_set", st->ch[i].g_st)) {
printf("ERROR: line %i: 'gfx_set' expected\n", f_ln);
goto failure;
}
// open for play ? //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "open", val)) {
printf("ERROR: line %i: 'open' expected\n", f_ln);
goto failure;
}
st->ch[i].opn = atoi(val);
// levels //
for (j = 0; j < st->l_num; j++) {
// level start //
F_GetE(f, str, F_SUB | F_VAL);
if (!F_CkE(str, F_SUB, "<level>", 0)) {
printf("ERROR: line %i: '<level>' expected\n", f_ln);
goto failure;
}
// time //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "limit", val)) {
printf("ERROR: line %i: 'limit' expected\n", f_ln);
goto failure;
}
st->ch[i].lvls[j].tm = atoi(val);
// map width //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "map_w", val)) {
printf("ERROR: line %i: 'map_w' expected\n", f_ln);
goto failure;
}
if ((st->ch[i].lvls[j].m_w = atoi(val)) > L_MAX_W || atoi(val) < L_MIN_W) {
printf("ERROR: line %i: 'map_w' out of range (%i-%i): %i\n", f_ln, L_MIN_W, L_MAX_W, atoi(val));
goto failure;
}
// map height //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "map_h", val)) {
printf("ERROR: line %i: 'map_h' expected\n", f_ln);
goto failure;
}
if ((st->ch[i].lvls[j].m_h = atoi(val)) > L_MAX_H || atoi(val) < L_MIN_H) {
printf("ERROR: line %i: 'map_w' out of range (%i-%i): %i\n", f_ln, L_MIN_H, L_MAX_H, atoi(val));
goto failure;
}
// figure width //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "fig_w", val)) {
printf("ERROR: line %i: 'fig_w' expected\n", f_ln);
goto failure;
}
st->ch[i].lvls[j].f_w = atoi(val);
if ((st->ch[i].lvls[j].f_w = atoi(val)) > F_MAX_W || atoi(val) < F_MIN_W) {
printf("ERROR: line %i: 'fig_w' out of range (%i-%i): %i\n", f_ln, F_MIN_W, F_MAX_W, atoi(val));
goto failure;
}
// figure height //
F_GetE(f, str, F_VAL);
if (!F_CkE(str, F_VAL, "fig_h", val)) {
printf("ERROR: line %i: 'fig_h' expected\n", f_ln);
goto failure;
}
if ((st->ch[i].lvls[j].f_h = atoi(val)) > F_MAX_H || atoi(val) < F_MIN_H) {
printf("ERROR: line %i: 'fig_h' out of range (%i-%i): %i\n", f_ln, F_MIN_H, F_MAX_H, atoi(val));
goto failure;
}
// figure start //
F_GetE(f, str, F_SUB | F_VAL);
if (!F_CkE(str, F_SUB, "<figure>", 0)) {
printf("ERROR: line %i: '<figure>' expected\n", f_ln);
goto failure;
}
// figure //
for (k = 0; k < st->ch[i].lvls[j].f_h; k++) {
F_GetE(f, str, F_VAL);
for (l = 0; l < st->ch[i].lvls[j].f_w; l++) {
if (str[l] >= '0' && str[l] <= '9')
st->ch[i].lvls[j].fgr[l][k] = str[l] - 48;
else
if (str[l] != 32)
printf("WARNING: line %i: bad figure marble '%c'\n", f_ln, str[l]);
else
st->ch[i].lvls[j].fgr[l][k] = -1;
}
}
// figure end //
F_GetE(f, str, F_SUB | F_VAL);
if (!F_CkE(str, F_SUB, "</figure>", 0)) {
printf("ERROR: line %i: '</figure>' expected\n", f_ln);
goto failure;
}
// map start //
F_GetE(f, str, F_SUB | F_VAL);
if (!F_CkE(str, F_SUB, "<map>", 0)) {
printf("ERROR: line %i: '<map>' expected\n", f_ln);
goto failure;
}
// map
for (k = 0; k < st->ch[i].lvls[j].m_h; k++) {
memset(str, 0, 256);
F_GetE(f, str, F_VAL);
for (l = 0; l < st->ch[i].lvls[j].m_w; l++) {
if (str[l] >= '0' && str[l] <= '9')
L_StMpT(&st->ch[i].lvls[j].map[l][k], str[l] - 48, M_FLOOR, 0);
else
switch (str[l]) {
case 'a':
case 'b':
case 'c':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_WALL, str[l] - 97);
break;
case ' ':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_FLOOR, 0);
break;
case 'u':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_U, 0);
break;
case 'd':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_D, 0);
break;
case 'r':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_R, 0);
break;
case 'l':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_L, 0);
break;
case 'U':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_U_C, 0);
break;
case 'D':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_D_C, 0);
break;
case 'R':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_R_C, 0);
break;
case 'L':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_OW_L_C, 0);
break;
case 'w':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_TLP_0, 0);
break;
case 'x':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_TLP_1, 0);
break;
case 'y':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_TLP_2, 0);
break;
case 'z':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_TLP_3, 0);
break;
case 'A':
case 'B':
case 'C':
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_CRUMBLE, str[l] - 65);
break;
default:
L_StMpT(&st->ch[i].lvls[j].map[l][k], -1, M_EMPTY, 0);
break;
}
}
}
// map end //
F_GetE(f, str, F_SUB | F_VAL);
if (!F_CkE(str, F_SUB, "</map>", 0)) {
printf("ERROR: line %i: '</map>' expected\n", f_ln);
goto failure;
}
// level end //
F_GetE(f, str, F_SUB | F_VAL);
if (!F_CkE(str, F_SUB, "</level>", 0)) {
printf("ERROR: line %i: '</level>' expected\n", f_ln);
goto failure;
}
}
// chapter end //
F_GetE(f, str, F_SUB);
if (!F_CkE(str, F_SUB, "</chapter>", 0)) {
printf("ERROR: line %i: '</chapter>' expected\n", f_ln);
goto failure;
}
}
// return 1 in any case cuz 0 assumes that an empty set must be added
printf("ok\n");
DL_Add(&l_sts, st);
st->ok = 1;
return 1;
failure:
DL_Add(&l_sts, st);
// L_DelSt(st);
st->ok = 0;
return 1;
}
/*
initialize level l
*/
void L_Ini(int c, int l)
{
char *nm;
DL_E *e;
int gst_ok = 0;
int px, py, i, j, k;
Lvl *lp;
char str[64];
int off;
char *str_num[] = {"1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.", "9.", "10."};
float mv_mod;
// show credit when new chapter
if ( gm.o_ch == -1 || gm.o_ch != c )
Cr_Ini();
// set level & chapter index
gm.o_ch = c;
gm.c_ch = c;
gm.c_l_id = l;
gm.l_done = 0;
// set open flag
gm.c_s_inf->c_opn[gm.c_ch] = 1;
// copy current level
if (gm.c_lvl) free(gm.c_lvl);
gm.c_lvl = malloc(sizeof(Lvl));
memcpy(gm.c_lvl, &gm.c_l_st->ch[gm.c_ch].lvls[gm.c_l_id], sizeof(Lvl));
// load gfx set
nm = gm.c_l_st->ch[gm.c_ch].g_st;
e = gm.g_sts.hd.n;
while (e != &gm.g_sts.tl) {
if (!strncmp(nm, ((GSet*)e->d)->nm, strlen(nm)) && ((GSet*)e->d)->ok) {
gm.c_g_st = (GSet*)e->d;
gst_ok = 1;
break;
}
e = e->n;
}
if (!gst_ok) {
printf("WARNING: unknown or unuseable gfx set '%s';\nsearching for a good one...\n", nm);
// find first useable set
e = gm.g_sts.hd.n;
while (e != &gm.g_sts.tl) {
if (((GSet*)e->d)->ok) {
gm.c_g_st = (GSet*)e->d;
printf("'%s' used instead\n", gm.c_g_st->nm);
gst_ok = 1;
break;
}
e = e->n;
}
if (!gst_ok) {
printf("ERROR: no good gfx set found...\n");
exit(1);
}
}
// set bkgd picture
if (gm.c_g_st->s_bkgd) {
for (j = 0; j < gm.scr_w - gm.brd_w; j += gm.c_g_st->s_bkgd->w)
for (k = 0; k < gm.scr_h; k += gm.c_g_st->s_bkgd->h) {
D_DST(gm.s_bkgd, j, k, gm.c_g_st->s_bkgd->w, gm.c_g_st->s_bkgd->h);
D_SRC(gm.c_g_st->s_bkgd, 0, 0);
SS_Blt();
}
}
else {
D_DST(gm.s_bkgd, 0, 0, gm.scr_w - gm.brd_w, gm.scr_h);
SS_Fill(0x0);
}
// add board
D_DST(gm.s_bkgd, gm.s_bkgd->w - gm.s_brd->w, 0, gm.s_brd->w, gm.s_brd->h);
D_SRC(gm.s_brd, 0, 0);
SS_Blt();
// add static level gfx
lp = &gm.c_l_st->ch[gm.c_ch].lvls[gm.c_l_id];
gm.l_x = (gm.scr_w - gm.brd_w - lp->m_w * gm.t_w) / 2;
gm.l_y = (gm.scr_h - lp->m_h * gm.t_h) / 2;
for (i = 0; i < lp->m_w; i++)
for (j = 0; j < lp->m_h; j++)
L_DrwMpTl(i, j);
// add marbles
for (i = 0; i < lp->m_w; i++)
for (j = 0; j < lp->m_h; j++)
if (lp->map[i][j].m != - 1) {
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);
D_SRC(gm.s_mrb, 0, lp->map[i][j].m * gm.t_h);
SS_Blt();
}
// add figure
px = gm.b_x + gm.f_x + (gm.f_fw - lp->f_w * gm.f_h) / 2;
py = gm.f_y + (gm.f_fh - lp->f_h * gm.f_h)/ 2;
for (i = 0; i < lp->f_w; i++)
for (j = 0; j < lp->f_h; j++)
if (lp->fgr[i][j] != -1) {
D_DST(gm.s_bkgd, px + i * gm.f_w, py + j * gm.f_h, gm.f_w, gm.f_h);
D_SRC(gm.s_fig, 0, lp->fgr[i][j] * gm.f_h);
SS_Blt();
}
// add player info
off = gm.f_sml->h + 2;
gm.f_sml->algn = TA_X_L | TA_Y_T;
SF_Wrt(gm.f_sml, gm.s_bkgd, gm.i_x + gm.b_x, gm.i_y, "Player:", 0);
gm.f_sml->algn = TA_X_R | TA_Y_T;
SF_Wrt(gm.f_sml, gm.s_bkgd, gm.scr_w - gm.i_x, gm.i_y, gm.c_prf->nm, 0);
gm.f_sml->algn = TA_X_L | TA_Y_T;
SF_Wrt(gm.f_sml, gm.s_bkgd, gm.i_x + gm.b_x, gm.i_y + off, "Score:", 0);
gm.f_sml->algn = TA_X_R | TA_Y_T;
sprintf(str, "%i", gm.c_prf->scr);
SF_Wrt(gm.f_sml, gm.s_bkgd, gm.scr_w - gm.i_x, gm.i_y + off, str, 0);
gm.f_sml->algn = TA_X_L | TA_Y_T;
SF_Wrt(gm.f_sml, gm.s_bkgd, gm.i_x + gm.b_x, gm.i_y + off*2 + 5, "HighScore:", 0);
gm.f_sml->algn = TA_X_R | TA_Y_T;
sprintf(str, "%i", gm.hi_scr);
SF_Wrt(gm.f_sml, gm.s_bkgd, gm.scr_w - gm.i_x, gm.i_y + off*2 + 5, str, 0);
// add name of levelset above set info
gm.f_sml->algn = TA_X_C | TA_Y_T;
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);
// compute position of first chapter
gm.c_x = 50; // changed
gm.c_y = gm.s_y + (gm.s_h - gm.c_l_st->c_num * L_SIZE) / 2;
// add chapter numbers
gm.f_sml->algn = TA_X_L | TA_Y_T;
for (i = 0; i < gm.c_l_st->c_num; i++) {
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);
}
// draw chapter lights
for (j = 0; j < gm.c_l_st->c_num; j++)
for (i = 0; i < gm.c_l_st->l_num; i++) {
D_DST(gm.s_bkgd, gm.b_x + gm.c_x + i * L_SIZE, gm.c_y + j * L_SIZE, L_SIZE, L_SIZE);
if (!gm.c_s_inf->c_opn[j]) {
D_SRC(gm.s_lghts, L_RED * L_SIZE, 0);
}
else
if ( gm.c_s_inf->cmp[j * gm.c_l_st->l_num + i] ) {
D_SRC(gm.s_lghts, L_GREEN * L_SIZE, 0);
}
else {
D_SRC(gm.s_lghts, L_ORANGE * L_SIZE, 0);
}
SS_Blt();
}
// current level is white
D_DST(gm.s_bkgd, gm.b_x + gm.c_x + l * L_SIZE, gm.c_y + c * L_SIZE, L_SIZE, L_SIZE);
D_SRC(gm.s_lghts, L_WHITE * L_SIZE, 0);
SS_Blt();
// initiate animations
MA_Ini();
// undim
D_FDST(sdl.scr);
D_FSRC(gm.s_bkgd);
SS_Blt();
if (cfg.dim)
SDL_UNDIM();
else
Sdl_FUpd();
// reset timer
T_Rst();
// reset marble and frame
gm.m_mv = 0;
gm.m_sel = 0;
gm.mf_a.p = 0;
gm.msf_a.p = 0;
gm.m_act = M_EMPTY;
gm.m_mx = gm.m_my = -1;
if ( gm.c_l_st->limit_type == TIME ) {
/* set time from seconds to milliseconds if time used */
gm.c_lvl->tm *= 1000;
gm.c_lvl->tm+=1000;
}
else {
/* gm.c_lvl->tm containts the move limit. this is modified according
to the difficulty levels */
switch ( cfg.diff ) {
case DIFF_EASY:
mv_mod = (int)ceil((float)gm.c_lvl->tm * 0.2 * ( 5 - gm.c_ch ) );
gm.c_lvl->tm += mv_mod;
if ( gm.c_lvl->tm % 2 ) gm.c_lvl->tm++;
break;
case DIFF_NORMAL:
mv_mod = (int)ceil((float)gm.c_lvl->tm * 0.1 * ( 5 - gm.c_ch ) );
gm.c_lvl->tm += mv_mod;
if ( gm.c_lvl->tm % 2 ) gm.c_lvl->tm++;
break;
case DIFF_HARD:
mv_mod = (int)ceil((float)gm.c_lvl->tm * 0.05 * ( 5 - gm.c_ch ) );
gm.c_lvl->tm += mv_mod;
if ( gm.c_lvl->tm % 2 ) gm.c_lvl->tm++;
break;
case DIFF_BRAINSTORM:
break;
}
}
// init blink time //
gm.blink_time = 0;
// cursor state
gm.c_stat = C_NONE;
SDL_SetCursor(gm.c_n);
// reset shrapnells
DL_Clr(&gm.shr);
}
/*
draw a map tile to gm.s_bkgd with x,y position in the map using current map
*/
void L_DrwMpTl(int i, int j)
{
switch (gm.c_lvl->map[i][j].t) {
case M_WALL:
// add wall shadow on right side ? //
if ( i + 1 >= gm.c_lvl->m_w || gm.c_lvl->map[i + 1][j].t == M_EMPTY ) {
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);
SS_Fill(0x0);
}
// add wall shadow on bottom ? //
if ( j + 1 >= gm.c_lvl->m_h || gm.c_lvl->map[i][j + 1].t == M_EMPTY ) {
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);
SS_Fill(0x0);
}
// add wall shadow on left side ? //
if ( (i == 0)
|| ((i - 1 >= gm.c_lvl->m_w) || gm.c_lvl->map[i - 1][j].t == M_EMPTY )) {
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);
SS_Fill(0x0);
}
// add wall shadow on top ? //
if ( (j == 0)
|| ((j - 1 >= gm.c_lvl->m_h) || gm.c_lvl->map[i][j - 1].t == M_EMPTY )) {
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);
SS_Fill(0x0);
}
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);
D_SRC(gm.c_g_st->s_wl, gm.c_lvl->map[i][j].id * gm.t_w, 0);
SS_Blt();
break;
case M_CRUMBLE:
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);
D_SRC(gm.c_g_st->s_flr, 0, 0);
SS_Blt();
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);
D_SRC(gm.c_g_st->s_crmbl, gm.c_lvl->map[i][j].id * gm.t_w, 0);
SS_Blt();
gm.f_sml->algn = TA_X_R | TA_Y_B;
switch (gm.c_lvl->map[i][j].id) {
case 0:
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);
break;
case 1:
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);
break;
case 2:
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);
break;
}
break;
case M_EMPTY:
break;
default:
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);
D_SRC(gm.c_g_st->s_flr, 0, 0);
SS_Blt();
break;
}
// static animations ? //
if (!cfg.ani) {
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);
switch (gm.c_lvl->map[i][j].t) {
case M_OW_U:
case M_OW_U_C:
D_SRC(gm.c_g_st->s_u_arw, 0, 0);
SS_Blt();
break;
case M_OW_D:
case M_OW_D_C:
D_SRC(gm.c_g_st->s_d_arw, 0, 0);
SS_Blt();
break;
case M_OW_L:
case M_OW_L_C:
D_SRC(gm.c_g_st->s_l_arw, 0, 0);
SS_Blt();
break;
case M_OW_R:
case M_OW_R_C:
D_SRC(gm.c_g_st->s_r_arw, 0, 0);
SS_Blt();
break;
}
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);
switch (gm.c_lvl->map[i][j].t) {
case M_OW_U_C:
case M_OW_D_C:
D_SRC(gm.c_g_st->s_lr_bar, 0, 0);
SS_Blt();
break;
case M_OW_L_C:
case M_OW_R_C:
D_SRC(gm.c_g_st->s_ud_bar, 0, 0);
SS_Blt();
break;
}
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);
switch (gm.c_lvl->map[i][j].t) {
case M_TLP_0:
D_SRC(gm.c_g_st->s_tlp_0, 0, 0);
SS_ABlt(gm.tlp_a);
break;
case M_TLP_1:
D_SRC(gm.c_g_st->s_tlp_1, 0, 0);
SS_ABlt(gm.tlp_a);
break;
case M_TLP_2:
D_SRC(gm.c_g_st->s_tlp_2, 0, 0);
SS_ABlt(gm.tlp_a);
break;
case M_TLP_3:
D_SRC(gm.c_g_st->s_tlp_3, 0, 0);
SS_ABlt(gm.tlp_a);
break;
}
}
}
/*
proceed to next valid level
*/
int L_FndNxt()
{
int i, j;
// proceed to next level
gm.c_l_id++;
if (gm.c_l_id >= gm.c_l_st->l_num) {
gm.c_l_id = 0;
gm.c_ch++;
// check if this chapter can be entered or if this was the last chapter if not take first unsolved level found
if (gm.c_ch >= gm.c_l_st->c_num || !gm.c_l_st->ch[gm.c_ch].opn) {
for (i = 0; i < gm.c_ch; i++)
for (j = 0; j < gm.c_l_st->l_num; j++)
if (!gm.c_s_inf->cmp[i * gm.c_l_st->l_num + j]) {
// not all levels completed jump back to first unsolved level
gm.c_ch = i;
gm.c_l_id = j;
return 1;
}
if (gm.c_ch >= gm.c_l_st->c_num)
return 0;
else
return 1;
}
}
else {
// check if all levels of this chapter has been solved
for (i = 0; i <= gm.c_ch; i++)
for (j = 0; j < gm.c_l_st->l_num; j++)
if (!gm.c_s_inf->cmp[i * gm.c_l_st->l_num + j]) {
return 1;
}
// yes! open next chapter
if ( gm.c_ch < gm.c_l_st->c_num - 1 )
gm.c_s_inf->c_opn[gm.c_ch + 1] = 1;
}
return 1;
}