# include # include # include # include # include "ddutil.h" # include "dsutil.h" # include "resource.h" const int ultris_nettobreite = 360; // Breite des Inneren des Haupfensters const int ultris_nettohoehe = 520; // Hoehe des Inneren des Hauptfensters int ultris_bruttobreite; // Breite des gesamten Haupfensters (incl. Rahmen) int ultris_bruttohoehe; // Hoehe des gesamten Haupfensters (incl. Rahmen) HINSTANCE ultris_instance; // Instanz der Ultris Applikation HWND ultris_window; // Das Hauptfenster von Ultris HMENU ultris_menu; // Das Menu von Ultris const int sound_start = 0; // Sound fuer neues Spiel const int sound_dreh = 1; // Sound bei Drehung const int sound_move = 2; // Sound bei rechts/links Bewegung const int sound_down = 3; // Sound bei Aufprall const int sound_row1 = 4; // Sound bei Abraeumen einer Reihe const int sound_row2 = 5; // Sound bei Abraeumen von mehreren Reihen const int sound_ende = 6; // Sound bei Spielende const int sound_win = 7; // Sound bei Eintrag in Highscore Tabelle const int anzahl_sounds = 8; // Anzahl Sounds char *soundfiles[anzahl_sounds] = { "ul_start.wav", "ul_dreh.wav", "ul_move.wav", "ul_down.wav", "ul_row1.wav", "ul_row2.wav", "ul_ende.wav", "ul_win.wav" }; class sounds { private: CSoundManager smgr; CSound *snd[anzahl_sounds]; public: int on; sounds(); int init( HWND wnd); void play( int snr); ~sounds(); }; sounds::sounds() { int i; for( i = 0; i < anzahl_sounds; i++) snd[i] = 0; on = 1; } int sounds::init( HWND wnd) { HRESULT ret; int i; ret = smgr.Initialize( wnd, DSSCL_PRIORITY, 2, 22050, 16); if( ret < 0) return ret; for( i = 0; i < anzahl_sounds; i++) { ret = smgr.Create( snd+i, soundfiles[i]); if( ret < 0) return ret; } return S_OK; } sounds::~sounds() { int i; for( i = 0; i < anzahl_sounds; i++) { if( snd[i]) delete snd[i]; } } void sounds::play( int i) { if( !on) return; if( snd[i]->IsSoundPlaying()) { snd[i]->Stop(); snd[i]->Reset(); } snd[i]->Play(0,0); } sounds ultris_sounds; class display { private: CDisplay dsply; CSurface *hgrnd; CSurface *fldst; CSurface *fllst; CSurface *prvst; CSurface *deckel; CSurface *ziff[10]; public: display(); void free_all(); ~display() {free_all();} HRESULT init( HWND wnd); void hintergrund() { dsply.Blt( 0, 0, hgrnd);} void abdeckung() { dsply.Blt( 60, 0, deckel);} void ziffer( int pos, int val) { dsply.Blt( 120+pos*20, 50, ziff[val]);} void feldstein( int z, int s) { dsply.Blt( 80+s*20, 100+z*20, fldst);} void fallstein( int z, int s, int offset) { dsply.Blt( 80+s*20, 100+z*20+offset, fllst);} void prevstein( int p, int z, int s, int b, int h){ dsply.Blt( 290+s*15+(4-b)*15/2, 410-p*70+z*15+(4-h)*15/2, prvst);} void update(){ dsply.UpdateBounds();} HRESULT cooperative(){return dsply.GetDirectDraw()->TestCooperativeLevel();} HRESULT restore(); HRESULT present(); }; display::display() { int i; hgrnd = 0; fldst = 0; fllst = 0; prvst = 0; deckel = 0; for( i = 0; i < 10; i++) ziff[i] = 0; } void display::free_all() { int i; if( hgrnd) delete hgrnd; if( fldst) delete fldst; if( fllst) delete fllst; if( prvst) delete prvst; if( deckel) delete deckel; for( i = 0; i < 10; i++) { if( ziff[i]) delete ziff[i]; } } HRESULT display::init( HWND wnd) { HRESULT hr; int i; char fname[20]; hr = dsply.CreateWindowedDisplay( wnd, ultris_nettobreite, ultris_nettohoehe ); if( hr < 0) return hr; hr = dsply.CreateSurfaceFromBitmap( &hgrnd, "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); if( hr < 0) return hr; hr = dsply.CreateSurfaceFromBitmap( &fldst, "ul_feld.bmp", 20, 20); if( hr < 0) return hr; hr = dsply.CreateSurfaceFromBitmap( &fllst, "ul_stein.bmp", 20, 20); if( hr < 0) return hr; hr = dsply.CreateSurfaceFromBitmap( &prvst, "ul_prev.bmp", 15, 15); if( hr < 0) return hr; hr = dsply.CreateSurfaceFromBitmap( &deckel, "ul_adeck.bmp", 240, 100); if( hr < 0) return hr; for( i = 0; i < 10; i++) { sprintf( fname, "ul_z%d.bmp", i); hr = dsply.CreateSurfaceFromBitmap( &ziff[i], fname, 20, 40); if( hr < 0) return hr; } return S_OK; } HRESULT display::restore() { HRESULT hr; int i; char fname[20]; hr = dsply.GetDirectDraw()->RestoreAllSurfaces(); if( hr < 0) return hr; hr = hgrnd->DrawBitmap( "ul_hgrnd.bmp", ultris_nettobreite, ultris_nettohoehe); if( hr < 0) return hr; hr = fldst->DrawBitmap( "ul_feld.bmp", 20, 20); if( hr < 0) return hr; hr = fllst->DrawBitmap( "ul_stein.bmp", 20, 20); if( hr < 0) return hr; hr = prvst->DrawBitmap( "ul_prev.bmp", 15, 15); if( hr < 0) return hr; hr = deckel->DrawBitmap( "ul_adeck.bmp", 240, 100); if( hr < 0) return hr; for( i = 0; i < 10; i++) { sprintf( fname, "ul_z%d.bmp", i); hr = ziff[i]->DrawBitmap( fname, 20, 40); if( hr < 0) return hr; } MessageBox( ultris_window, "Surfaces restauriert", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); return S_OK; } HRESULT display::present() { HRESULT hr; hr = dsply.Present(); if( hr == DDERR_SURFACELOST ) return restore(); return hr; } display ultris_display; const int anzahl_formen = 35; // Anzahl der Formen // // Datenstruktur für die Formen // struct form { char h; // Hoehe char b; // Breite char data[4][4]; // Vorhandene Segmente }; // Form 1 in allen Drehvarianten // // *** * * * // * ** *** ** // * * const form s_01_1 = {2, 3, {{1,1,1}, {0,1,0}}}; const form s_01_2 = {3, 2, {{1,0}, {1,1}, {1,0}}}; const form s_01_3 = {2, 3, {{0,1,0}, {1,1,1}}}; const form s_01_4 = {3, 2, {{0,1}, {1,1}, {0,1}}}; // Form 2 in allen Drehvarianten // // ** * ** * // ** ** ** ** // * * const form s_02_1 = {2, 3, {{1,1,0}, {0,1,1}}}; const form s_02_2 = {3, 2, {{0,1}, {1,1}, {1,0}}}; const form s_02_3 = {2, 3, {{1,1,0}, {0,1,1}}}; const form s_02_4 = {3, 2, {{0,1}, {1,1}, {1,0}}}; // Form 3 in allen Drehvarianten // // ** * ** * // ** ** ** ** // * * const form s_03_1 = {2, 3, {{0,1,1}, {1,1,0}}}; const form s_03_2 = {3, 2, {{1,0}, {1,1}, {0,1}}}; const form s_03_3 = {2, 3, {{0,1,1}, {1,1,0}}}; const form s_03_4 = {3, 2, {{1,0}, {1,1}, {0,1}}}; // Form 4 in allen Drehvarianten // // *** ** * * // * * *** * // * ** const form s_04_1 = {2, 3, {{1,1,1}, {0,0,1}}}; const form s_04_2 = {3, 2, {{1,1}, {1,0}, {1,0}}}; const form s_04_3 = {2, 3, {{1,0,0}, {1,1,1}}}; const form s_04_4 = {3, 2, {{0,1}, {0,1}, {1,1}}}; // Form 5 in allen Drehvarianten // // * ** *** * // *** * * * // * ** const form s_05_1 = {2, 3, {{0,0,1}, {1,1,1}}}; const form s_05_2 = {3, 2, {{1,1}, {0,1}, {0,1}}}; const form s_05_3 = {2, 3, {{1,1,1}, {1,0,0}}}; const form s_05_4 = {3, 2, {{1,0}, {1,0}, {1,1}}}; // Form 6 in allen Drehvarianten // // ** ** ** ** // ** ** ** ** // const form s_06_1 = {2, 2, {{1,1}, {1,1}}}; const form s_06_2 = {2, 2, {{1,1}, {1,1}}}; const form s_06_3 = {2, 2, {{1,1}, {1,1}}}; const form s_06_4 = {2, 2, {{1,1}, {1,1}}}; // Form 7 in allen Drehvarianten // // **** * **** * // * * // * * // * * const form s_07_1 = {1, 4, {{1,1,1,1}}}; const form s_07_2 = {4, 1, {{1},{1},{1},{1}}}; const form s_07_3 = {1, 4, {{1,1,1,1}}}; const form s_07_4 = {4, 1, {{1},{1},{1},{1}}}; // Form 8 in allen Drehvarianten // // *** ** * * ** // * * * *** * // ** ** const form s_08_1 = {2, 3, {{1,1,1}, {1,0,1}}}; const form s_08_2 = {3, 2, {{1,1},{1,0},{1,1}}}; const form s_08_3 = {2, 3, {{1,0,1}, {1,1,1}}}; const form s_08_4 = {3, 2, {{1,1},{0,1},{1,1}}}; // Form 9 in allen Drehvarianten // // ** * ** * // * *** * *** // ** * ** * const form s_09_1 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; const form s_09_2 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; const form s_09_3 = {3, 3, {{1,1,0}, {0,1,0}, {0,1,1}}}; const form s_09_4 = {3, 3, {{0,0,1}, {1,1,1}, {1,0,0}}}; // Form 10 in allen Drehvarianten // // ** ** * * // * * ** ** // const form s_10_1 = {2, 2, {{1,1}, {0,1}}}; const form s_10_2 = {2, 2, {{1,1}, {1,0}}}; const form s_10_3 = {2, 2, {{1,0}, {1,1}}}; const form s_10_4 = {2, 2, {{0,1}, {1,1}}}; // Form 11 in allen Drehvarianten // // * * * * // *** *** *** *** // * * * * const form s_11_1 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; const form s_11_2 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; const form s_11_3 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; const form s_11_4 = {3, 3, {{0,1,0}, {1,1,1}, {0,1,0}}}; // Form 12 in allen Drehvarianten // // ** ** * *** // ** *** ** ** // * ** const form s_12_1 = {3, 2, {{1,1}, {1,1}, {1,0}}}; const form s_12_2 = {2, 3, {{1,1,0}, {1,1,1}}}; const form s_12_3 = {3, 2, {{0,1}, {1,1}, {1,1}}}; const form s_12_4 = {2, 3, {{1,1,1}, {0,1,1}}}; // Form 13 in allen Drehvarianten // // ** *** * ** // ** ** ** *** // * ** const form s_13_1 = {3, 2, {{1,1}, {1,1}, {0,1}}}; const form s_13_2 = {2, 3, {{1,1,1}, {1,1,0}}}; const form s_13_3 = {3, 2, {{1,0}, {1,1}, {1,1}}}; const form s_13_4 = {2, 3, {{0,1,1}, {1,1,1}}}; // Form 14 in allen Drehvarianten // // *** * * *** // * * * * // * *** *** * const form s_14_1 = {3, 3, {{1,1,1}, {1,0,0}, {1,0,0}}}; const form s_14_2 = {3, 3, {{1,0,0}, {1,0,0}, {1,1,1}}}; const form s_14_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,1}}}; const form s_14_4 = {3, 3, {{1,1,1}, {0,0,1}, {0,0,1}}}; // Form 15 in allen Drehvarianten // // * * * * const form s_15_1 = {1, 1, {{1}}}; const form s_15_2 = {1, 1, {{1}}}; const form s_15_3 = {1, 1, {{1}}}; const form s_15_4 = {1, 1, {{1}}}; // Form 16 in allen Drehvarianten // // * * * * // * * * * const form s_16_1 = {2, 2, {{1,0}, {0,1}}}; const form s_16_2 = {2, 2, {{0,1}, {1,0}}}; const form s_16_3 = {2, 2, {{1,0}, {0,1}}}; const form s_16_4 = {2, 2, {{0,1}, {1,0}}}; // Form 17 in allen Drehvarianten // // * * * * // * * * * // * * * * const form s_17_1 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; const form s_17_2 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; const form s_17_3 = {3, 3, {{1,0,0}, {0,1,0}, {0,0,1}}}; const form s_17_4 = {3, 3, {{0,0,1}, {0,1,0}, {1,0,0}}}; // Form 18 in allen Drehvarianten // // * * * * // * * * * * * * * // * * * * const form s_18_1 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; const form s_18_2 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; const form s_18_3 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; const form s_18_4 = {3, 3, {{0,1,0}, {1,0,1}, {0,1,0}}}; // Form 19 in allen Drehvarianten // // * * * * * // * * * * * // * * const form s_19_1 = {2, 3, {{0,1,0}, {1,0,1}}}; const form s_19_2 = {3, 2, {{0,1},{1,0},{0,1}}}; const form s_19_3 = {2, 3, {{1,0,1}, {0,1,0}}}; const form s_19_4 = {3, 2, {{1,0},{0,1},{1,0}}}; // Form 20 in allen Drehvarianten // // *** * * * // * *** * *** // * * *** * const form s_20_1 = {3, 3, {{1,1,1}, {0,1,0}, {0,1,0}}}; const form s_20_2 = {3, 3, {{1,0,0}, {1,1,1}, {1,0,0}}}; const form s_20_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,1,1}}}; const form s_20_4 = {3, 3, {{0,0,1}, {1,1,1}, {0,0,1}}}; // Form 21 in allen Drehvarianten // // * * * * * // * ** * ** // * * * * * const form s_21_1 = {3, 3, {{1,0,1}, {0,1,0}, {0,1,0}}}; const form s_21_2 = {3, 3, {{1,0,0}, {0,1,1}, {1,0,0}}}; const form s_21_3 = {3, 3, {{0,1,0}, {0,1,0}, {1,0,1}}}; const form s_21_4 = {3, 3, {{0,0,1}, {1,1,0}, {0,0,1}}}; // Form 22 in allen Drehvarianten // // ** * ** * // * * // const form s_22_1 = {1, 2, {{1,1}}}; const form s_22_2 = {2, 1, {{1},{1}}}; const form s_22_3 = {1, 2, {{1,1}}}; const form s_22_4 = {2, 1, {{1},{1}}}; // Form 23 in allen Drehvarianten // // *** * *** * // * * // * * const form s_23_1 = {1, 3, {{1,1,1}}}; const form s_23_2 = {3, 1, {{1},{1},{1}}}; const form s_23_3 = {1, 3, {{1,1,1}}}; const form s_23_4 = {3, 1, {{1},{1},{1}}}; // Form 24 in allen Drehvarianten // // ** * * * // * * ** * // * * const form s_24_1 = {2, 3, {{1,1,0}, {0,0,1}}}; const form s_24_2 = {3, 2, {{0,1}, {1,0}, {1,0}}}; const form s_24_3 = {2, 3, {{1,0,0}, {0,1,1}}}; const form s_24_4 = {3, 2, {{0,1}, {0,1}, {1,0}}}; // Form 25 in allen Drehvarianten // // * * ** * // ** * * * // * * const form s_25_1 = {2, 3, {{0,0,1}, {1,1,0}}}; const form s_25_2 = {3, 2, {{1,0}, {0,1}, {0,1}}}; const form s_25_3 = {2, 3, {{0,1,1}, {1,0,0}}}; const form s_25_4 = {3, 2, {{1,0}, {1,0}, {0,1}}}; // Form 26 in allen Drehvarianten // // ** * ** * // ** * ** * // * * // * * const form s_26_1 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; const form s_26_2 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; const form s_26_3 = {2, 4, {{0,0,1,1}, {1,1,0,0}}}; const form s_26_4 = {4, 2, {{1,0},{1,0},{0,1}, {0,1}}}; // Form 27 in allen Drehvarianten // // ** * ** * // ** * ** * // * * // * * const form s_27_1 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; const form s_27_2 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; const form s_27_3 = {2, 4, {{1,1,0,0},{0,0,1,1}}}; const form s_27_4 = {4, 2, {{0,1},{0,1},{1,0},{1,0}}}; // Form 28 in allen Drehvarianten // // * * * ** * // ** * * * * // * * // * * const form s_28_1 = {2, 4, {{1,0,0,1},{0,1,1,0}}}; const form s_28_2 = {4, 2, {{1,0},{0,1},{0,1},{1,0}}}; const form s_28_3 = {2, 4, {{0,1,1,0},{1,0,0,1}}}; const form s_28_4 = {4, 2, {{0,1},{1,0},{1,0},{0,1}}}; // Form 29 in allen Drehvarianten // // ** * * ** // * * * * // * ** ** * const form s_29_1 = {3, 3, {{0,1,1}, {1,0,0}, {1,0,0}}}; const form s_29_2 = {3, 3, {{1,0,0}, {1,0,0}, {0,1,1}}}; const form s_29_3 = {3, 3, {{0,0,1}, {0,0,1}, {1,1,0}}}; const form s_29_4 = {3, 3, {{1,1,0}, {0,0,1}, {0,0,1}}}; // Form 30 in allen Drehvarianten // // * ** * * ** // * * * * * * // * * ** * ** const form s_30_1 = {3, 3, {{0,1,0}, {1,0,1}, {1,0,1}}}; const form s_30_2 = {3, 3, {{0,1,1}, {1,0,0}, {0,1,1}}}; const form s_30_3 = {3, 3, {{1,0,1}, {1,0,1}, {0,1,0}}}; const form s_30_4 = {3, 3, {{1,1,0}, {0,0,1}, {1,1,0}}}; // Form 31 in allen Drehvarianten // // *** * * * // * * *** * // * * // * * const form s_31_1 = {2, 4, {{1,1,1,0},{0,0,0,1}}}; const form s_31_2 = {4, 2, {{0,1},{1,0},{1,0},{1,0}}}; const form s_31_3 = {2, 4, {{1,0,0,0},{0,1,1,1}}}; const form s_31_4 = {4, 2, {{0,1},{0,1},{0,1},{1,0}}}; // Form 32 in allen Drehvarianten // // * * *** * // *** * * * // * * // * * const form s_32_1 = {2, 4, {{0,0,0,1},{1,1,1,0}}}; const form s_32_2 = {4, 2, {{1,0},{0,1},{0,1},{0,1}}}; const form s_32_3 = {2, 4, {{0,1,1,1},{1,0,0,0}}}; const form s_32_4 = {4, 2, {{1,0},{1,0},{1,0},{0,1}}}; // Form 33 in allen Drehvarianten // // ** *** ** *** // ** *** ** *** // ** ** const form s_33_1 = {3, 2, {{1,1}, {1,1}, {1,1}}}; const form s_33_2 = {2, 3, {{1,1,1}, {1,1,1}}}; const form s_33_3 = {3, 2, {{1,1}, {1,1}, {1,1}}}; const form s_33_4 = {2, 3, {{1,1,1}, {1,1,1}}}; // Form 34 in allen Drehvarianten // // **** * ** * // ** ** **** ** // ** ** // * * const form s_34_1 = {2, 4, {{1,1,1,1},{0,1,1,0}}}; const form s_34_2 = {4, 2, {{1,0},{1,1},{1,1},{1,0}}}; const form s_34_3 = {2, 4, {{0,1,1,0},{1,1,1,1}}}; const form s_34_4 = {4, 2, {{0,1},{1,1},{1,1},{0,1}}}; // Form 35 in allen Drehvarianten // // ** * ** * // * *** * *** // ** * ** * const form s_35_1 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; const form s_35_2 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; const form s_35_3 = {3, 3, {{0,1,1}, {0,1,0}, {1,1,0}}}; const form s_35_4 = {3, 3, {{1,0,0}, {1,1,1}, {0,0,1}}}; // Array mit allen Steinformen in allen Drehvarianten // Zugriff in der Form // // ultris_form[ steinform][ drehvariante] // // mit 0 <= steinform < 35 und 0 <= drehvariante <= 4 const form *ultris_form[anzahl_formen][4] = { { &s_01_1, &s_01_2, &s_01_3, &s_01_4}, { &s_02_1, &s_02_2, &s_02_3, &s_02_4}, { &s_03_1, &s_03_2, &s_03_3, &s_03_4}, { &s_04_1, &s_04_2, &s_04_3, &s_04_4}, { &s_05_1, &s_05_2, &s_05_3, &s_05_4}, { &s_06_1, &s_06_2, &s_06_3, &s_06_4}, { &s_07_1, &s_07_2, &s_07_3, &s_07_4}, { &s_08_1, &s_08_2, &s_08_3, &s_08_4}, { &s_09_1, &s_09_2, &s_09_3, &s_09_4}, { &s_10_1, &s_10_2, &s_10_3, &s_10_4}, { &s_11_1, &s_11_2, &s_11_3, &s_11_4}, { &s_12_1, &s_12_2, &s_12_3, &s_12_4}, { &s_13_1, &s_13_2, &s_13_3, &s_13_4}, { &s_14_1, &s_14_2, &s_14_3, &s_14_4}, { &s_15_1, &s_15_2, &s_15_3, &s_15_4}, { &s_16_1, &s_16_2, &s_16_3, &s_16_4}, { &s_17_1, &s_17_2, &s_17_3, &s_17_4}, { &s_18_1, &s_18_2, &s_18_3, &s_18_4}, { &s_19_1, &s_19_2, &s_19_3, &s_19_4}, { &s_20_1, &s_20_2, &s_20_3, &s_20_4}, { &s_21_1, &s_21_2, &s_21_3, &s_21_4}, { &s_22_1, &s_22_2, &s_22_3, &s_22_4}, { &s_23_1, &s_23_2, &s_23_3, &s_23_4}, { &s_24_1, &s_24_2, &s_24_3, &s_24_4}, { &s_25_1, &s_25_2, &s_25_3, &s_25_4}, { &s_26_1, &s_26_2, &s_26_3, &s_26_4}, { &s_27_1, &s_27_2, &s_27_3, &s_27_4}, { &s_28_1, &s_28_2, &s_28_3, &s_28_4}, { &s_29_1, &s_29_2, &s_29_3, &s_29_4}, { &s_30_1, &s_30_2, &s_30_3, &s_30_4}, { &s_31_1, &s_31_2, &s_31_3, &s_31_4}, { &s_32_1, &s_32_2, &s_32_3, &s_32_4}, { &s_33_1, &s_33_2, &s_33_3, &s_33_4}, { &s_34_1, &s_34_2, &s_34_3, &s_34_4}, { &s_35_1, &s_35_2, &s_35_3, &s_35_4} }; // Array mit den aktuell im Spiel aktivierten Steinformen // Zu Programmstart sind dies die ueblichen Tetris Spielsteine (0-6) char aktive_formen[anzahl_formen] = { 1,1,1,1,1,1,1, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0, 0,0,0,0,0,0,0 }; // Anzahl der aktuell aktivierten Steinformen int anz_aktive_formen = 7; // Punktwerte aller Steinformen const int formwert[anzahl_formen] = { 8,12,12,10,10,10, 6, 25,25, 4,20,10,10,20, 1, 8,25,40,15,25,35, 2, 4,10,10,20,20,25, 25,30,25,25,10,15,25 }; class ultris { struct formwahl { int ix; // Index der Form int dv; // Drehvariante der Form }; private: int vorbelegung; // Anzahl der bei Spielbeginn vorzubelegenden Zeilen int vorschau; // Anzahl der Formen in der Vorschau int spielfeld[20][10]; // Das Spielfeld int fuellstand[20]; // Der Fuellstand einer Reihe (= Anzahl Segmente in der Reihe) int punktestand; // Der aktuelle Punktestand formwahl formen[6]; // 0 aktuelle Form, 1-5 Vorschau int zeile; // Zeile der aktuellen Form int spalte; // Spalte der aktuellen Form int offset; // Offset zur Zeile int sichtbar; // Form war bereits sichtbar int zeige_dyn; // Zeige den dynamischen Anteil DWORD time; // Zeitreferenz int speed; // Geschwindigkeit void initialisieren(); void vorbelegen(); void display_spielfeld(); void display_punktestand(); void display_vorschau(); void display_form(); void naechste_form(); void neue_form(); const form *aktuelle_form() {return ultris_form[formen[0].ix][formen[0].dv];} int onestep(); // Stein um ein Pixel nach unten bewegen int blockiert(); public: int spiel_laeuft; // Indikator, dass das Spiel laeuft ultris(){ srand( GetTickCount()); initialisieren(); vorbelegung = 0; vorschau = 1;} int get_vorbelegung() { return vorbelegung;} void set_vorbelegung( int v) {if( v < 0) v = 0; if( v > 20) v = 20; vorbelegung = v;} int get_vorschau() { return vorschau;} void set_vorschau( int v) {if( v < 0) v = 0; if(v > 5) v = 5; vorschau = v;} void start(); void display(); int step(); void down(); void reset_timer(){time = timeGetTime();} void schneller() { speed += 50;} void langsamer() { if( speed > 50) speed -= 50;} void bewegen( int dir); // -1 eins nach links +1 eins nach rechts void drehen(int dir); // -1 eins nach links +1 eins nach rechts }; void ultris::initialisieren() { int z, s; for( z = 0; z < 20; z++) { fuellstand[z] = 0; for( s = 0; s < 10; s++) spielfeld[z][s] = 0; } spiel_laeuft = 0; zeige_dyn = 0; punktestand = 0; } void ultris::vorbelegen() { int z, s, i; for( i = 0; i < vorbelegung*5; i++) { z = 19-rand()%vorbelegung; s = rand()%10; if( !spielfeld[z][s]) { spielfeld[z][s] = 1; fuellstand[z]++; } } punktestand = vorbelegung * 2500; } void ultris::start() { ultris_sounds.play( sound_start); initialisieren(); vorbelegen(); spiel_laeuft = 1; naechste_form(); naechste_form(); naechste_form(); naechste_form(); naechste_form(); neue_form(); zeige_dyn = 1; reset_timer(); speed = 100; } void ultris::display_spielfeld() { int z, s; for( z = 0; z < 20; z++) { for( s = 0; s < 10; s++) { if( spielfeld[z][s]) ultris_display.feldstein( z, s); } } } void ultris::display_punktestand() { int i, z, p; for( i = 5, p = punktestand; i >= 0; i--, p/= 10) { z = p % 10; ultris_display.ziffer( i, z); } } void ultris::display() { ultris_display.hintergrund(); display_spielfeld(); if( zeige_dyn) { display_vorschau(); display_form(); } ultris_display.abdeckung(); display_punktestand(); ultris_display.present(); } void ultris::naechste_form() { int z, i, ix; for( i = 0; i < 5; i++) formen[i] = formen[i+1]; z = rand()%anz_aktive_formen+1; for( ix = -1; z; z--) { while( !aktive_formen[++ix]) ; } formen[5].ix = ix; formen[5].dv = rand()%4; } void ultris::neue_form() { naechste_form(); zeile = -aktuelle_form()->h; spalte = 5-(aktuelle_form()->b)/2; offset = 0; sichtbar = 0; punktestand += formwert[formen[0].ix]; } void ultris::display_vorschau() { int z, s, p, y; const form *f; if( !sichtbar) sichtbar = (zeile >= 0); for( y = 0, p = sichtbar; y < vorschau; p++, y++) { f = ultris_form[formen[p].ix][formen[p].dv]; for( z = 0; z < f->h; z++) { for( s = 0; s < f->b; s++) { if( f->data[z][s]) ultris_display.prevstein(y, z, s, f->b, f->h); } } } } void ultris::display_form() { int z, s; for( z = 0; z < aktuelle_form()->h; z++) { for( s = 0; s < aktuelle_form()->b; s++) { if( aktuelle_form()->data[z][s]) { ultris_display.fallstein( zeile+z, spalte+s, offset); } } } } void ultris::down() { while( onestep()) ; } int ultris::step() { DWORD now; int pixel; int diff; now = timeGetTime(); diff = (now-time)*speed; pixel = diff/5000; if( !pixel) return 0; time = now - diff%5000/speed; for( ; pixel && onestep(); pixel--) ; return 1; } int ultris::blockiert() { int z, s, zz; for( z = 0; z < aktuelle_form()->h; z++) { for( s = 0; s < aktuelle_form()->b; s++) { if( aktuelle_form()->data[z][s]) { zz = zeile + z + 1; if( (zz >= 20) || ((zz >= 0) &&(spielfeld[zz][spalte+s]))) return 1; } } } return 0; } int ultris::onestep() { if( offset) { if( offset < 20) offset++; else { offset = 0; zeile++; } return 1; } else { if( blockiert()) { ultris_sounds.play( sound_down); // vorlaeufig neue_form(); // vorlaeufig return 0; } offset++; return 1; } } // V10 Beginn void ultris::bewegen( int dir) // -1 eins nach links +1 eins nach rechts { int z, s, neue_spalte; const form *f; f = aktuelle_form(); neue_spalte = spalte + dir; if( neue_spalte < 0) return; if( neue_spalte + f->b > 10) return; for( z = 0; z < f->h; z++) { if( zeile+z < 0) continue; for( s = 0; s < f->b; s++) { if( f->data[z][s]) { if( (offset < 16) && spielfeld[zeile+z][neue_spalte+s]) return; if( (offset > 0) && spielfeld[zeile+z+1][neue_spalte+s]) return; } } } spalte = neue_spalte; ultris_sounds.play( sound_move); } void ultris::drehen(int dir) { int sv, sp, zl; int b1, b2, h1, h2, db, dh; int maxb, maxh, minz, mins; int i, j; sv = (formen[0].dv + 4 - dir)%4; b1 = aktuelle_form()->b; b2 = ultris_form[formen[0].ix][sv]->b; h1 = aktuelle_form()->h; h2 = ultris_form[formen[0].ix][sv]->h; db = (b1-b2)/2; dh = (h1-h2)/2; sp = spalte+db; zl = zeile+dh; if( sp < 0) sp = 0; if( sp+b2 >= 10) sp = 10-b2; if( zl+h2 >= 20) return; mins = spalte < sp ? spalte : sp; minz = zeile < zl ? zeile : zl; maxb = b1 > b2 ? b1 : b2; maxh = h1 > h2 ? h1 : h2; if( offset) maxh++; for( i = minz; i < minz+maxh; i++) { for( j = mins; j < mins+maxb; j++) { if( (i>=0)&&(i<20)&&(j>=0)&&(j<10)&&spielfeld[i][j]) return; } } formen[0].dv = sv; spalte = sp; zeile = zl; ultris_sounds.play( sound_dreh); } // V10 Ende ultris mein_spiel; BOOL CALLBACK hilfedialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_COMMAND: if((wParam == IDOK)||(wParam == IDCANCEL)) { EndDialog(hwndDlg, wParam); return TRUE; } } return FALSE; } BOOL CALLBACK ultrisdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch (uMsg) { case WM_COMMAND: if( wParam == IDC_WEITERE_INFO) { ShellExecute(NULL, "open", "http://www-et.bocholt.fh-gelsenkirchen.de", NULL, NULL, SW_SHOWNORMAL); return TRUE; } if((wParam == IDOK)||(wParam == IDCANCEL)) { EndDialog(hwndDlg, wParam); return TRUE; } } return FALSE; } BOOL CALLBACK konfigurationsdialog( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { int i; switch (uMsg) { case WM_INITDIALOG: for( i = 0; i < anzahl_formen; i++) CheckDlgButton( hwndDlg, 5000+i, aktive_formen[i] ? BST_CHECKED : BST_UNCHECKED); SetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, mein_spiel.get_vorbelegung(), FALSE); SetDlgItemInt( hwndDlg, IDC_VORSCHAU, mein_spiel.get_vorschau(), FALSE); return TRUE; case WM_COMMAND: if(wParam == IDOK) { for( i = 0, anz_aktive_formen = 0; i < anzahl_formen; i++) { aktive_formen[i] = 0; if(IsDlgButtonChecked( hwndDlg, 5000+i) == BST_CHECKED) { aktive_formen[i] = 1; anz_aktive_formen++; } } if( anz_aktive_formen == 0) { aktive_formen[0] = 1; anz_aktive_formen = 1; } mein_spiel.set_vorbelegung( GetDlgItemInt( hwndDlg, IDC_VORBELEGUNG, NULL, FALSE)); mein_spiel.set_vorschau( GetDlgItemInt( hwndDlg, IDC_VORSCHAU, NULL, FALSE)); EndDialog(hwndDlg, wParam); return TRUE; } if(wParam == IDCANCEL) { EndDialog(hwndDlg, wParam); return TRUE; } if (HIWORD(wParam) == BN_CLICKED) { switch( LOWORD(wParam)) { case IDC_LOESCHEN: for( i = 0; i < anzahl_formen; i++) CheckDlgButton( hwndDlg, 5000+i, BST_UNCHECKED); return TRUE; case IDC_ALLE: for( i = 0; i < anzahl_formen; i++) CheckDlgButton( hwndDlg, 5000+i, BST_CHECKED); return TRUE; case IDC_STANDARD: for( i = 0; i < anzahl_formen; i++) CheckDlgButton( hwndDlg, 5000+i, i < 7 ? BST_CHECKED:BST_UNCHECKED); return TRUE; } } } return FALSE; } /* ** ultris_windowhandler */ LRESULT CALLBACK ultris_windowhandler( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { switch(msg) { case WM_COMMAND: switch( LOWORD( wParam)) { case IDM_EXIT: PostMessage( hWnd, WM_CLOSE, 0, 0); return 0; case ID_ULTRIS_SOUND: ultris_sounds.on = !ultris_sounds.on; CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); return 0; case ID_INFO_HILFE: DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_HILFE), ultris_window, hilfedialog); mein_spiel.reset_timer(); return 0; case ID_INFO_ULTRIS: DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_ULTRIS), ultris_window, ultrisdialog); mein_spiel.reset_timer(); return 0; case ID_EINSTELLUNGEN_KONFIGURATION: DialogBox( ultris_instance, MAKEINTRESOURCE( IDD_KONFIGURATION), ultris_window, konfigurationsdialog); mein_spiel.reset_timer(); return 0; case ID_ULTRIS_NEUESSPIEL: mein_spiel.start(); CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, MF_UNCHECKED); PostMessage( ultris_window, WM_PAINT, 0, 0); break; case ID_ULTRIS_PAUSE: mein_spiel.spiel_laeuft = !mein_spiel.spiel_laeuft; CheckMenuItem( ultris_menu, ID_ULTRIS_PAUSE, mein_spiel.spiel_laeuft ? MF_UNCHECKED:MF_CHECKED); return 0; case IDM_DOWN: if( mein_spiel.spiel_laeuft) mein_spiel.down(); return 0; case IDM_SCHNELLER: mein_spiel.schneller(); return 0; case IDM_LANGSAMER: mein_spiel.langsamer(); return 0; // V10 Beginn case IDM_DREHRECHTS: mein_spiel.drehen(1); return 0; case IDM_DREHLINKS: mein_spiel.drehen(-1); return 0; case IDM_RECHTS: mein_spiel.bewegen(1); return 0; case IDM_LINKS: mein_spiel.bewegen(-1); return 0; // V10 Ende case IDM_TEST: // Testcode return 0; } break; case WM_GETMINMAXINFO: ((MINMAXINFO *)lParam)->ptMinTrackSize.x = ((MINMAXINFO *)lParam)->ptMaxTrackSize.x = ultris_bruttobreite; ((MINMAXINFO *)lParam)->ptMinTrackSize.y = ((MINMAXINFO *)lParam)->ptMaxTrackSize.y = ultris_bruttohoehe; return 0; case WM_DESTROY: PostQuitMessage( 0); return 0; case WM_MOVE: ultris_display.update(); return 0; case WM_EXITMENULOOP: case WM_EXITSIZEMOVE: mein_spiel.reset_timer(); break; case WM_PAINT: mein_spiel.display(); break; } return DefWindowProc(hWnd, msg, wParam, lParam); } /* ** WinMain */ int APIENTRY WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR pCmdLine, int nCmdShow) { MSG msg; HACCEL acc; WNDCLASSEX wcx; ultris_instance = hInst; wcx.cbSize = sizeof( wcx); wcx.lpszClassName = TEXT( "Ultris"); wcx.lpfnWndProc = ultris_windowhandler; wcx.style = CS_VREDRAW | CS_HREDRAW; wcx.hInstance = hInst; wcx.hIcon = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); wcx.hIconSm = LoadIcon( hInst, MAKEINTRESOURCE( IDI_MAIN)); wcx.hCursor = LoadCursor( NULL, IDC_ARROW); wcx.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcx.lpszMenuName = MAKEINTRESOURCE( IDR_MENU); wcx.cbClsExtra = 0; wcx.cbWndExtra = 0; if( !RegisterClassEx( &wcx)) return 0; acc = LoadAccelerators( hInst, MAKEINTRESOURCE(IDR_ACCEL)); ultris_bruttohoehe = ultris_nettohoehe + 2*GetSystemMetrics( SM_CYSIZEFRAME) + GetSystemMetrics( SM_CYMENU) + GetSystemMetrics( SM_CYCAPTION); ultris_bruttobreite = ultris_nettobreite + 2*GetSystemMetrics( SM_CXSIZEFRAME); ultris_window = CreateWindowEx( 0, TEXT( "Ultris"), TEXT( "Ultris"), WS_OVERLAPPEDWINDOW & ~WS_MAXIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, ultris_bruttobreite, ultris_bruttohoehe, NULL, NULL, hInst, NULL); if( !ultris_window) return 0; ultris_menu = GetMenu( ultris_window); if( ultris_sounds.init( ultris_window) < 0) { MessageBox( ultris_window, "Fehler beim Initialisieren der Sounds", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); return 0; } CheckMenuItem( ultris_menu, ID_ULTRIS_SOUND, ultris_sounds.on ? MF_CHECKED:MF_UNCHECKED); if( ultris_display.init( ultris_window) < 0) { MessageBox( ultris_window, "Fehler beim Initialisieren der Grafik", "Ultris-Fehlermeldung", MB_OK | MB_ICONERROR | MB_SETFOREGROUND); return 0; } MoveWindow( ultris_window, (GetSystemMetrics(SM_CXSCREEN)-ultris_bruttobreite)/2, (GetSystemMetrics(SM_CYSCREEN)-ultris_bruttohoehe)/2, ultris_bruttobreite, ultris_bruttohoehe, TRUE); ShowWindow( ultris_window, nCmdShow); while( TRUE) { if( PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE)) { if( GetMessage( &msg, NULL, 0, 0 ) == 0) return 0; // Message ist WM_QUIT if( TranslateAccelerator( ultris_window, acc, &msg) == 0) { TranslateMessage( &msg); DispatchMessage( &msg); } } else { HRESULT hr; hr = ultris_display.cooperative(); if( hr < 0) { switch( hr ) { case DDERR_EXCLUSIVEMODEALREADYSET: Sleep(10); break; case DDERR_WRONGMODE: ultris_display.free_all(); ultris_display.init( ultris_window); PostMessage( ultris_window, WM_PAINT, 0, 0); break; } } else { if( mein_spiel.spiel_laeuft) { if( mein_spiel.step()) mein_spiel.display(); } else { WaitMessage(); mein_spiel.reset_timer(); // Spieluhr laeuft nicht } } } } }