home *** CD-ROM | disk | FTP | other *** search
- // ____________________________________________________
- // | |
- // | Project: POWER VIEW INTERFACE |
- // | File: PVTETRIS.CPP |
- // | Compiler: WPP386 (10.6) |
- // | |
- // | Subject: Tetris implementation |
- // | |
- // | Author: Ivaylo Beltchev |
- // |____________________________________________________|
- //
- // E-mail: ivob@geocities.com
- // URL: http://www.geocities.com/SiliconValley/Bay/2344
-
- #define uses_system
- #define uses_dc
- #define uses_string
- #define uses_desk
- #define uses_win
- #define uses_lbox
- #define uses_dialog
- #define uses_stddlg
- #define uses_input
- #define uses_config
- #define uses_ini
- #define uses_tetris
-
- #include "PVuses.H"
-
- #define CHY 21
- #define CHX 10
- #define MAX_LEVEL 10
-
- #define cmSTART cmUSER00
- #define cmNEXT cmUSER01
- #define cmLEVEL cmUSER02
-
- struct Tpoint {
- int x,y;
- };
-
- typedef Tpoint Tfigure[4];
-
- static long ini_level;
- static boolean ini_nextfl;
-
- static Tfigure figs[7][4]={{{{ 0,-1},{ 0, 0},{ 0, 1},{ 0, 2}},
- {{-1, 0},{ 0, 0},{ 1, 0},{ 2, 0}},
- {{ 0,-1},{ 0, 0},{ 0, 1},{ 0, 2}},
- {{-1, 0},{ 0, 0},{ 1, 0},{ 2, 0}}},
- {{{ 0, 0},{ 1, 0},{ 1, 1},{ 0, 1}},
- {{ 0, 0},{ 1, 0},{ 1, 1},{ 0, 1}},
- {{ 0, 0},{ 1, 0},{ 1, 1},{ 0, 1}},
- {{ 0, 0},{ 1, 0},{ 1, 1},{ 0, 1}}},
- {{{-1, 0},{ 0, 0},{ 1, 0},{ 0, 1}},
- {{ 0,-1},{ 0, 0},{ 0, 1},{-1, 0}},
- {{-1, 0},{ 0, 0},{ 1, 0},{ 0,-1}},
- {{ 0,-1},{ 0, 0},{ 0, 1},{ 1, 0}}},
- {{{-1, 0},{ 0, 0},{ 1, 0},{ 1, 1}},
- {{ 0,-1},{ 0, 0},{ 0, 1},{-1, 1}},
- {{-1, 0},{ 0, 0},{ 1, 0},{-1,-1}},
- {{ 0,-1},{ 0, 0},{ 0, 1},{ 1,-1}}},
- {{{-1, 0},{ 0, 0},{ 1, 0},{-1, 1}},
- {{ 0,-1},{ 0, 0},{ 0, 1},{-1,-1}},
- {{-1, 0},{ 0, 0},{ 1, 0},{ 1,-1}},
- {{ 0,-1},{ 0, 0},{ 0, 1},{ 1, 1}}},
- {{{-1, 0},{ 0, 0},{ 0, 1},{ 1, 1}},
- {{ 0,-1},{ 0, 0},{-1, 0},{-1, 1}},
- {{-1, 0},{ 0, 0},{ 0, 1},{ 1, 1}},
- {{ 0,-1},{ 0, 0},{-1, 0},{-1, 1}}},
- {{{-1, 1},{ 0, 1},{ 0, 0},{ 1, 0}},
- {{ 0,-1},{ 0, 0},{ 1, 0},{ 1, 1}},
- {{-1, 1},{ 0, 1},{ 0, 0},{ 1, 0}},
- {{ 0,-1},{ 0, 0},{ 1, 0},{ 1, 1}}}};
-
- class Ttetris: public Titem
- {
- public:
- char chasha[CHY+5][CHX*4+2];
- int nextfl;
- int curfig;
- int nextfig;
- int currot;
- int curx,cury;
- boolean gameover;
- uint speed;
- int score;
- int lines;
- int points;
- int level;
-
- Ttetris( void );
- virtual ~Ttetris( void );
- inline void plot(int x,int y,char c);
- inline char getpix(int x,int y);
- void drawfig(int x,int y,int f,int rot);
- void clrfig(int x,int y,int f,int rot);
- boolean testfig(int x,int y,int f,int rot);
- boolean movefig(int x,int y,int rot);
- void newfig( void );
- void init_chasha( void );
- boolean newgame( void );
- inline void nextlev( void );
- inline boolean rotate( void );
- inline boolean left( void );
- inline boolean right( void );
- inline void drop_down( void );
-
- protected:
- virtual void set_palette( void );
- virtual void draw( void );
- virtual void get_focused( void );
- virtual boolean release_focus( void );
- virtual void event_handler(Tevent &ev);
- };
-
- static int tetnum=0;
- static uint time_speed=1;
- static int timer_handle=-1;
-
- static void timer( void )
- {
- call_request( timer_handle, timer, time_speed );
- if( !event_present() )
- {
- #ifdef __386__
- static
- #endif
- Tevent ev1;
- ev1.code=evCOMMAND;
- ev1.CMD_CODE=cmTETRIS_TIMER;
- ev1.destination=NULL;
- ev1.priority = epKEY_PRESS;
- ev1.CMD_INFO=NULL;
- ev1.CMD_SIZE=0;
- put_event(ev1);
- }
- }
-
- Ttetris::Ttetris( void ):
- Titem( CHX*2+14, CHY )
- {
- int tmr;
- #ifdef __FLAT__
- int *system_timer = (int *) BIOS_DTA( 0x6C );
- tmr = *system_timer;
- #else
- int far *system_timer = (int *) BIOS_DTA( 0x6C );
- do { tmr = *system_timer; } while( tmr!=*system_timer );
- #endif
- srand(tmr);
- grow_mode=gmDONT_GROW;
- #ifdef CYR
- Twindow *w=NEW( Twindow( "ÆÑ▓░¿▒", xl+4, yl+2 ) );
- #else
- Twindow *w=NEW( Twindow( "Tetris", xl+4, yl+2 ) );
- #endif
- w->set_flags( ifRESIZEABLE+ifTILEABLE, 0 );
- w->palette = wpTOOL;
- w->grow_mode = gmDONT_GROW;
- w->put_in( this, 2, 1 );
- #ifndef NOHELP
- w->help_ctx=help_ctx;
- #endif
- #ifdef CYR
- Tbutton *b0=NEW( Tbutton( " |~æ½Ññóá ", cmNEXT ) );
- Tbutton *b1=NEW( Tbutton( " |~ì¿ó« ", cmLEVEL ) );
- Tbutton *b2=NEW( Tbutton( " |~ÉÑ▒▓á░▓ ", cmSTART ) );
- Tbutton *b3=NEW( Tbutton( " è║╕ ", cmWIN_CLOSE ) );
- #ifndef NOHELP
- w->put_in( NEW( Tbutton( " Å«¼«╣ ", cmHELP ) ), CHX*2+5, CHY-2 );
- #endif
- #else
- Tbutton *b0=NEW( Tbutton( " |~Next ", cmNEXT ) );
- Tbutton *b1=NEW( Tbutton( " |~Level ", cmLEVEL ) );
- Tbutton *b2=NEW( Tbutton( " |~Restart ", cmSTART ) );
- Tbutton *b3=NEW( Tbutton( " Close ", cmWIN_CLOSE ) );
- #ifndef NOHELP
- w->put_in( NEW( Tbutton( " Help ", cmHELP ) ), CHX*2+5, CHY-2 );
- #endif
- #endif
- b0->set_flags( bfBROADCAST, 1 ); b0->shortcut='1';
- b1->set_flags( bfBROADCAST, 1 ); b1->shortcut=kBS;
- b2->set_flags( bfBROADCAST, 1 ); b2->shortcut=kCTRL_R;
- b3->shortcut=kESC;
- w->put_in( b0, CHX*2+5, CHY-8 );
- w->put_in( b1, CHX*2+5, CHY-6 );
- w->put_in( b2, CHX*2+5, CHY-4 );
- w->put_in( b3, CHX*2+5, CHY );
- gameover=1;
- nextfl=ini_nextfl;
- level=ini_level;
- if( !newgame() ) set_state( isVALID, 0 );
- if (!tetnum++)
- {
- timer_handle = alloc_timer();
- timer();
- }
- focus();
- insert_window( w, xCENTER, yCENTER );
- }
-
- Ttetris::~Ttetris( void )
- {
- if( !--tetnum ) free_timer( timer_handle );
- }
-
- void Ttetris::init_chasha( void )
- {
- int x,y;
-
- memset( chasha, ' ', sizeof( chasha ) );
- for( y=0; y<CHY+4; y++ ) {
- for (x=0;x<CHX;x++) {
- chasha[y][x*4] = '|';
- chasha[y][x*4+1] = (x%2)+'0';
- }
- chasha[y][x*4] = '|';
- chasha[y][x*4+1] = 'n';
- }
- chasha[y][0] = 0;
- }
-
- boolean Ttetris::newgame( void )
- {
- #ifdef CYR
- dialog("ì«óá ¿ú░á");
- iinput("ìá╖ὡ« ¡¿ó«:",level,1,10);
- #else
- dialog("New tetris");
- iinput("Startup level:",level,1,10);
- #endif
- if (!bkc()) return 0;
- init_chasha();
- nextfig=rand()%7;
- score=0;
- lines=0;
- level--;
- points=0;
- gameover=0;
- nextlev();
- newfig();
- return 1;
- }
-
- void Ttetris::nextlev( void )
- {
- if( level<MAX_LEVEL )
- speed=MAX_LEVEL-level++;
- time_speed=speed;
- }
-
- void Ttetris::set_palette( void )
- {
- int i;
-
- Titem::set_palette();
- attr[0]=0x0F;
- attr[1]=0x8F;
- if( scr_bw )
- for( i=2; i<9; i++ ) attr[i]=0xF0;
- else
- {
- attr[2]=0x9F;
- attr[3]=0xAF;
- attr[4]=0xBF;
- attr[5]=0xCF;
- attr[6]=0xDF;
- attr[7]=0xEF;
- attr[8]=0xF0;
- }
- if( !state( isFOCUSED ) )
- for( i=2; i<9; i++ ) attr[i]&=0x7F;
- }
-
- void Ttetris::draw( void )
- {
- txt( chasha[4] );
- int bx=current_dc->base_x;
- int by=current_dc->base_y;
- if( gameover )
- {
- set_base( bx+(CHX*2-13)/2, by+2 );
- #ifdef CYR
- txtf( "|5%c|r\014%c%c|n%c èÉÇë %c|n%c|r\014%c%c",
- #else
- txtf( "|5%c|r\014%c%c|n%c GAME OVER %c|n%c|r\014%c%c",
- #endif
- frame_normal[0],frame_normal[1],frame_normal[2],
- frame_normal[3],frame_normal[5],
- frame_normal[6],frame_normal[7],frame_normal[8] );
- }
- set_base( bx+CHX*2+2, by );
- #ifdef CYR
- txtf("|nÆ«╖¬¿:|b%6d|n|tï¿¡¿¿:|b%6d|n|tì¿ó«: |b%6d|n|n|tæ½Ññóá:|n|0|r\014 |l\004",
- score, lines, level );
- #else
- txtf("|nScore:|b%6d|n|tLines:|b%6d|n|tLevel:|b%6d|n|n|tNext:|n|0|r\014 |l\004",
- score, lines, level );
- #endif
- if( nextfl )
- for( int i=0; i<4; i++ )
- {
- goto_xy( figs[nextfig][!nextfig][i].x*2-!nextfig+5-(nextfig==1),
- figs[nextfig][!nextfig][i].y+7 );
- txtf( "|%c ", nextfig+'2' );
- }
- }
-
- inline void Ttetris::plot(int x,int y,char c)
- {
- chasha[y+4][(x<<2)+1]=c+'0';
- }
-
- inline char Ttetris::getpix(int x,int y)
- {
- return chasha[y+4][(x<<2)+1]-'0';
- }
-
- void Ttetris::drawfig(int x,int y,int f,int rot)
- {
- int i;
-
- for (i=0;i<4;i++)
- plot(figs[f][rot][i].x+x,figs[f][rot][i].y+y,f+2);
- }
-
- void Ttetris::clrfig(int x,int y,int f,int rot)
- {
- int i;
-
- for (i=0;i<4;i++)
- {
- int xx = figs[f][rot][i].x+x;
- plot(xx,figs[f][rot][i].y+y,xx%2);
- }
- }
-
- boolean Ttetris::testfig(int x,int y,int f,int rot)
- {
- int i,xx,yy;
-
- for (i=0;i<4;i++) {
- xx=x+figs[f][rot][i].x;
- if (xx<0 || xx>=CHX) return 0;
- yy=y+figs[f][rot][i].y;
- if (yy<-4 || yy>=CHY) return 0;
- if (getpix(xx,yy)>1) return 0;
- }
- return 1;
- }
-
- boolean Ttetris::movefig(int x,int y,int rot)
- {
- clrfig(curx,cury,curfig,currot);
- if (testfig(x,y,curfig,rot)) {
- curx=x;
- cury=y;
- currot=rot;
- drawfig(x,y,curfig,rot);
- return 1;
- }
- drawfig(curx,cury,curfig,currot);
- return 0;
- }
-
- void Ttetris::newfig( void )
- {
- int x,y,y1;
-
- curfig=nextfig;
- nextfig=rand()%7;
- score+=points;
- points=level*5+20;
- for (y=CHY-1;y>=0;y--) {
- for (x=0;x<CHX;x++)
- if (getpix(x,y)<=1) goto nodel;
- for (y1=y+3;y1>0;y1--)
- memcpy(chasha[y1+1],chasha[y1],sizeof(chasha[y1]));
- for (x=0;x<CHX;x++)
- plot(x,y1,x%2);
- lines++;
- y++;
- nodel:
- continue;
- }
- if (level<MAX_LEVEL)
- while (lines/10>level) nextlev();
- currot=0;
- curx=5;
- cury=-3;
- if (!testfig(curx,cury,curfig,currot)) gameover=1;
- }
-
- void Ttetris::get_focused( void )
- {
- time_speed=speed;
- cenable( cmNEXT ); cenable( cmSTART ); cenable( cmLEVEL );
- }
-
- boolean Ttetris::release_focus( void )
- {
- if( !Titem::release_focus() ) return 0;
- cdisable( cmNEXT ); cdisable( cmSTART ); cdisable( cmLEVEL );
- return 1;
- }
-
- inline boolean Ttetris::rotate( void )
- {
- boolean f=movefig(curx,cury,(currot-1)&3);
- points-=f;
- return f;
- }
-
- inline boolean Ttetris::left( void )
- {
- return movefig(curx-1,cury,currot);
- }
-
- inline boolean Ttetris::right( void )
- {
- return movefig(curx+1,cury,currot);
- }
-
- inline void Ttetris::drop_down( void )
- {
- while (movefig(curx,cury+1,currot));
- }
-
- void Ttetris::event_handler(Tevent &ev)
- {
- Titem::event_handler( ev );
- switch( ev.code )
- {
- case evKEY_PRESS:
- if( !state( isFOCUSED ) ) return;
- if( ev.ASCII==kTAB || ev.ASCII==kSHIFT_TAB) break;
- if( gameover || !state( isFOCUSED ) ) return;
- switch(ev.ASCII)
- {
- case kHOME :
- case kLEFT : left(); break;
- case kPG_UP :
- case kRIGHT : right(); break;
- case kUP : rotate(); break;
- case ' ' :
- case kDOWN : drop_down(); break;
- default : return;
- }
- break;
- #ifndef NOMOUSE
- case evMOUSE_DOWN:
- if( gameover || !ev.INSIDE ) return;
- if( ev.BUTTON )
- rotate();
- else
- {
- int mx=ev.LOCAL_X/2;
- while( curx>mx && left() );
- while( curx<mx && right() );
- if( ev.CLICKS%2 ) drop_down();
- }
- break;
- #endif
- case evCOMMAND:
- switch( ev.CMD_CODE )
- {
- case cmTETRIS_TIMER:
- if( !state(isFOCUSED) || gameover ) return;
- if( owner->state(isICONIZED) ) break;
- if (!movefig(curx,cury+1,currot)) newfig();
- points--;
- points-=nextfl;
- break;
- case cmSTART:
- newgame();
- break;
- case cmNEXT:
- nextfl=!nextfl;
- break;
- case cmLEVEL:
- nextlev();
- break;
- default:
- return;
- }
- break;
- default:
- return;
- }
- redraw();
- handled( ev );
- }
-
- void tetris( void )
- {
- _context( cxTETRIS ); NEW( Ttetris() );
- }
-
- void __init_tetris( void )
- {
- #ifndef NOCONFIG
- seek_section( 0, SECTION_TETRIS );
- ini( VAR_LEVEL, ini_level, 7 );
- ini( VAR_NEXT, ini_nextfl, 1 );
- #endif
- }
-