/*************************************************************************** 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 #include #include #include #include #include #include #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, "", 0)) { printf("ERROR: line %i: '' 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, "", 0)) { printf("ERROR: line %i: '' 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, "", 0)) { printf("ERROR: line %i: '' 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, "", 0)) { printf("ERROR: line %i: '' 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, "
", 0)) { printf("ERROR: line %i: '
' 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, "
", 0)) { printf("ERROR: line %i: '
' expected\n", f_ln); goto failure; } // map start // F_GetE(f, str, F_SUB | F_VAL); if (!F_CkE(str, F_SUB, "", 0)) { printf("ERROR: line %i: '' 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, "", 0)) { printf("ERROR: line %i: '' expected\n", f_ln); goto failure; } // level end // F_GetE(f, str, F_SUB | F_VAL); if (!F_CkE(str, F_SUB, "
", 0)) { printf("ERROR: line %i: '
' expected\n", f_ln); goto failure; } } // chapter end // F_GetE(f, str, F_SUB); if (!F_CkE(str, F_SUB, "
", 0)) { printf("ERROR: line %i: '
' 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; }