#include "Spiel.h"
#include <time.h>
#include "KartenLeser.h"
#include "Statistik.h"
#include <DateiSystem.h>
#ifdef WIN32
#include <random>
#else
#include <math.h>
#include <unistd.h>
#include <stdlib.h>
#define Sleep( x )    usleep( (x) * 1000 )
#endif

#define TICK 0.03333333

// Inhalt der Spiel Klasse aus Spiel.h
// Konstruktor
Spiel::Spiel()
{
	stat = new Statistik();
	score = new Bestenliste();
	teams = new Array< int >();
	teamAnzahl = 0;
	psqldb = 0;
	spieler = new RCArray< Spieler >();
	spielerAnzahl = 0;
	spielId = 0;
	karte = new Karte();
	isRunning = 0;
	sts = 0;
	InitializeCriticalSection( &cs );
	rundenAnzahl = 0;
	spielZeit = 0;
	ende = 1;
	ref = 1;
}

// Destruktor
Spiel::~Spiel()
{
	teams->release();
	stat->release();
	score->release();
	spieler->release();
	if( psqldb )
		psqldb->release();
	karte->release();
	if( sts )
		sts->release();
	DeleteCriticalSection( &cs );
}

// nicht constant
void Spiel::setPSQLK( SSDatenbankV *psqldb )
{
	if( this->psqldb )
		this->psqldb->release();
	this->psqldb = psqldb;
	stat->setPSQLDB( psqldb->getThis() );
}

void Spiel::setSpielId( int id )
{
	spielId = id;
	stat->setSpielId( id );
}

void Spiel::setKarteId( int karteId )
{
	this->karteId = karteId;
	karte->setKarteId( karteId );
	stat->setKarteId( karteId );
}

void Spiel::setTempPfad( char *pfad )
{
    mapPfad = pfad;
    mapPfad += "/";
}

void Spiel::setAccounts( int anzahl, Array< int > *zAccounts )
{
	spielerAnzahl = anzahl;
	for( int i = 0; i < anzahl; i++ )
	{
		Spieler *tmp = new Spieler();
		tmp->setAccountId( zAccounts->hat( i ) ? zAccounts->get( i ) : 0 );
		spieler->set( tmp, i );
	}
	stat->setSpieler( spielerAnzahl, spieler );
}

void Spiel::setKlients( int anzahl, RCArray< SSKlientV > *zKlients )
{
	for( int i = 0; i < anzahl; i++ )
	{
		Spieler *tmp = spieler->z( i );
		if( tmp )
			tmp->setKlient( new Klient( zKlients->get( i ) ) );
	}
}

void Spiel::setSpielerNummern( int anzahl, Array< int > *spielerNummern )
{
	if( !sts )
	{
		sts = new SpielerTeamStruktur();
		KartenLeser *reader = new KartenLeser( karteId, psqldb->getThis(), mapPfad );
		reader->ladeSpielerTeamStruktur( sts );
		reader->release();
		stat->setTeamNamen( sts->teamName->getThis() );
	}
	for( int i = 0; i < anzahl; i++ )
	{
		Spieler *tmp = spieler->z( i );
		if( tmp )
		{
			int sNum = spielerNummern->hat( i ) ? spielerNummern->get( i ) : 0;
			tmp->setSpielerNummer( sNum );
			tmp->setSpielerFarbe( sts->spielerFarbe->hat( sNum ) ? sts->spielerFarbe->get( sNum ) : 0 );
			int team = 0;
			int von = 0;
			int bis = 0;
			for( int j = 0; j < sts->teamAnzahl; j++ )
			{
				bis = von + ( sts->teamSize->hat( j ) ? sts->teamSize->get( j ) : 0 );
				if( sNum >= von && sNum < bis )
				{
					team = j;
					break;
				}
				von = bis;
			}
			tmp->setTeam( team );
			tmp->setTeamFarbe( sts->teamFarbe->hat( team ) ? sts->teamFarbe->get( team ) : 0 );
		}
	}
}

void Spiel::klientOffline( int accountId )
{
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		if( spieler->z( i )->getAccountId() == accountId )
			spieler->z( i )->offline();
	}
}

void Spiel::klientOnline( int accountId, SSKlientV *zKlient )
{
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		if( spieler->z( i )->getAccountId() == accountId )
		{
			EnterCriticalSection( &cs );
			Spieler *s = spieler->z( i );
			s->online( zKlient );
			Klient *tmp = spieler->z( i )->zKlient();
			tmp->sendeSpielerNummer( s->getSpielerNummer(), 0 );
			tmp->sendeInitSpieler( spielerAnzahl, spieler, 0 );
			tmp->sendeKammeraSize( 400, 400, 0 );
			tmp->sendeKartenSize( karte->getBreite(), karte->getHeight(), 0 );
			for( int i = 0; i < spielerAnzahl; i++ )
			{
				Spieler *z = spieler->z( i );
				if( z )
				{
					tmp->sendeSpielerPosition( z, 0 );
					tmp->sendeSpielerGeschwindigkeit( z, 0 );
					tmp->sendeSpielerWendigkeit( z, 0 );
				}
			}
			LeaveCriticalSection( &cs );
		}
	}
}

void Spiel::nachricht( int accountId, int len, char *bytes )
{
	if( !isRunning || ende )
		return;
	EnterCriticalSection( &cs );
	if( ende )
	{
		LeaveCriticalSection( &cs );
		return;
	}
	char *msgBeg = bytes;
	int msgLen = len;
	int msgAccount = accountId;
	bool saveMSG = 1;
	len--;
	switch( *bytes )
	{
	case 0: // Spieler drückt T_Links
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			Spieler *tmp = spieler->z( i );
			if( tmp && tmp->getAccountId() == accountId )
			{
				if( !tmp->istAmLeben() )
					break;
				if( tmp->machtKurve( 0 ) )
				{
					saveMSG = 0;
					break;
				}
				tmp->setLKurve( 1 );
				for( int j = 0; j < spielerAnzahl; j++ )
				{
					Spieler *s = spieler->z( j );
					if( s && s->zKlient() )
						s->zKlient()->sendeSpielerKurve( tmp->getSpielerNummer(), 1, spielZeit );
				}
				break;
			}
		}
		break;
	case 1: // Spieler lässt T_Links los
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			Spieler *tmp = spieler->z( i );
			if( tmp && tmp->getAccountId() == accountId )
			{
				if( !tmp->istAmLeben() )
					break;
				if( !tmp->machtKurve( 0 ) )
				{
					saveMSG = 0;
					break;
				}
				tmp->setLKurve( 0 );
				for( int j = 0; j < spielerAnzahl; j++ )
				{
					Spieler *s = spieler->z( j );
					if( s && s->zKlient() )
						s->zKlient()->sendeSpielerKurve( tmp->getSpielerNummer(), 2, spielZeit );
				}
				break;
			}
		}
		break;
	case 2: // Spieler drückt T_Rechts
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			Spieler *tmp = spieler->z( i );
			if( tmp && tmp->getAccountId() == accountId )
			{
				if( !tmp->istAmLeben() )
					break;
				if( tmp->machtKurve( 1 ) )
				{
					saveMSG = 0;
					break;
				}
				tmp->setRKurve( 1 );
				for( int j = 0; j < spielerAnzahl; j++ )
				{
					Spieler *s = spieler->z( j );
					if( s && s->zKlient() )
						s->zKlient()->sendeSpielerKurve( tmp->getSpielerNummer(), 3, spielZeit );
				}
				break;
			}
		}
		break;
	case 3: // Spieler lässt T_Rechts los
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			Spieler *tmp = spieler->z( i );
			if( tmp && tmp->getAccountId() == accountId )
			{
				if( !tmp->istAmLeben() )
					break;
				if( !tmp->machtKurve( 1 ) )
				{
					saveMSG = 0;
					break;
				}
				tmp->setRKurve( 0 );
				for( int j = 0; j < spielerAnzahl; j++ )
				{
					Spieler *s = spieler->z( j );
					if( s && s->zKlient() )
						s->zKlient()->sendeSpielerKurve( tmp->getSpielerNummer(), 4, spielZeit );
				}
				break;
			}
		}
		break;
	case 4: // chat Nachricht
		if( 1 )
		{
			bytes++;
			Text *txt = psqldb->getAccountRufName( accountId );
			txt->append( ": " );
			txt->append( bytes, len );
			for( int i = 0; i < spielerAnzahl; i++ )
			{
				Spieler *tmp = spieler->z( i );
				if( tmp && tmp->zKlient() )
					tmp->zKlient()->sendeChatNachricht( txt->getText(), spielZeit );
			}
			txt->release();
			len = 0;
		}
		break;
	default:
		saveMSG = 0;
	}
	if( len )
	{
		// error
	}
	if( log && log->istOffen() && saveMSG )
	{
		char c = 1;
		log->schreibe( &c, 1 );
		int spielerNum = 0;
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			Spieler *tmp = spieler->z( i );
			if( tmp && tmp->getAccountId() == msgAccount )
			{
				spielerNum = tmp->getSpielerNummer();
				break;
			}
		}
		log->schreibe( (char*)&spielerNum, 4 );
		short l = (short)msgLen;
		log->schreibe( (char*)&l, 2 );
		log->schreibe( msgBeg, l );
	}
	LeaveCriticalSection( &cs );
}

void Spiel::tick( double zeit )
{
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		Spieler *tmp = spieler->z( i );
		if( tmp )
		{
			bool amLeben = tmp->istAmLeben();
			bool lu = tmp->linieIstUnterbrochen();
			tmp->tick( karte->zMap(), zeit );
			if( amLeben != tmp->istAmLeben() || lu != tmp->linieIstUnterbrochen() )
			{
				if( lu != tmp->linieIstUnterbrochen() )
				{
					char c = 1;
					log->schreibe( &c, 1 );
					int sNum = tmp->getSpielerNummer();
					log->schreibe( (char*)&sNum, 4 );
					short len = 2;
					log->schreibe( (char*)&len, 2 );
					c = 5;
					log->schreibe( &c, 1 );
					c = (char)tmp->linieIstUnterbrochen();
					log->schreibe( &c, 1 );
				}
				for( int j = 0; j < spielerAnzahl; j++ )
				{
					Spieler *s = spieler->z( j );
					if( s && s->zKlient() )
					{
						if( amLeben && !tmp->istAmLeben() )
						{
							if( tmp->getKillFarbe() == s->getSpielerFarbe() )
								s->addKill();
							s->zKlient()->sendeSpielerTod( tmp, spielZeit );
							if( s != tmp && s->istAmLeben() )
							{
								score->addSpielerPunkt( s->getSpielerNummer(), 1 );
								s->addPunkte( 1 );
							}
						}
						else if( lu != tmp->linieIstUnterbrochen() )
							s->zKlient()->sendeLinienUnterbrechung( tmp->getSpielerNummer(), tmp->linieIstUnterbrochen(), spielZeit );
					}
				}
				if( amLeben && !tmp->istAmLeben() )
				{
					int team = tmp->getSpielerTeam();
					bool teamLebt = 0;
					for( int k = 0; k < spielerAnzahl; k++ )
					{
						if( spieler->z( k ) && spieler->z( k )->getSpielerTeam() == team )
							teamLebt |= spieler->z( k )->istAmLeben();
					}
					if( !teamLebt )
					{
						int teamAmLebenAnzahl = 0;
						for( int k = 0; k < teamAnzahl; k++ )
						{
							int t = teams->hat( k ) ? teams->get( k ) : 0;
							bool amLeben = 0;
							for( int l = 0; l < spielerAnzahl; l++ )
							{
								if( spieler->z( l ) && spieler->z( l )->getSpielerTeam() == t )
									amLeben |= spieler->z( l )->istAmLeben();
							}
							if( amLeben )
							{
								teamAmLebenAnzahl++;
								score->addTeamPunkt( t, 1 );
							}
							else
								score->addTeamPunkt( t, 0 );
						}
						if( teamAmLebenAnzahl <= 1 )
							ende = 1;
					}
				}
			}
		}
	}
}

void Spiel::run()
{
	log = new Datei();
	Text *pfad = new Text( "../spiel log/" );
	pfad->append( spielId );
	pfad->append( "/verlauf.ksggl" );
	log->setDatei( pfad );
	log->remove();
	log->erstellen();
	log->open( Datei::Style::schreiben );
	time_t t;
	time( &t );
	srand( (unsigned int)t );
	log->schreibe( (char*)&spielerAnzahl, 4 );
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		Spieler *tmp = spieler->z( i );
		if( tmp && tmp->zKlient() )
		{
			log->schreibe( (char*)&i, 4 );
			int sNum = tmp->getSpielerNummer();
			score->setSpielerPunkte( sNum, 0 );
			log->schreibe( (char*)&sNum, 4 );
			tmp->zKlient()->sendeSpielerNummer( sNum, 0 );
			tmp->zKlient()->sendeInitSpieler( spielerAnzahl, spieler, 0 );
			int kg = 400;
			log->schreibe( (char*)&kg, 4 );
			log->schreibe( (char*)&kg, 4 );
			int team = tmp->getSpielerTeam();
			log->schreibe( (char*)&team, 4 );
			int farbe = tmp->getSpielerFarbe();
			log->schreibe( (char*)&farbe, 4 );
			farbe = tmp->getTeamFarbe();
			log->schreibe( (char*)&farbe, 4 );
			Text *name = psqldb->getAccountRufName( tmp->getAccountId() );
			char len = (char)( name ? name->getLength() : 0 );
			log->schreibe( &len, 1 );
			if( len )
				log->schreibe( name->getText(), len );
			if( name )
				name->release();
			name = sts->teamName->z( tmp->getSpielerTeam() );
			len = (char)( name ? name->getLength() : 0 );
			log->schreibe( &len, 1 );
			if( len )
				log->schreibe( name->getText(), len );
			tmp->zKlient()->sendeKammeraSize( 400, 400, 0 );
			bool gefunden = 0;
			for( int j = 0; j < teamAnzahl; j++ )
				gefunden |= teams->hat( j ) && teams->get( j ) == tmp->getSpielerTeam();
			if( !gefunden )
			{
				score->setTeamMaxPunkte( tmp->getSpielerTeam(), teamAnzahl * 3 );
				score->setTeamPunkte( tmp->getSpielerTeam(), ( teamAnzahl * 3 ) / 2 );
				teams->set( tmp->getSpielerTeam(), teamAnzahl );
				teamAnzahl++;
			}
		}
	}
	for( int i = 0; i < teamAnzahl; i++ )
	{
		score->setTeamMaxPunkte( teams->hat( i ) ? teams->get( i ) : 0, teamAnzahl * 3 );
		score->setTeamPunkte( teams->hat( i ) ? teams->get( i ) : 0, ( teamAnzahl * 3 ) / 2 );
	}
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		Spieler *tmp = spieler->z( i );
		if( tmp && tmp->zKlient() )
		{
			for( int j = 0; j < teamAnzahl; j++ )
			{
				int team = teams->hat( j ) ? teams->get( j ) : 0;
				if( i == 0 )
					log->schreibe( (char*)&team, 4 );
				int p = score->getTeamMaxPunkte( team );
				tmp->zKlient()->sendeTeamMaxPunkte( team, p, 0 );
				if( i == 0 )
					log->schreibe( (char*)&p, 4 );
				p = score->getTeamPunkte( team );
				tmp->zKlient()->sendeTeamPunkte( team, p, 0 );
				if( i == 0 )
					log->schreibe( (char*)&p, 4 );
				if( sts->teamName->z( team ) )
				    tmp->zKlient()->sendeTeamName( team, sts->teamName->z( team )->getText() );
			}
		}
	}
	Array< char > spielerStatus;
	int gewinner = -1;
	while( 1 )
	{
		rundenAnzahl++;
		int karteBreite = 400 + ( rand() % ( spielerAnzahl * 50 ) );
		int karteHeignt = 400 + ( rand() % ( spielerAnzahl * 50 ) );
		karte->setSize( karteBreite, karteHeignt );
		EnterCriticalSection( &cs );
		log->schreibe( (char*)&karteBreite, 4 );
		log->schreibe( (char*)&karteHeignt, 4 );
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			Spieler *tmp = spieler->z( i );
			if( tmp && tmp->zKlient() )
			{
				tmp->zKlient()->sendeKartenSize( karteBreite, karteHeignt, 0 );
				double w = 50.0 / 180 * PI;
				log->schreibe( (char*)&w, 8 );
				tmp->setWendigkeit( w );
				tmp->setPosition( 100 + ( rand() % ( karteBreite - 200 ) ), 100 + ( rand() % ( karteHeignt - 200 ) ) );
				double p = tmp->getX();
				log->schreibe( (char*)&p, 8 );
				p = tmp->getY();
				log->schreibe( (char*)&p, 8 );
				int grad = rand() % 180 - 90;
				double xs = sin( grad / 180.0 * PI ) * 30;
				log->schreibe( (char*)&xs, 8 );
				double ys = sqrt( 30 * 30 - xs * xs );
				ys *= ( rand() % 2 > 0 ) ? 1 : -1;
				log->schreibe( (char*)&ys, 8 );
				tmp->setGeschwindigkeit( xs, ys );
			}
		}
		LeaveCriticalSection( &cs );
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			Spieler *tmp = spieler->z( i );
			if( tmp )
			{
				for( int j = 0; j < spielerAnzahl; j++ )
				{
					Spieler *s = spieler->z( j );
					if( s && s->zKlient() )
					{
						s->zKlient()->sendeSpielerPosition( tmp, 0 );
						s->zKlient()->sendeSpielerGeschwindigkeit( tmp, 0 );
						s->zKlient()->sendeSpielerWendigkeit( tmp, 0 );
					}
				}
			}
		}
		for( int i = 0; i < teamAnzahl; i++ )
		{
			if( teams->hat( i ) && !score->istTeamAmLeben( teams->get( i ) ) )
			{
				for( int j = 0; j < spielerAnzahl; j++ )
				{
					Spieler *tmp = spieler->z( teams->get( i ) );
					if( tmp )
						tmp->zKlient()->sendeTeamTod( teams->get( i ), 0 );
				}
			}
		}
		ZeitMesser *zeit = new ZeitMesser();
		zeit->messungStart();
		isRunning = 1;
		ende = 0;
		double ausgleich = 0;
		spielZeit = 0;
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			Spieler *tmp = spieler->z( i );
			if( tmp && tmp->zKlient() )
				tmp->zKlient()->sendeStart( 0 );
		}
		double rZeit = 0;
		while( !ende )
		{
			zeit->messungEnde();
			zeit->messungStart();
			double z = zeit->getSekunden();
			ausgleich += 1.0 / 25 - z;
			if( ausgleich > 0 )
				Sleep( (int)( ausgleich * 1000 ) );
			rZeit += z;
			while( spielZeit + TICK < rZeit && !ende )
			{
				EnterCriticalSection( &cs );
				spielZeit += TICK;
				char c = 0;
				log->schreibe( &c, 1 );
				tick( TICK );
				LeaveCriticalSection( &cs );
			}
		}
		zeit->messungEnde();
		zeit->release();
		gewinner = -1;
		for( int i = 0; i < spielerAnzahl; i++ )
		{
			if( spieler->z( i )->istAmLeben() )
			{
				gewinner = spieler->z( i )->getSpielerTeam();
				break;
			}
		}
		if( gewinner < 0 )
		{
			double sterbeZeit = 0;
			for( int i = 0; i < spielerAnzahl; i++ )
			{
				if( spieler->z( i )->getTodesZeit() >= sterbeZeit )
				{
					sterbeZeit = spieler->z( i )->getTodesZeit();
					gewinner = spieler->z( i )->getSpielerTeam();
				}
			}
		}
		stat->rundenEnde( gewinner, (int)spielZeit, karte->zMap()->getThis() );
		int winTeamAnzahl = 0;
		Array< int > *winTeams = new Array< int >();
		for( int i = 0; i < teamAnzahl; i++ )
		{
			if( score->hatTeamGewonnen( i ) || rundenAnzahl >= 10 )
			{
				winTeams->add( i, winTeamAnzahl );
				winTeamAnzahl++;
			}
		}
		if( !winTeamAnzahl )
		{
			int verloren = 0;
			int team = -1;
			for( int i = 0; i < teamAnzahl; i++ )
			{
				int t = teams->hat( i ) ? teams->get( i ) : 0;
				if( !score->getTeamPunkte( t ) )
					verloren++;
				else
					team = t;
			}
			if( verloren == teamAnzahl - 1 )
			{
				winTeams->add( team, winTeamAnzahl );
				winTeamAnzahl++;
			}
		}
		if( winTeamAnzahl > 1 )
		{
			int p = -1;
			for( int i = 0; i < winTeamAnzahl; i++ )
			{
				int t = winTeams->hat( i ) ? winTeams->get( i ) : 0;
				if( score->getTeamMaxPunkte( t ) - score->getTeamPunkte( t ) < p || p < 0 )
				{
					p = score->getTeamMaxPunkte( t ) - score->getTeamPunkte( t );
					for( int j = 0; j < winTeamAnzahl; j++ )
					{
						int tt = winTeams->hat( j ) ? winTeams->get( j ) : 0;
						if( score->getTeamMaxPunkte( tt ) - score->getTeamPunkte( tt ) > p )
						{
							if( i >= j )
								i--;
							score->setTeamPunkte( tt, 0 );
							winTeams->remove( j );
							winTeamAnzahl--;
							j--;
						}
					}
				}
			}
		}
		if( ( !winTeamAnzahl || winTeamAnzahl > 1 ) && teamAnzahl > 1 && rundenAnzahl < 10 )
		{
			winTeams->release();
			for( int i = 0; i < spielerAnzahl; i++ )
			{
				if( spieler->z( i ) && spieler->z( i )->zKlient() )
				{
					spieler->z( i )->neuRunde( score->getTeamPunkte( spieler->z( i )->getSpielerTeam() ) != 0 );
					spieler->z( i )->zKlient()->sendeRundenEnde( gewinner, 0 );
				}
			}
			for( int i = 5; i >= 0; i-- )
			{
				for( int k = 0; k < 10; k++ )
				{
					Sleep( 100 );
					for( int j = 0; j < spielerAnzahl; j++ )
					{
						if( spieler->z( j ) && spieler->z( j )->zKlient() )
							spieler->z( j )->zKlient()->sendeZeitVerbleibend( i, 0 );
					}
					if( !i )
						break;
				}
			}
		}
		else
		{
			for( int i = 0; i < spielerAnzahl; i++ )
			{
				if( spieler->z( i ) && spieler->z( i )->zKlient() )
				{
					if( winTeams->getWertIndex( spieler->z( i )->getSpielerTeam() ) < 0 )
					{
						spielerStatus.set( 1, i ); // Datenbank Verloren
						spieler->z( i )->zKlient()->sendeSpielEnde( 0, 0 );
					}
					else if( winTeamAnzahl > 1 )
					{
						spielerStatus.set( 5, i ); // Datenbank Unentschieden
						spieler->z( i )->zKlient()->sendeSpielEnde( 2, 0 );
					}
					else
					{
						spielerStatus.set( 2, i ); // Datenbank Gewonnen
						spieler->z( i )->zKlient()->sendeSpielEnde( 1, 0 );
					}
				}
				if( spieler->z( i ) && ( !spieler->z( i )->zKlient() || !spieler->z( i )->istOnline() ) )
					spielerStatus.set( 3, i );
			}
			winTeams->release();
			break;
		}
	}
	if( teamAnzahl == 1 )
		psqldb->setSpielStatusBeendet( spielId, 6 );
	else
		psqldb->setSpielStatusBeendet( spielId, 5 );
	for( int i = 0; i < spielerAnzahl; i++ )
	{
		Spieler *tmp = spieler->z( i );
		if( tmp )
		{
			psqldb->setSpielSpielerStatus( spielId, tmp->getAccountId(), tmp->getPunkte(), spielerStatus.get( i ) );
			if( teamAnzahl > 1 )
				psqldb->addSpielerStatistik( tmp->getAccountId(), spielId );
		}
	}
	log->close();
	log = log->release();
	isRunning = 0;
}

// constant
StatistikV *Spiel::getStatistik() const
{
	return stat->getThis();
}

// Reference Counting 
SpielKlasse *Spiel::getThis()
{
	ref++;
	return this;
}

SpielKlasse *Spiel::release()
{
	ref--;
	if( !ref )
		delete this;
	return 0;
}