home *** CD-ROM | disk | FTP | other *** search
/ Visual Basic Source Code / Visual Basic Source Code.iso / vbsource / powervww / pvtetris.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-05  |  12.5 KB  |  508 lines

  1. //  ____________________________________________________
  2. // |                                                    |
  3. // |  Project:     POWER VIEW INTERFACE                 |
  4. // |  File:        PVTETRIS.CPP                         |
  5. // |  Compiler:    WPP386 (10.6)                        |
  6. // |                                                    |
  7. // |  Subject:     Tetris implementation                |
  8. // |                                                    |
  9. // |  Author:      Ivaylo Beltchev                      |
  10. // |____________________________________________________|
  11. //
  12. // E-mail: ivob@geocities.com
  13. // URL:    http://www.geocities.com/SiliconValley/Bay/2344
  14.  
  15. #define uses_system
  16. #define uses_dc
  17. #define uses_string
  18. #define uses_desk
  19. #define uses_win
  20. #define uses_lbox
  21. #define uses_dialog
  22. #define uses_stddlg
  23. #define uses_input
  24. #define uses_config
  25. #define uses_ini
  26. #define uses_tetris
  27.  
  28. #include "PVuses.H"
  29.  
  30. #define CHY             21
  31. #define CHX             10
  32. #define MAX_LEVEL       10
  33.  
  34. #define cmSTART         cmUSER00
  35. #define cmNEXT          cmUSER01
  36. #define cmLEVEL         cmUSER02
  37.  
  38. struct Tpoint {
  39.   int x,y;
  40. };
  41.  
  42. typedef Tpoint Tfigure[4];
  43.  
  44. static long ini_level;
  45. static boolean ini_nextfl;
  46.  
  47. static Tfigure figs[7][4]={{{{ 0,-1},{ 0, 0},{ 0, 1},{ 0, 2}},
  48.                            {{-1, 0},{ 0, 0},{ 1, 0},{ 2, 0}},
  49.                            {{ 0,-1},{ 0, 0},{ 0, 1},{ 0, 2}},
  50.                            {{-1, 0},{ 0, 0},{ 1, 0},{ 2, 0}}},
  51.                           {{{ 0, 0},{ 1, 0},{ 1, 1},{ 0, 1}},
  52.                           {{ 0, 0},{ 1, 0},{ 1, 1},{ 0, 1}},
  53.                            {{ 0, 0},{ 1, 0},{ 1, 1},{ 0, 1}},
  54.                            {{ 0, 0},{ 1, 0},{ 1, 1},{ 0, 1}}},
  55.                           {{{-1, 0},{ 0, 0},{ 1, 0},{ 0, 1}},
  56.                            {{ 0,-1},{ 0, 0},{ 0, 1},{-1, 0}},
  57.                            {{-1, 0},{ 0, 0},{ 1, 0},{ 0,-1}},
  58.                            {{ 0,-1},{ 0, 0},{ 0, 1},{ 1, 0}}},
  59.                           {{{-1, 0},{ 0, 0},{ 1, 0},{ 1, 1}},
  60.                            {{ 0,-1},{ 0, 0},{ 0, 1},{-1, 1}},
  61.                            {{-1, 0},{ 0, 0},{ 1, 0},{-1,-1}},
  62.                            {{ 0,-1},{ 0, 0},{ 0, 1},{ 1,-1}}},
  63.                           {{{-1, 0},{ 0, 0},{ 1, 0},{-1, 1}},
  64.                            {{ 0,-1},{ 0, 0},{ 0, 1},{-1,-1}},
  65.                            {{-1, 0},{ 0, 0},{ 1, 0},{ 1,-1}},
  66.                            {{ 0,-1},{ 0, 0},{ 0, 1},{ 1, 1}}},
  67.                           {{{-1, 0},{ 0, 0},{ 0, 1},{ 1, 1}},
  68.                            {{ 0,-1},{ 0, 0},{-1, 0},{-1, 1}},
  69.                            {{-1, 0},{ 0, 0},{ 0, 1},{ 1, 1}},
  70.                            {{ 0,-1},{ 0, 0},{-1, 0},{-1, 1}}},
  71.                           {{{-1, 1},{ 0, 1},{ 0, 0},{ 1, 0}},
  72.                            {{ 0,-1},{ 0, 0},{ 1, 0},{ 1, 1}},
  73.                            {{-1, 1},{ 0, 1},{ 0, 0},{ 1, 0}},
  74.                            {{ 0,-1},{ 0, 0},{ 1, 0},{ 1, 1}}}};
  75.  
  76. class Ttetris: public Titem
  77. {
  78.   public:
  79.     char chasha[CHY+5][CHX*4+2];
  80.     int  nextfl;
  81.     int  curfig;
  82.     int  nextfig;
  83.     int  currot;
  84.     int  curx,cury;
  85.     boolean gameover;
  86.     uint speed;
  87.     int  score;
  88.     int  lines;
  89.     int  points;
  90.     int  level;
  91.  
  92.     Ttetris( void );
  93.     virtual ~Ttetris( void );
  94.     inline void plot(int x,int y,char c);
  95.     inline char getpix(int x,int y);
  96.     void drawfig(int x,int y,int f,int rot);
  97.     void clrfig(int x,int y,int f,int rot);
  98.     boolean testfig(int x,int y,int f,int rot);
  99.     boolean movefig(int x,int y,int rot);
  100.     void newfig( void );
  101.     void init_chasha( void );
  102.     boolean newgame( void );
  103.     inline void nextlev( void );
  104.     inline boolean rotate( void );
  105.     inline boolean left( void );
  106.     inline boolean right( void );
  107.     inline void drop_down( void );
  108.  
  109.   protected:
  110.     virtual void set_palette( void );
  111.     virtual void draw( void );
  112.     virtual void get_focused( void );
  113.     virtual boolean release_focus( void );
  114.     virtual void event_handler(Tevent &ev);
  115. };
  116.  
  117. static int tetnum=0;
  118. static uint time_speed=1;
  119. static int timer_handle=-1;
  120.  
  121. static void timer( void )
  122. {
  123.   call_request( timer_handle, timer, time_speed );
  124.   if( !event_present() )
  125.   {
  126. #ifdef __386__
  127.     static
  128. #endif
  129.            Tevent ev1;
  130.     ev1.code=evCOMMAND;
  131.     ev1.CMD_CODE=cmTETRIS_TIMER;
  132.     ev1.destination=NULL;
  133.     ev1.priority = epKEY_PRESS;
  134.     ev1.CMD_INFO=NULL;
  135.     ev1.CMD_SIZE=0;
  136.     put_event(ev1);
  137.   }
  138. }
  139.  
  140. Ttetris::Ttetris( void ):
  141.   Titem( CHX*2+14, CHY )
  142. {
  143.   int tmr;
  144. #ifdef __FLAT__
  145.   int *system_timer = (int *) BIOS_DTA( 0x6C );
  146.   tmr = *system_timer;
  147. #else
  148.   int far *system_timer = (int *) BIOS_DTA( 0x6C );
  149.   do { tmr = *system_timer; } while( tmr!=*system_timer );
  150. #endif
  151.   srand(tmr);
  152.   grow_mode=gmDONT_GROW;
  153. #ifdef CYR
  154.   Twindow *w=NEW( Twindow( "ÆÑ▓░¿▒", xl+4, yl+2 ) );
  155. #else
  156.   Twindow *w=NEW( Twindow( "Tetris", xl+4, yl+2 ) );
  157. #endif
  158.   w->set_flags( ifRESIZEABLE+ifTILEABLE, 0 );
  159.   w->palette = wpTOOL;
  160.   w->grow_mode = gmDONT_GROW;
  161.   w->put_in( this, 2, 1 );
  162. #ifndef NOHELP
  163.   w->help_ctx=help_ctx;
  164. #endif
  165. #ifdef CYR
  166.   Tbutton *b0=NEW( Tbutton( " |~æ½Ññóá  ", cmNEXT ) );
  167.   Tbutton *b1=NEW( Tbutton( "  |~ì¿ó«   ", cmLEVEL ) );
  168.   Tbutton *b2=NEW( Tbutton( " |~ÉÑ▒▓á░▓ ", cmSTART ) );
  169.   Tbutton *b3=NEW( Tbutton( "   è║╕   ", cmWIN_CLOSE ) );
  170. #ifndef NOHELP
  171.   w->put_in( NEW( Tbutton(  "  Å«¼«╣  ", cmHELP ) ), CHX*2+5, CHY-2 );
  172. #endif
  173. #else
  174.   Tbutton *b0=NEW( Tbutton( "  |~Next   ", cmNEXT ) );
  175.   Tbutton *b1=NEW( Tbutton( "  |~Level  ", cmLEVEL ) );
  176.   Tbutton *b2=NEW( Tbutton( " |~Restart ", cmSTART ) );
  177.   Tbutton *b3=NEW( Tbutton( "  Close  ", cmWIN_CLOSE ) );
  178. #ifndef NOHELP
  179.   w->put_in( NEW( Tbutton(  "  Help   ", cmHELP ) ), CHX*2+5, CHY-2 );
  180. #endif
  181. #endif
  182.   b0->set_flags( bfBROADCAST, 1 ); b0->shortcut='1';
  183.   b1->set_flags( bfBROADCAST, 1 ); b1->shortcut=kBS;
  184.   b2->set_flags( bfBROADCAST, 1 ); b2->shortcut=kCTRL_R;
  185.                                    b3->shortcut=kESC;
  186.   w->put_in( b0, CHX*2+5, CHY-8 );
  187.   w->put_in( b1, CHX*2+5, CHY-6 );
  188.   w->put_in( b2, CHX*2+5, CHY-4 );
  189.   w->put_in( b3, CHX*2+5, CHY   );
  190.   gameover=1;
  191.   nextfl=ini_nextfl;
  192.   level=ini_level;
  193.   if( !newgame() ) set_state( isVALID, 0 );
  194.   if (!tetnum++)
  195.   {
  196.     timer_handle = alloc_timer();
  197.     timer();
  198.   }
  199.   focus();
  200.   insert_window( w, xCENTER, yCENTER );
  201. }
  202.  
  203. Ttetris::~Ttetris( void )
  204. {
  205.   if( !--tetnum ) free_timer( timer_handle );
  206. }
  207.  
  208. void Ttetris::init_chasha( void )
  209. {
  210.   int x,y;
  211.  
  212.   memset( chasha, ' ', sizeof( chasha ) );
  213.   for( y=0; y<CHY+4; y++ ) {
  214.     for (x=0;x<CHX;x++) {
  215.       chasha[y][x*4] = '|';
  216.       chasha[y][x*4+1] = (x%2)+'0';
  217.     }
  218.     chasha[y][x*4] = '|';
  219.     chasha[y][x*4+1] = 'n';
  220.   }
  221.   chasha[y][0] = 0;
  222. }
  223.  
  224. boolean Ttetris::newgame( void )
  225. {
  226. #ifdef CYR
  227.   dialog("ì«óá ¿ú░á");
  228.   iinput("ìá╖ὡ« ¡¿ó«:",level,1,10);
  229. #else
  230.   dialog("New tetris");
  231.   iinput("Startup level:",level,1,10);
  232. #endif
  233.   if (!bkc()) return 0;
  234.   init_chasha();
  235.   nextfig=rand()%7;
  236.   score=0;
  237.   lines=0;
  238.   level--;
  239.   points=0;
  240.   gameover=0;
  241.   nextlev();
  242.   newfig();
  243.   return 1;
  244. }
  245.  
  246. void Ttetris::nextlev( void )
  247. {
  248.   if( level<MAX_LEVEL )
  249.     speed=MAX_LEVEL-level++;
  250.   time_speed=speed;
  251. }
  252.  
  253. void Ttetris::set_palette( void )
  254. {
  255.   int i;
  256.  
  257.   Titem::set_palette();
  258.   attr[0]=0x0F;
  259.   attr[1]=0x8F;
  260.   if( scr_bw )
  261.     for( i=2; i<9; i++ ) attr[i]=0xF0;
  262.   else
  263.   {
  264.     attr[2]=0x9F;
  265.     attr[3]=0xAF;
  266.     attr[4]=0xBF;
  267.     attr[5]=0xCF;
  268.     attr[6]=0xDF;
  269.     attr[7]=0xEF;
  270.     attr[8]=0xF0;
  271.   }
  272.   if( !state( isFOCUSED ) )
  273.     for( i=2; i<9; i++ ) attr[i]&=0x7F;
  274. }
  275.  
  276. void Ttetris::draw( void )
  277. {
  278.   txt( chasha[4] );
  279.   int bx=current_dc->base_x;
  280.   int by=current_dc->base_y;
  281.   if( gameover )
  282.   {
  283.     set_base( bx+(CHX*2-13)/2, by+2 );
  284. #ifdef CYR
  285.     txtf( "|5%c|r\014%c%c|n%c    èÉÇë    %c|n%c|r\014%c%c",
  286. #else
  287.     txtf( "|5%c|r\014%c%c|n%c GAME  OVER %c|n%c|r\014%c%c",
  288. #endif
  289.     frame_normal[0],frame_normal[1],frame_normal[2],
  290.     frame_normal[3],frame_normal[5],
  291.     frame_normal[6],frame_normal[7],frame_normal[8] );
  292.   }
  293.   set_base( bx+CHX*2+2, by );
  294. #ifdef CYR
  295.   txtf("|nÆ«╖¬¿:|b%6d|n|tï¿¡¿¿:|b%6d|n|tì¿ó«: |b%6d|n|n|tæ½Ññóá:|n|0|r\014 |l\004",
  296.     score, lines, level );
  297. #else
  298.   txtf("|nScore:|b%6d|n|tLines:|b%6d|n|tLevel:|b%6d|n|n|tNext:|n|0|r\014 |l\004",
  299.     score, lines, level );
  300. #endif
  301.   if( nextfl )
  302.     for( int i=0; i<4; i++ )
  303.     {
  304.       goto_xy( figs[nextfig][!nextfig][i].x*2-!nextfig+5-(nextfig==1),
  305.                figs[nextfig][!nextfig][i].y+7 );
  306.       txtf( "|%c  ", nextfig+'2' );
  307.     }
  308. }
  309.  
  310. inline void Ttetris::plot(int x,int y,char c)
  311. {
  312.   chasha[y+4][(x<<2)+1]=c+'0';
  313. }
  314.  
  315. inline char Ttetris::getpix(int x,int y)
  316. {
  317.   return chasha[y+4][(x<<2)+1]-'0';
  318. }
  319.  
  320. void Ttetris::drawfig(int x,int y,int f,int rot)
  321. {
  322.   int i;
  323.  
  324.   for (i=0;i<4;i++)
  325.     plot(figs[f][rot][i].x+x,figs[f][rot][i].y+y,f+2);
  326. }
  327.  
  328. void Ttetris::clrfig(int x,int y,int f,int rot)
  329. {
  330.   int i;
  331.  
  332.   for (i=0;i<4;i++)
  333.   {
  334.     int xx = figs[f][rot][i].x+x;
  335.     plot(xx,figs[f][rot][i].y+y,xx%2);
  336.   }
  337. }
  338.  
  339. boolean Ttetris::testfig(int x,int y,int f,int rot)
  340. {
  341.   int i,xx,yy;
  342.  
  343.   for (i=0;i<4;i++) {
  344.     xx=x+figs[f][rot][i].x;
  345.     if (xx<0 || xx>=CHX) return 0;
  346.     yy=y+figs[f][rot][i].y;
  347.     if (yy<-4 || yy>=CHY) return 0;
  348.     if (getpix(xx,yy)>1) return 0;
  349.   }
  350.   return 1;
  351. }
  352.  
  353. boolean Ttetris::movefig(int x,int y,int rot)
  354. {
  355.   clrfig(curx,cury,curfig,currot);
  356.   if (testfig(x,y,curfig,rot)) {
  357.     curx=x;
  358.     cury=y;
  359.     currot=rot;
  360.     drawfig(x,y,curfig,rot);
  361.     return 1;
  362.   }
  363.   drawfig(curx,cury,curfig,currot);
  364.   return 0;
  365. }
  366.  
  367. void Ttetris::newfig( void )
  368. {
  369.   int x,y,y1;
  370.  
  371.   curfig=nextfig;
  372.   nextfig=rand()%7;
  373.   score+=points;
  374.   points=level*5+20;
  375.   for (y=CHY-1;y>=0;y--) {
  376.     for (x=0;x<CHX;x++)
  377.       if (getpix(x,y)<=1) goto nodel;
  378.     for (y1=y+3;y1>0;y1--)
  379.       memcpy(chasha[y1+1],chasha[y1],sizeof(chasha[y1]));
  380.     for (x=0;x<CHX;x++)
  381.       plot(x,y1,x%2);
  382.     lines++;
  383.     y++;
  384.   nodel:
  385.     continue;
  386.   }
  387.   if (level<MAX_LEVEL)
  388.     while (lines/10>level) nextlev();
  389.   currot=0;
  390.   curx=5;
  391.   cury=-3;
  392.   if (!testfig(curx,cury,curfig,currot)) gameover=1;
  393. }
  394.  
  395. void Ttetris::get_focused( void )
  396. {
  397.   time_speed=speed;
  398.   cenable( cmNEXT ); cenable( cmSTART ); cenable( cmLEVEL );
  399. }
  400.  
  401. boolean Ttetris::release_focus( void )
  402. {
  403.   if( !Titem::release_focus() ) return 0;
  404.   cdisable( cmNEXT ); cdisable( cmSTART ); cdisable( cmLEVEL );
  405.   return 1;
  406. }
  407.  
  408. inline boolean Ttetris::rotate( void )
  409. {
  410.   boolean f=movefig(curx,cury,(currot-1)&3);
  411.   points-=f;
  412.   return f;
  413. }
  414.  
  415. inline boolean Ttetris::left( void )
  416. {
  417.   return movefig(curx-1,cury,currot);
  418. }
  419.  
  420. inline boolean Ttetris::right( void )
  421. {
  422.   return movefig(curx+1,cury,currot);
  423. }
  424.  
  425. inline void Ttetris::drop_down( void )
  426. {
  427.   while (movefig(curx,cury+1,currot));
  428. }
  429.  
  430. void Ttetris::event_handler(Tevent &ev)
  431. {
  432.   Titem::event_handler( ev );
  433.   switch( ev.code )
  434.   {
  435.     case evKEY_PRESS:
  436.       if( !state( isFOCUSED ) ) return;
  437.       if( ev.ASCII==kTAB || ev.ASCII==kSHIFT_TAB) break;
  438.       if( gameover || !state( isFOCUSED ) ) return;
  439.       switch(ev.ASCII)
  440.       {
  441.         case kHOME     :
  442.         case kLEFT     : left(); break;
  443.         case kPG_UP    :
  444.         case kRIGHT    : right(); break;
  445.         case kUP       : rotate(); break;
  446.         case ' '       :
  447.         case kDOWN     : drop_down(); break;
  448.         default        : return;
  449.       }
  450.       break;
  451. #ifndef NOMOUSE
  452.     case evMOUSE_DOWN:
  453.       if( gameover || !ev.INSIDE ) return;
  454.       if( ev.BUTTON )
  455.         rotate();
  456.       else
  457.       {
  458.         int mx=ev.LOCAL_X/2;
  459.         while( curx>mx && left() );
  460.         while( curx<mx && right() );
  461.         if( ev.CLICKS%2 ) drop_down();
  462.       }
  463.       break;
  464. #endif
  465.     case evCOMMAND:
  466.       switch( ev.CMD_CODE )
  467.       {
  468.         case cmTETRIS_TIMER:
  469.           if( !state(isFOCUSED) || gameover ) return;
  470.           if( owner->state(isICONIZED) ) break;
  471.           if (!movefig(curx,cury+1,currot)) newfig();
  472.           points--;
  473.           points-=nextfl;
  474.           break;
  475.         case cmSTART:
  476.           newgame();
  477.           break;
  478.         case cmNEXT:
  479.           nextfl=!nextfl;
  480.           break;
  481.         case cmLEVEL:
  482.           nextlev();
  483.           break;
  484.         default:
  485.           return;
  486.       }
  487.       break;
  488.     default:
  489.       return;
  490.   }
  491.   redraw();
  492.   handled( ev );
  493. }
  494.  
  495. void tetris( void )
  496. {
  497.   _context( cxTETRIS ); NEW( Ttetris() );
  498. }
  499.  
  500. void __init_tetris( void )
  501. {
  502. #ifndef NOCONFIG
  503.   seek_section( 0, SECTION_TETRIS );
  504.   ini( VAR_LEVEL, ini_level, 7 );
  505.   ini( VAR_NEXT, ini_nextfl, 1 );
  506. #endif
  507. }
  508.