You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1403 lines
35 KiB
C++

# include <stdio.h>
# include <windows.h>
# include <ddraw.h>
# include <dsound.h>
# 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();
void aufloesen();
void aufruecken();
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())
{
// V11 Beginn
aufloesen();
aufruecken();
spiel_laeuft = (zeile >= 0);
if( spiel_laeuft)
neue_form();
else
{
zeige_dyn = 0;
display();
ultris_sounds.play( sound_ende);
}
return 0;
// V11 Ende
}
offset++;
return 1;
}
}
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);
}
// V11 Beginn
void ultris::aufloesen()
{
int z, s;
int zz, ss;
for( z = 0; z < aktuelle_form()->h; z++)
{
zz = zeile+z;
if((zz >=0) && (zz<20))
{
for( s = 0; s < aktuelle_form()->b; s++)
{
ss = spalte + s;
if( aktuelle_form()->data[z][s] && (ss>=0) && (ss<10))
{
spielfeld[zz][ss] = 1;
fuellstand[zz]++;
}
}
}
}
}
void ultris::aufruecken()
{
int zz, z, s;
int a;
for( z = 19, a = 0; z >= 0; )
{
if( fuellstand[z] == 10)
{
a++;
punktestand += speed;
speed += 5;
for( zz = z-1; zz >= 0; zz--)
{
for( s = 0; s < 10; s++)
spielfeld[zz+1][s] = spielfeld[zz][s];
fuellstand[zz+1] = fuellstand[zz];
}
for( s = 0; s < 10; s++)
spielfeld[0][s] = 0;
fuellstand[0] = 0;
}
else
z--;
}
if( a == 0)
ultris_sounds.play( sound_down);
else if( a == 1)
ultris_sounds.play( sound_row1);
else
ultris_sounds.play( sound_row2);
}
// V11 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;
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;
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
}
}
}
}
}