#define SPRSIZE 8 #define PITXOFF (SPRSIZE*2+((MAXPITWIDTH-PITWIDTH)*SPRSIZE/2)) #define PITYOFF SPRSIZE*4 #define PITX(x) (((x)*SPRSIZE)+PITXOFF) #define PITY(y) (((y)*SPRSIZE)+PITYOFF) #define SCOREPX 200 #define SCOREX (SCOREPX+50) #define SCOREY 20 #define LEVELPX 200 #define LEVELX (LEVELPX+50) #define LEVELY 40 #define NEXTPX 200 #define NEXTX (NEXTPX+50) #define NEXTY 100 #define NODIR -1 #define LEFT 0 #define UP 1 #define RIGHT 2 #define DOWN 3 #define PATHLEN (MAXPITWIDTH*PITDEPTH) #define ROR(x) ((x) ? ((x)-1) : (3)) #define ROL(x) (((x)+1)%4) int xi[4]={-1,0,1,0}; int yi[4]={0,-1,0,1}; typedef struct { int score; int level; char name[4]; } Hisc; typedef struct { int x,y; int level; int score; int rotate; int is_special; int current_type; Piece current; int next_is_special; int next_type; Piece next; } Game; Game game; /* ------------------------------------------------------------------------- WIRE ROTATE PIECE UTILS ------------------------------------------------------------------------- */ int ROL_Piece(int tile) { /* This should be in a table, but using sprite numbers for the tile codes makes that not so neat */ switch(tile) { case CROSS: return(CROSS); break; case UPDOWN: return(ACROSS); break; case ACROSS: return(UPDOWN); break; case LEFTDOWN: return(LEFTUP); break; case RIGHTDOWN: return(LEFTDOWN); break; case LEFTUP: return(RIGHTUP); break; case RIGHTUP: return(RIGHTDOWN); break; default: return(BLANK); break; } } int ROR_Piece(int tile) { /* This should be in a table, but using sprite numbers for the tile codes makes that not so neat */ switch(tile) { case CROSS: return(CROSS); break; case UPDOWN: return(ACROSS); break; case ACROSS: return(UPDOWN); break; case LEFTDOWN: return(RIGHTDOWN); break; case RIGHTDOWN: return(RIGHTUP); break; case LEFTUP: return(LEFTDOWN); break; case RIGHTUP: return(LEFTUP); break; default: return(BLANK); break; } } /* ------------------------------------------------------------------------- WIRE PATH UTILS ------------------------------------------------------------------------- */ int Dir(int tile,int dir) { switch(tile) /* This should be in a table, but */ { /* using sprite numbers for the tile */ case CROSS: /* codes makes that not so neat */ return(dir); break; case UPDOWN: if ((dir==UP)||(dir==DOWN)) return(dir); else return(NODIR); break; case ACROSS: if ((dir==LEFT)||(dir==RIGHT)) return(dir); else return(NODIR); break; case LEFTDOWN: if (dir==RIGHT) return(DOWN); else if (dir==UP) return(LEFT); else return(NODIR); break; case RIGHTDOWN: if (dir==LEFT) return(DOWN); else if (dir==UP) return(RIGHT); else return(NODIR); break; case LEFTUP: if (dir==RIGHT) return(UP); else if (dir==DOWN) return(LEFT); else return(NODIR); break; case RIGHTUP: if (dir==LEFT) return(UP); else if (dir==DOWN) return(RIGHT); else return(NODIR); break; default: return(NODIR); break; } } int FindPathFrom(int sx,int sy,int dir,Path *p) { dir=Dir(pit.data[sy][sx],dir); if (dir==NODIR) { p->len=0; return (FALSE); } p->p[p->len].x=sx; p->p[p->len].y=sy; p->len++; sx+=xi[dir]; sy+=yi[dir]; if (sy==-1) { return (FALSE); p->len=0; } if ((sx==-1)||(sx==PITWIDTH)||(sy==PITDEPTH)) return (TRUE); else return (FindPathFrom(sx,sy,dir,p)); } int FindPath(Path *p) { int f; p->len=0; for(f=PITDEPTH-1;f>=0;f--) { if (FindPathFrom(0,f,RIGHT,p)) return (TRUE); if (FindPathFrom(PITWIDTH-1,f,LEFT,p)) return (TRUE); } for(f=0;flen=0; return (FALSE); } p->p[p->len].x=x; p->p[p->len].y=y; p->len++; x+=xi[dir]; y+=yi[dir]; if ((x==ox)&&(y==oy)) return (TRUE); else return (FindLoopFrom(ox,oy,x,y,dir,p)); } int FindLoop(Path *p) { int x,y; p->len=0; for(y=PITDEPTH-1;y>=0;y--) for(x=0;xp[p->len].x=x; p->p[p->len].y=y; p->len++; } } void GetSpecialPath(Path *p) { p->len=0; if (game.y>0) GetSpecialPathFromTile(pit.data[game.y-1][game.x],p); if (game.y<(PITDEPTH-1)) GetSpecialPathFromTile(pit.data[game.y+1][game.x],p); if (game.x>0) GetSpecialPathFromTile(pit.data[game.y][game.x-1],p); if (game.x<(PITWIDTH-1)) GetSpecialPathFromTile(pit.data[game.y][game.x+1],p); } void DrawPath(Path *p) { } /* ------------------------------------------------------------------------- SCORE UTILS ------------------------------------------------------------------------- */ #define DSNO 3 #define DSFADE (SLOW ? (10) : (20)) struct { char p[80]; int sc; int col; int cnt; } dispsc[DSNO]; void InitScores(void) { int f; for(f=0;f=0;f--) dispsc[f+1]=dispsc[f]; strcpy(dispsc[0].p,s); dispsc[0].sc=sc; dispsc[0].col=MELTOMAX-1; dispsc[0].cnt=DSFADE; } void UpdateScores(void) { int f; char s[80]; for(f=0;fpiece[RND(ps->no)]; } game.next.ox=tetris_off[game.next_type][0].x; game.next.oy=tetris_off[game.next_type][0].y; } } void RotTetrisWirePiece(int dir) { int x,y; Piece p; if (game.is_special) return; if (dir==LEFT) { game.rotate=ROL(game.rotate); for(x=0;x<4;x++) for(y=0;y<4;y++) p.data[x][3-y]=ROL_Piece(game.current.data[y][x]); p.ox=tetris_off[game.current_type][game.rotate].x; p.oy=tetris_off[game.current_type][game.rotate].y; } else { game.rotate=ROR(game.rotate); for(x=0;x<4;x++) for(y=0;y<4;y++) p.data[3-x][y]=ROR_Piece(game.current.data[y][x]); p.ox=tetris_off[game.current_type][game.rotate].x; p.oy=tetris_off[game.current_type][game.rotate].y; } game.current=p; } /* ------------------------------------------------------------------------- PLAY GAME UTILS ------------------------------------------------------------------------- */ int MoveOK(int x, int y) { int cx,cy,nx,ny; for(cx=0;cx<4;cx++) for(cy=0;cy<4;cy++) if (game.current.data[cy][cx]!=BLANK) { nx=x+cx-game.current.ox; ny=y+cy-game.current.oy; if ((nx<0)||(nx>=PITWIDTH)||(ny>=PITDEPTH)) return(FALSE); if ((ny>=0)&&(pit.data[ny][nx]!=BLANK)) return(FALSE); } return(TRUE); } int AddAndCheckIsDead(int id) { int cx,cy,nx,ny; if (game.is_special) return(game.y<0); else for(cx=0;cx<4;cx++) for(cy=0;cy<4;cy++) if (game.current.data[cy][cx]!=BLANK) { nx=game.x+cx-game.current.ox; ny=game.y+cy-game.current.oy; if ((nx<0)||(nx>=PITWIDTH)||(ny<0)||(ny>=PITDEPTH)) return(TRUE); pit.data[ny][nx]=game.current.data[cy][cx]; pit.id[ny][nx]=id; } return(FALSE); } void UnglueID(int id) { int x,y; for(x=0;x=0) if (pit.data[y][x]!=BLANK) return (pit.id[y][x]==0); else y--; return(FALSE); } void CompressBlanks(void) { int x,y,ny; for(x=0;xhisc[MODE][f].score) sc=f; for(f=HISC-1;f>sc;f--) hisc[MODE][f]=hisc[MODE][f-1]; strcpy(hisc[MODE][sc].name,""); hisc[MODE][sc].level=LEVEL; hisc[MODE][sc].score=game.score; if (MUSIC) play_midi(score_midi,TRUE); text_mode(0); /* Go and do entry */ while(!done) { rectfill(img,0,0,SCREEN_W-1,50,BLACK); CENTRE(hisc_let,20,WHITE); draw_rle_sprite(img,SPR(spr),sbx+curs*8,17); if ((ctr++%10)==0) if (++spr>HISC_CURS3) spr=HISC_CURS1; CENTRE("ENTER YOUR INITIALS",CY,CYAN); k=GETKEY; if ((k==KLEFT)||(k==KEY_LEFT)) { SoundFX(CLICK_FX); if (len==3) { if (curs==sl-2) curs=sl-1; else curs=sl-2; } else { if (curs) curs--; else curs=sl-1; } } else if((k==KRIGHT)||(k==KEY_RIGHT)) { SoundFX(CLICK_FX); if (len==3) { if (curs==sl-2) curs=sl-1; else curs=sl-2; } else { if (curs==(sl-1)) curs=0; else curs++; } } else if ((k==KDROP)||(k==KEY_SPACE)) { SoundFX(POP_FX); switch(hisc_let[curs]) { case '<': if (len) { len--; hisc[MODE][sc].name[len]=0; } break; case '>': done=TRUE; break; default: hisc[MODE][sc].name[len]=hisc_let[curs]; hisc[MODE][sc].name[++len]=0; if (len==3) curs=sl-1; break; } } for(f=0;f