Browse Source

Projektdateien hinzufügen.

Kolja Strohm 6 years ago
parent
commit
0f693f3283
57 changed files with 10174 additions and 0 deletions
  1. 28 0
      Linie.sln
  2. 650 0
      Linie/Aufzeichnung/Aufzeichnung.cpp
  3. 61 0
      Linie/Aufzeichnung/Aufzeichnung.h
  4. 714 0
      Linie/Aufzeichnung/Bestenliste/VideoBestenliste.cpp
  5. 137 0
      Linie/Aufzeichnung/Bestenliste/VideoBestenliste.h
  6. 109 0
      Linie/Aufzeichnung/Chat/VideoChat.cpp
  7. 33 0
      Linie/Aufzeichnung/Chat/VideoChat.h
  8. 72 0
      Linie/Aufzeichnung/Ende/VideoEnde.cpp
  9. 30 0
      Linie/Aufzeichnung/Ende/VideoEnde.h
  10. 145 0
      Linie/Aufzeichnung/Kamera/VideoKamera.cpp
  11. 45 0
      Linie/Aufzeichnung/Kamera/VideoKamera.h
  12. 89 0
      Linie/Aufzeichnung/Karte/VideoKarte.cpp
  13. 37 0
      Linie/Aufzeichnung/Karte/VideoKarte.h
  14. 366 0
      Linie/Aufzeichnung/Nachricht/VideoNachricht.cpp
  15. 102 0
      Linie/Aufzeichnung/Nachricht/VideoNachricht.h
  16. 385 0
      Linie/Aufzeichnung/Spieler/VideoSpieler.cpp
  17. 95 0
      Linie/Aufzeichnung/Spieler/VideoSpieler.h
  18. 219 0
      Linie/Aufzeichnung/Steuerung/VideoSteuerung.cpp
  19. 45 0
      Linie/Aufzeichnung/Steuerung/VideoSteuerung.h
  20. 55 0
      Linie/Aufzeichnung/VideoDaten/VideoDaten.h
  21. 214 0
      Linie/HistorieStatistik/HistorieStatistik.cpp
  22. 50 0
      Linie/HistorieStatistik/HistorieStatistik.h
  23. 411 0
      Linie/HistorieStatistik/StatistikLeser.cpp
  24. 44 0
      Linie/HistorieStatistik/StatistikLeser.h
  25. 218 0
      Linie/Initialisierung/Initialisierung.cpp
  26. 32 0
      Linie/Initialisierung/Initialisierung.h
  27. 235 0
      Linie/Linie.vcxproj
  28. 180 0
      Linie/Linie.vcxproj.filters
  29. 62 0
      Linie/Netzwerk/STKNachricht.cpp
  30. 30 0
      Linie/Netzwerk/STKNachricht.h
  31. 654 0
      Linie/Spiel/Bestenliste/Bestenliste.cpp
  32. 131 0
      Linie/Spiel/Bestenliste/Bestenliste.h
  33. 161 0
      Linie/Spiel/Chat/Chat.cpp
  34. 37 0
      Linie/Spiel/Chat/Chat.h
  35. 111 0
      Linie/Spiel/Ende/Ende.cpp
  36. 34 0
      Linie/Spiel/Ende/Ende.h
  37. 99 0
      Linie/Spiel/Ende/RundenEnde.cpp
  38. 34 0
      Linie/Spiel/Ende/RundenEnde.h
  39. 124 0
      Linie/Spiel/Kamera/Kamera.cpp
  40. 45 0
      Linie/Spiel/Kamera/Kamera.h
  41. 78 0
      Linie/Spiel/Karte/Karte.cpp
  42. 37 0
      Linie/Spiel/Karte/Karte.h
  43. 820 0
      Linie/Spiel/SpielKlasse.cpp
  44. 69 0
      Linie/Spiel/SpielKlasse.h
  45. 380 0
      Linie/Spiel/Spieler/Spieler.cpp
  46. 71 0
      Linie/Spiel/Spieler/Spieler.h
  47. 518 0
      Linie/SpielStatistik/Chat/StatistikChat.cpp
  48. 131 0
      Linie/SpielStatistik/Chat/StatistikChat.h
  49. 142 0
      Linie/SpielStatistik/Runde/StatistikRunde.cpp
  50. 42 0
      Linie/SpielStatistik/Runde/StatistikRunde.h
  51. 564 0
      Linie/SpielStatistik/SpielStatistik.cpp
  52. 66 0
      Linie/SpielStatistik/SpielStatistik.h
  53. 72 0
      Linie/SpielStatistik/SpielStatistikDaten.h
  54. 776 0
      Linie/SpielStatistik/Tabelle/StatistikTabelle.cpp
  55. 55 0
      Linie/SpielStatistik/Tabelle/StatistikTabelle.h
  56. 27 0
      Linie/Start/DllStart.cpp
  57. 3 0
      build.bat

+ 28 - 0
Linie.sln

@@ -0,0 +1,28 @@
+
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 14
+VisualStudioVersion = 14.0.22823.1
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Linie", "Linie\Linie.vcxproj", "{B2E0B9EF-0131-42B7-A7AC-A5A74C7547A7}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Win32 = Debug|Win32
+		Debug|x64 = Debug|x64
+		Release|Win32 = Release|Win32
+		Release|x64 = Release|x64
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{B2E0B9EF-0131-42B7-A7AC-A5A74C7547A7}.Debug|Win32.ActiveCfg = Debug|Win32
+		{B2E0B9EF-0131-42B7-A7AC-A5A74C7547A7}.Debug|Win32.Build.0 = Debug|Win32
+		{B2E0B9EF-0131-42B7-A7AC-A5A74C7547A7}.Debug|x64.ActiveCfg = Debug|x64
+		{B2E0B9EF-0131-42B7-A7AC-A5A74C7547A7}.Debug|x64.Build.0 = Debug|x64
+		{B2E0B9EF-0131-42B7-A7AC-A5A74C7547A7}.Release|Win32.ActiveCfg = Release|Win32
+		{B2E0B9EF-0131-42B7-A7AC-A5A74C7547A7}.Release|Win32.Build.0 = Release|Win32
+		{B2E0B9EF-0131-42B7-A7AC-A5A74C7547A7}.Release|x64.ActiveCfg = Release|x64
+		{B2E0B9EF-0131-42B7-A7AC-A5A74C7547A7}.Release|x64.Build.0 = Release|x64
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+EndGlobal

+ 650 - 0
Linie/Aufzeichnung/Aufzeichnung.cpp

@@ -0,0 +1,650 @@
+#include "Aufzeichnung.h"
+#include <MausEreignis.h>
+#include <TastaturEreignis.h>
+
+// Inhalt der Aufzeichnung Klasse auf Aufzeichnung.h
+// Konstruktor
+Aufzeichnung::Aufzeichnung()
+{
+	nMsg = 0;
+	nMsgVorwärts = 0;
+	schrift = 0;
+	screen = 0;
+	nachrichten = 0;
+	bestenliste = 0;
+	chat = 0;
+	steuerung = 0;
+	kam = 0;
+	map = 0;
+	ende = 0;
+	spieler = new RCArray< VideoSpieler >();
+	spielZeit = 0;
+	rSpielZeit = new Array< double >();
+	spielPause = 1;
+	spielerAnzahl = 0;
+	teamAnzahl = 0;
+	kamSpielerNummer = -1;
+	mx = -1;
+	my = -1;
+	geladen = 0;
+	pauseZeit = -1;
+	time = 0;
+	ref = 1;
+}
+
+// Destruktor
+Aufzeichnung::~Aufzeichnung()
+{
+	if( schrift )
+		schrift->release();
+	if( screen )
+		screen->release();
+	spieler->release();
+	if( ende )
+		ende->release();
+	if( map )
+		map->release();
+	if( kam )
+		kam->release();
+	if( steuerung )
+		steuerung->release();
+	if( chat )
+		chat->relese();
+	if( bestenliste )
+		bestenliste->release();
+	if( nachrichten )
+		nachrichten->release();
+	rSpielZeit->release();
+}
+
+// nicht constant
+void Aufzeichnung::setSchrift( Schrift *schrift )
+{
+	if( this->schrift )
+		this->schrift->release();
+	this->schrift = schrift;
+}
+
+void Aufzeichnung::setBildschirm( Bildschirm *screen )
+{
+	if( this->screen )
+		this->screen->release();
+	this->screen = screen;
+}
+
+bool Aufzeichnung::ladeSpiel( int id )
+{
+	nachrichten = new SpielNachricht( id );
+	bestenliste = new VideoBestenliste( schrift->getThis() );
+	chat = new VideoChat( schrift );
+	steuerung = new VideoSteuerung( schrift, screen );
+	kam = new VideoKamera();
+	map = new VideoKarte();
+	ende = new VideoEnde( schrift );
+	Text f;
+	if( nachrichten->hatFehler( &f ) )
+	{
+		ende->setText( f );
+		ende->setSichtbar( 1 );
+		geladen = 1;
+		return 1;
+	}
+	spielerAnzahl = nachrichten->getSVD()->spielerAnzahl;
+	teamAnzahl = 0;
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		SpielerVideoDaten *dat = nachrichten->getSPVD( i );
+		if( !i )
+			kam->setSize( dat->kamBreite, dat->kamHöhe );
+		VideoSpieler *tmp = new VideoSpieler( dat );
+		bestenliste->addSpieler( tmp );
+		spieler->set( tmp, i );
+		teamAnzahl = teamAnzahl < dat->team ? dat->team : teamAnzahl;
+	}
+	teamAnzahl++;
+	bestenliste->setTeamAnzahl( teamAnzahl );
+	for( int i = 0; i < nachrichten->getTeamAnzahl(); i++ )
+	{
+		TeamVideoDaten *dat = nachrichten->getTVD( i );
+		bestenliste->setTeamMaxPunkte( dat->teamNummer, dat->maxPunkte );
+		bestenliste->setTeamPunkte( dat->teamNummer, dat->punkte );
+	}
+	RundeVideoDaten *rDat = nachrichten->getRVD();
+	map->setSize( rDat->mapBreite, rDat->mapHöhe );
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		RundeSpielerVideoDaten *dat = nachrichten->getRSVD( i );
+		spieler->z( i )->neuRunde( 1, dat, 1 );
+		bestenliste->updateSpielerStatus( spieler->z( i ) );
+	}
+	pauseZeit = 3;
+	ende->setText( "Die Aufzeichnung des Spiels wird geladen.\nRunde 1 beginnt in kürze." );
+	ende->setSichtbar( 1 );
+	geladen = 1;
+	return 1;
+}
+
+void Aufzeichnung::doMausEreignis( MausEreignis &me )
+{
+	if( !geladen )
+		return;
+	if( kam->istMausIn( me.mx, me.my ) )
+	{
+		if( me.id == ME_PLinks )
+		{
+			for( int i = 0; i < spielerAnzahl; i++ )
+			{
+				if( spieler->z( i )->istMausIn( kam->getLinks() + me.mx - kam->getRX( kam->getLinks() ), kam->getOben() + me.my - kam->getRY( kam->getOben() ) ) )
+				{
+					kamSpielerNummer = spieler->z( i )->getSpielerNummer();
+					me.verarbeitet = 1;
+					break;
+				}
+			}
+		}
+		if( ( me.id == ME_RLinks || me.id == ME_RRechts ) && mx >= 0 )
+		{
+			mx = -1;
+			my = -1;
+		}
+		if( me.id == ME_Bewegung && mx >= 0 )
+		{
+			kam->addPosition( mx - me.mx, my - me.my, map );
+			mx = me.mx;
+			my = me.my;
+		}
+		if( ( me.id == ME_PLinks || me.id == ME_PRechts ) && mx < 0 && !me.verarbeitet )
+		{
+			mx = me.mx;
+			my = me.my;
+			kamSpielerNummer = -1;
+		}
+		me.verarbeitet = 1;
+	}
+	else
+	{
+		mx = -1;
+		my = -1;
+	}
+	bestenliste->doMausEreignis( me );
+	steuerung->doMausEreignis( me );
+}
+
+void Aufzeichnung::doTastaturEreignis( TastaturEreignis &te )
+{
+	if( !geladen )
+		return;
+	if( te.id == TE_Press )
+	{
+		switch( te.taste )
+		{
+		case T_Links:
+			kam->addPosition( -2, 0, map );
+			te.verarbeitet = 1;
+			break;
+		case T_Oben:
+			kam->addPosition( 0, -2, map );
+			te.verarbeitet = 1;
+			break;
+		case T_Rechts:
+			kam->addPosition( 2, 0, map );
+			te.verarbeitet = 1;
+			break;
+		case T_Unten:
+			kam->addPosition( 0, 2, map );
+			te.verarbeitet = 1;
+			break;
+		}
+		if( te.verarbeitet )
+			kamSpielerNummer = -1;
+	}
+}
+
+bool Aufzeichnung::spielTick( double spielZeit )
+{
+	this->spielZeit += spielZeit;
+	bool setKam = kamSpielerNummer >= 0;
+	int x = 0;
+	int y = 0;
+	bool rEnd = 0;
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		VideoSpieler *tmp = spieler->z( i );
+		if( tmp )
+		{
+			if( tmp->getSpielerNummer() == kamSpielerNummer )
+			{
+				x = (int)( tmp->getX() + 0.5 );
+				y = (int)( tmp->getY() + 0.5 );
+			}
+			bool amLeben = tmp->istAmLeben();
+			tmp->tick( map->zMap(), spielZeit );
+			if( amLeben != tmp->istAmLeben() )
+			{
+				bestenliste->updateSpielerStatus( tmp );
+				for( int j = 0; j < spielerAnzahl; j++ )
+				{
+					VideoSpieler *s = spieler->z( j );
+					if( s && s != tmp && s->istAmLeben() )
+						bestenliste->addPunkt( s->getTeam(), s->getSpielerNummer(), spielZeit > 0 );
+				}
+			}
+			if( amLeben && !tmp->istAmLeben() )
+			{ // gestorben
+				int team = tmp->getTeam();
+				bool teamLebt = 0;
+				for( int k = 0; k < spielerAnzahl; k++ )
+				{
+					if( spieler->z( k ) && spieler->z( k )->getTeam() == team )
+						teamLebt |= spieler->z( k )->istAmLeben();
+				}
+				if( !teamLebt )
+				{
+					int teamAmLebenAnzahl = 0;
+					for( int k = 0; k < teamAnzahl; k++ )
+					{
+						if( !bestenliste->teamExistiert( k ) )
+							continue;
+						bool amLeben = 0;
+						for( int l = 0; l < spielerAnzahl; l++ )
+						{
+							if( spieler->z( l ) && spieler->z( l )->getTeam() == k )
+								amLeben |= spieler->z( l )->istAmLeben();
+						}
+						if( amLeben )
+						{
+							teamAmLebenAnzahl++;
+							bestenliste->addPunkt( k, 1 );
+						}
+						else
+							bestenliste->addPunkt( k, 0 );
+						if( !bestenliste->getTeamPunkte( k ) )
+							bestenliste->setTeamStatus( k, "tod", 0xFFFF0000 );
+					}
+					if( teamAmLebenAnzahl <= 1 )
+						rEnd = 1;
+				}
+			}
+			if( !amLeben && tmp->istAmLeben() )
+			{ // Wiederbelebt
+				int team = tmp->getTeam();
+				bool teamLebt = 0;
+				for( int k = 0; k < spielerAnzahl; k++ )
+				{
+					if( k != i && spieler->z( k ) && spieler->z( k )->getTeam() == team )
+						teamLebt |= spieler->z( k )->istAmLeben();
+				}
+				if( !teamLebt )
+				{
+					for( int k = 0; k < teamAnzahl; k++ )
+					{
+						if( !bestenliste->teamExistiert( k ) )
+							continue;
+						bool amLeben = 0;
+						for( int l = 0; l < spielerAnzahl; l++ )
+						{
+							if( l != i && spieler->z( l ) && spieler->z( l )->getTeam() == k )
+								amLeben |= spieler->z( l )->istAmLeben();
+						}
+						if( amLeben )
+							bestenliste->addPunkt( k, 0 );
+						else
+							bestenliste->addPunkt( k, 1 );
+						if( bestenliste->getTeamPunkte( k ) )
+							bestenliste->setTeamStatus( k, "lebt", 0xFF00FF00 );
+					}
+				}
+			}
+		}
+	}
+	if( setKam )
+	{
+		double z = spielZeit < 0 ? -spielZeit : spielZeit;
+		double px = ( ( x - kam->getX() ) / 100.0 ) * ( 50 * z );
+		double py = ( ( y - kam->getY() ) / 100.0 ) * ( 50 * z );
+		kam->addPosition( (int)px, (int)py, map );
+	}
+	chat->tick( spielZeit );
+	steuerung->tick( spielZeit );
+	if( rEnd && spielZeit > 0 )
+	{ // Runden Ende
+		int nAnz = 0;
+		int nAnz2 = 0;
+		for( int i = 0; i < teamAnzahl; i++ )
+		{
+			if( bestenliste->teamExistiert( i ) )
+			{
+				nAnz += bestenliste->hatTeamGewonnen( i );
+				nAnz2 += bestenliste->getTeamPunkte( i ) >= 0;
+			}
+		}
+		if( nAnz || nAnz2 <= 1 || nachrichten->getRunde() >= 9 )
+		{ // Spiel Ende
+			steuerung->pause( 1 );
+			return 1;
+		}
+		spielPause = 1;
+		pauseZeit = 2;
+		ende->setText( "Die nächste Runde beginnt in kürze." );
+		ende->setSichtbar( 1 );
+		int r = nachrichten->setRundenEnde( 1 );
+		rSpielZeit->set( spielZeit, r - 1 );
+		this->spielZeit = 0;
+		time = 0;
+		bestenliste->updatePunkte();
+		kam->nextRunde( 1 );
+		map->nextRunde( 1 );
+		RundeVideoDaten *dat = nachrichten->getRVD();
+		map->setSize( dat->mapBreite, dat->mapHöhe );
+		for( int i = 0; i < spielerAnzahl; i++ )
+		{
+			spieler->z( i )->neuRunde( 1, nachrichten->getRSVD( i ), bestenliste->getTeamPunkte( spieler->z( i )->getTeam() ) != 0 );
+			bestenliste->updateSpielerStatus( spieler->z( i ) );
+		}
+		return 1;
+	}
+	return 0;
+}
+
+bool Aufzeichnung::tick( double tickVal )
+{
+	if( !geladen )
+		return 0;
+	if( spielPause )
+	{
+		if( pauseZeit >= 0 )
+		{
+			pauseZeit -= tickVal;
+			if( pauseZeit < 0 )
+			{
+				pauseZeit = 0;
+				spielPause = 0;
+				ende->setSichtbar( 0 );
+			}
+		}
+		chat->tick( 0 );
+		steuerung->tick( 0 );
+		return 1;
+	}
+	if( ( steuerung->istVorwärts() || nMsg && nMsgVorwärts ) && !( nMsg && !nMsgVorwärts ) )
+	{
+		if( steuerung->istZeitlupe() )
+			time += tickVal / steuerung->getSpeed();
+		else
+			time += tickVal * steuerung->getSpeed();
+		while( steuerung->getSpeed() != 0 )
+		{
+			while( !nMsg || nMsg->typ && steuerung->getSpeed() != 0 )
+			{
+				if( !nMsg )
+					nMsg = nachrichten->GetNextNachricht();
+				if( !nMsg )
+					break;
+				nMsgVorwärts = 1;
+				if( !nMsg->typ )
+					break;
+				VideoAktionMSG *ak = (VideoAktionMSG*)nMsg;
+				switch( ak->aktion )
+				{
+				case 0: // T_Links Press
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+						{
+							spieler->z( i )->setLinksKurve( 1 );
+							break;
+						}
+					}
+					break;
+				case 1: // T_Links Release
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+						{
+							spieler->z( i )->setLinksKurve( 0 );
+							break;
+						}
+					}
+					break;
+				case 2: // T_Rechts Press
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+						{
+							spieler->z( i )->setRechtsKurve( 1 );
+							break;
+						}
+					}
+					break;
+				case 3: // T_Rechts Release
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+						{
+							spieler->z( i )->setRechtsKurve( 0 );
+							break;
+						}
+					}
+					break;
+				case 4: // Chat Nachricht
+					if( 1 )
+					{
+						VideoChatMSG *msg = (VideoChatMSG*)ak;
+						for( int i = 0; i < spielerAnzahl; i++ )
+						{
+							if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+							{
+								Text txt = spieler->z( i )->zName()->getText();
+								txt += ": ";
+								txt += msg->msg.getText();
+								chat->addNachricht( txt );
+								break;
+							}
+						}
+					}
+					break;
+				case 5: // Linien Unterbrechung
+					if( 1 )
+					{
+						VideoLinieMSG *lMsg = (VideoLinieMSG*)ak;
+						for( int i = 0; i < spielerAnzahl; i++ )
+						{
+							if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+							{
+								spieler->z( i )->setLinienUnterbrechung( lMsg->unterbrechung != 0 );
+								break;
+							}
+						}
+					}
+					break;
+				}
+				nMsg = 0;
+			}
+			if( !nMsg )
+				break;
+			if( time > spielZeit + TICK )
+			{
+				bool end = spielTick( TICK );
+				nMsg = 0;
+				if( !steuerung->istVorwärts() || end )
+					break;
+			}
+			else
+				break;
+		}
+	}
+	else
+	{
+		if( steuerung->istZeitlupe() )
+			time -= tickVal / steuerung->getSpeed();
+		else
+			time -= tickVal * steuerung->getSpeed();
+		while( 1 )
+		{
+			while( !nMsg || nMsg->typ )
+			{
+				if( !nMsg )
+				{
+					nMsg = nachrichten->GetLastNachricht();
+					nMsgVorwärts = 0;
+					if( !nMsg )
+					{
+						int r = nachrichten->setRundenEnde( 0 );
+						if( r < 0 )
+						{ // Spiel Beginn
+							steuerung->pause( 0 );
+							return 1;
+						}
+						bestenliste->updatePunkte( 0 );
+						kam->nextRunde( 0 );
+						map->nextRunde( 0 );
+						for( int i = 0; i < spielerAnzahl; i++ )
+							spieler->z( i )->neuRunde( 0, 0, 1 );
+						spielPause = 1;
+						pauseZeit = 2;
+						ende->setText( "Vorherige Runde beginnt in kürze." );
+						ende->setSichtbar( 1 );
+						spielZeit = rSpielZeit->get( r );
+						time = spielZeit;
+						return 1;
+					}
+				}
+				if( !nMsg->typ )
+					break;
+				VideoAktionMSG *ak = (VideoAktionMSG*)nMsg;
+				switch( ak->aktion )
+				{
+				case 0: // T_Links Press
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+						{
+							spieler->z( i )->setLinksKurve( 0 );
+							break;
+						}
+					}
+					break;
+				case 1: // T_Links Release
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+						{
+							spieler->z( i )->setLinksKurve( 1 );
+							break;
+						}
+					}
+					break;
+				case 2: // T_Rechts Press
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+						{
+							spieler->z( i )->setRechtsKurve( 0 );
+							break;
+						}
+					}
+					break;
+				case 3: // T_Rechts Release
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+						{
+							spieler->z( i )->setRechtsKurve( 1 );
+							break;
+						}
+					}
+					break;
+				case 4: // Chat Nachricht
+					if( 1 )
+					{
+						VideoChatMSG *msg = (VideoChatMSG*)ak;
+						for( int i = 0; i < spielerAnzahl; i++ )
+						{
+							if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+							{
+								Text txt = spieler->z( i )->zName()->getText();
+								txt += ": ";
+								txt += msg->msg.getText();
+								chat->removeNachricht( txt );
+								break;
+							}
+						}
+					}
+					break;
+				case 5: // Linien Unterbrechung
+					if( 1 )
+					{
+						VideoLinieMSG *lMsg = (VideoLinieMSG*)ak;
+						if( 1 )
+						{
+							for( int i = 0; i < spielerAnzahl; i++ )
+							{
+								if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+								{
+									spieler->z( i )->setLinienUnterbrechung( lMsg->unterbrechung == 0 );
+									break;
+								}
+							}
+						}
+					}
+					break;
+				}
+				nMsg = 0;
+			}
+			if( time <= spielZeit - TICK )
+			{
+				spielTick( -TICK );
+				nMsg = 0;
+				if( steuerung->istVorwärts() )
+					break;
+			}
+			else
+				break;
+		}
+	}
+	return 1;
+}
+
+void Aufzeichnung::render( Bild &zRObj )
+{
+	if( !geladen )
+		return;
+	bestenliste->render( zRObj );
+	chat->render( zRObj );
+	steuerung->render( zRObj );
+	kam->render( zRObj );
+	int x = kam->getRX( kam->getLinks() ) + 1, y = kam->getRY( kam->getOben() ) + 1;
+	if( zRObj.setDrawOptions( x, y, kam->getRechts() - kam->getLinks() - 2, kam->getUnten() - kam->getOben() - 2 ) )
+	{
+		zRObj.addScrollOffset( x, y );
+		map->render( kam, zRObj );
+		for( int i = 0; i < spielerAnzahl; i++ )
+			spieler->z( i )->render( kam, zRObj );
+		zRObj.releaseDrawOptions();
+	}
+	if( ende )
+		ende->render( zRObj );
+}
+
+// constant
+bool Aufzeichnung::hatVerlassen( bool jetzt ) const
+{
+	if( !geladen )
+		return 0;
+	return steuerung->istBeendet( jetzt );
+}
+
+// Reference Counting
+AufzeichnungV *Aufzeichnung::getThis()
+{
+	ref++;
+	return this;
+}
+
+AufzeichnungV *Aufzeichnung::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 61 - 0
Linie/Aufzeichnung/Aufzeichnung.h

@@ -0,0 +1,61 @@
+#ifndef Aufzeichnung_H
+#define Aufzeichnung_H
+
+#include <AufzeichnungV.h>
+#include "Bestenliste/VideoBestenliste.h"
+#include "Chat/VideoChat.h"
+#include "Ende/VideoEnde.h"
+#include "Nachricht/VideoNachricht.h"
+#include "Spieler/VideoSpieler.h"
+#include "Steuerung/VideoSteuerung.h"
+
+class Aufzeichnung : public AufzeichnungV
+{
+private:
+	Schrift *schrift;
+	Bildschirm *screen;
+	SpielNachricht *nachrichten;
+	VideoBestenliste *bestenliste;
+	VideoChat *chat;
+	VideoSteuerung *steuerung;
+	VideoKamera *kam;
+	VideoKarte *map;
+	VideoEnde *ende;
+	RCArray< VideoSpieler > *spieler;
+	VideoMSG *nMsg;
+	bool nMsgVorwärts;
+	Array< double > *rSpielZeit;
+	double pauseZeit;
+	double spielZeit;
+	double time;
+	bool spielPause;
+	int spielerAnzahl;
+	int teamAnzahl;
+	int kamSpielerNummer;
+	int mx;
+	int my;
+	bool geladen;
+	int ref;
+
+public:
+	// Konstruktor
+	Aufzeichnung();
+	// Destruktor
+	~Aufzeichnung();
+	// nicht constant
+	void setSchrift( Schrift *schrift ) override;
+	void setBildschirm( Bildschirm *screen ) override;
+	bool ladeSpiel( int id ) override;
+	void doMausEreignis( MausEreignis &me ) override;
+	void doTastaturEreignis( TastaturEreignis &te ) override;
+	bool spielTick( double spielZeit );
+	bool tick( double tickVal ) override;
+	void render( Bild &zRObj ) override;
+	// constant
+	bool hatVerlassen( bool jetzt ) const override;
+	// Reference Counting
+	AufzeichnungV *getThis() override;
+	AufzeichnungV *release() override;
+};
+
+#endif

+ 714 - 0
Linie/Aufzeichnung/Bestenliste/VideoBestenliste.cpp

@@ -0,0 +1,714 @@
+#include "VideoBestenliste.h"
+#include "..\Spieler\VideoSpieler.h"
+#include <Rahmen.h>
+#include <Schrift.h>
+#include <Punkt.h>
+#include <Scroll.h>
+#include <Bild.h>
+#include <Text.h>
+
+// Inhalt der VideoBLSpieler Klasse aus VideoBestenliste.h
+// Konstruktor
+VideoBLSpieler::VideoBLSpieler( int sNum, int farbe, Schrift *zS )
+{
+	this->sNum = sNum;
+	this->farbe = farbe;
+	p = 0;
+	nP = 0;
+
+	rahmen = new LRahmen();
+	rahmen->setFarbe( farbe );
+	rahmen->setRamenBreite( 1 );
+	rahmen->setSize( 400, 20 );
+
+	name = new TextFeld();
+	name->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( zS )
+	     name->setSchriftZ( zS->getThis() );
+	name->setSchriftFarbe( farbe );
+	name->setSchriftSize( 12 );
+	name->setSize( 100, 20 );
+	name->setPosition( 0, 0 );
+	name->setText( "" );
+
+	punkte = new TextFeld();
+	punkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( zS )
+	    punkte->setSchriftZ( zS->getThis() );
+	punkte->setSchriftFarbe( farbe );
+	punkte->setSchriftSize( 12 );
+	punkte->setSize( 100, 20 );
+	punkte->setPosition( 100, 0 );
+	punkte->setText( "" );
+
+	neuPunkte = new TextFeld();
+	neuPunkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( zS )
+	    neuPunkte->setSchriftZ( zS->getThis() );
+	neuPunkte->setSchriftFarbe( farbe );
+	neuPunkte->setSchriftSize( 12 );
+	neuPunkte->setSize( 100, 20 );
+	neuPunkte->setPosition( 200, 0 );
+	neuPunkte->setText( "" );
+
+	status = new TextFeld();
+	status->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( zS )
+	    status->setSchriftZ( zS->getThis() );
+	status->setSchriftFarbe( 0xFF00FF00 );
+	status->setSchriftSize( 12 );
+	status->setSize( 100, 20 );
+	status->setPosition( 300, 0 );
+	status->setText( "lebt" );
+
+	rundenNP = new Array< int >();
+	runde = 0;
+
+	ref = 1;
+}
+
+// Destruktor
+VideoBLSpieler::~VideoBLSpieler()
+{
+	rahmen->release();
+	name->release();
+	punkte->release();
+	neuPunkte->release();
+	status->release();
+	rundenNP->release();
+}
+
+// nicht constant
+bool VideoBLSpieler::updateStatus( VideoSpieler *zSpieler )
+{
+	if( sNum != zSpieler->getSpielerNummer() )
+		return 0;
+	if( zSpieler->istAmLeben() )
+	{
+		status->setSchriftFarbe( 0xFF00FF00 );
+		status->setText( "lebt" );
+	}
+	else
+	{
+		status->setSchriftFarbe( 0xFFFF0000 );
+		status->setText( "tot" );
+	}
+	name->setText( zSpieler->zName()->getText() );
+	return 1;
+}
+
+void VideoBLSpieler::setPunkte( int p )
+{
+	this->p = p;
+}
+
+void VideoBLSpieler::addPunkt( bool plus )
+{
+	if( plus )
+		nP++;
+	else
+		nP--;
+}
+
+void VideoBLSpieler::updatePunkte( bool vorwärts )
+{
+	if( vorwärts )
+	{
+		p += nP;
+		rundenNP->set( nP, runde );
+		nP = 0;
+		runde++;
+	}
+	else
+	{
+		runde--;
+		nP = rundenNP->get( runde );
+		p -= nP;
+	}
+}
+
+void VideoBLSpieler::render( int y, Bild &zRObj )
+{
+	if( !zRObj.setDrawOptions( 1, y, rahmen->getBreite(), rahmen->getHeight() ) )
+		return;
+	punkte->setText( "" );
+	if( nP == 0 )
+	{
+		neuPunkte->setText( "" );
+		neuPunkte->setSchriftFarbe( 0xFFFFFFFF );
+	}
+	else if( nP > 0 )
+	{
+		neuPunkte->setText( "+" );
+		neuPunkte->setSchriftFarbe( 0xFF00FF00 );
+	}
+	else
+	{
+		neuPunkte->setText( "" );
+		neuPunkte->setSchriftFarbe( 0xFFFF0000 );
+	}
+	punkte->zText()->append( p > 0 ? p : 0 );
+	neuPunkte->zText()->append( nP );
+	rahmen->render( zRObj );
+	name->render( zRObj );
+	punkte->render( zRObj );
+	neuPunkte->render( zRObj );
+	status->render( zRObj );
+	zRObj.releaseDrawOptions();
+}
+
+// constant
+int VideoBLSpieler::getSpielerNummer() const
+{
+	return sNum;
+}
+
+int VideoBLSpieler::getPunkte() const
+{
+	return p + nP;
+}
+
+// Reference Counting
+VideoBLSpieler *VideoBLSpieler::getThis()
+{
+	ref++;
+	return this;
+}
+
+VideoBLSpieler *VideoBLSpieler::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+// Inhalt der VideoBLTeam Klasse aus VideoBestenliste.h
+// Konstruktor
+VideoBLTeam::VideoBLTeam( int id, int farbe, Schrift *s, char *n )
+{
+	teamId = id;
+	spielerAnzahl = 0;
+	p = 0;
+	mP = 0;
+	nP = 0;
+	this->farbe = farbe;
+	schrift = s;
+
+	rahmen = new LRahmen();
+	rahmen->setFarbe( farbe );
+	rahmen->setRamenBreite( 1 );
+
+	spieler = new RCArray< VideoBLSpieler >();
+
+	name = new TextFeld();
+	name->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( s )
+	    name->setSchriftZ( s->getThis() );
+	name->setSchriftFarbe( farbe );
+	name->setSchriftSize( 12 );
+	name->setSize( 100, 20 );
+	name->setPosition( 0, 0 );
+	name->setText( n );
+
+	punkte = new TextFeld();
+	punkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( s )
+	    punkte->setSchriftZ( s->getThis() );
+	punkte->setSchriftFarbe( farbe );
+	punkte->setSchriftSize( 12 );
+	punkte->setSize( 100, 20 );
+	punkte->setPosition( 100, 0 );
+	punkte->setText( "" );
+
+	neuPunkte = new TextFeld();
+	neuPunkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( s )
+	    neuPunkte->setSchriftZ( s->getThis() );
+	neuPunkte->setSchriftFarbe( farbe );
+	neuPunkte->setSchriftSize( 12 );
+	neuPunkte->setSize( 100, 20 );
+	neuPunkte->setPosition( 200, 0 );
+	neuPunkte->setText( "" );
+
+	status = new TextFeld();
+	status->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( s )
+	    status->setSchriftZ( s->getThis() );
+	status->setSchriftFarbe( 0xFF00FF00 );
+	status->setSchriftSize( 12 );
+	status->setSize( 100, 20 );
+	status->setPosition( 300, 0 );
+	status->setText( "lebt" );
+
+	rundenNP = new Array< int >();
+	runde = 0;
+
+	ref = 1;
+}
+
+// Destruktor
+VideoBLTeam::~VideoBLTeam()
+{
+	if( schrift )
+	    schrift->release();
+	rahmen->release();
+	spieler->release();
+	name->release();
+	punkte->release();
+	neuPunkte->release();
+	status->release();
+	rundenNP->release();
+}
+
+// nicht constant
+bool VideoBLTeam::addSpieler( VideoSpieler *zSpieler )
+{
+	bool gefunden = 0;
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( spieler->z( i )->getSpielerNummer() == zSpieler->getSpielerNummer() )
+		{
+			gefunden = 1;
+			break;
+		}
+	}
+	if( gefunden )
+		return 0;
+	VideoBLSpieler *tmp = new VideoBLSpieler( zSpieler->getSpielerNummer(), zSpieler->getFarbe(), schrift );
+	spieler->set( tmp, spielerAnzahl );
+	spielerAnzahl++;
+	return 1;
+}
+
+bool VideoBLTeam::updateSpielerStatus( VideoSpieler *zSpieler )
+{
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( spieler->z( i )->getSpielerNummer() == zSpieler->getSpielerNummer() )
+		{
+			spieler->z( i )->updateStatus( zSpieler );
+			return 1;
+		}
+	}
+	return 0;
+}
+
+void VideoBLTeam::setStatus( const char *txt, int f )
+{
+	status->setText( txt );
+	status->setSchriftFarbe( f );
+}
+
+void VideoBLTeam::setPunkte( int p )
+{
+	this->p = p;
+}
+
+void VideoBLTeam::setMaxPunkte( int mP )
+{
+	this->mP = mP;
+}
+
+bool VideoBLTeam::setSpielerPunkte( int sNum, int p )
+{
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( spieler->z( i )->getSpielerNummer() == sNum )
+		{
+			spieler->z( i )->setPunkte( p );
+			return 1;
+		}
+	}
+	return 0;
+}
+
+void VideoBLTeam::addPunkt( bool plus )
+{
+	if( plus )
+		nP++;
+	else
+		nP--;
+}
+
+bool VideoBLTeam::addPunkt( int sNum, bool plus )
+{
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( spieler->z( i )->getSpielerNummer() == sNum )
+		{
+			spieler->z( i )->addPunkt( plus );
+			return 1;
+		}
+	}
+	return 0;
+}
+
+void VideoBLTeam::updatePunkte( bool vorwärts )
+{
+	if( vorwärts )
+	{
+		p += nP;
+		rundenNP->set( nP, runde );
+		nP = 0;
+		runde++;
+	}
+	else
+	{
+		runde--;
+		nP = rundenNP->get( runde );
+		p -= nP;
+	}
+	for( int i = 0; i < spielerAnzahl; i++ )
+		spieler->z( i )->updatePunkte( vorwärts );
+}
+
+void VideoBLTeam::render( int y, Bild &zRObj )
+{
+	rahmen->setSize( 402, 21 + 20 * spielerAnzahl );
+	if( !zRObj.setDrawOptions( 1, y, rahmen->getBreite(), rahmen->getHeight() ) )
+		return;
+	punkte->setText( "" );
+	if( nP == 0 )
+	{
+		neuPunkte->setText( "" );
+		neuPunkte->setSchriftFarbe( 0xFFFFFFFF );
+	}
+	else if( nP > 0 )
+	{
+		neuPunkte->setText( "+" );
+		neuPunkte->setSchriftFarbe( 0xFF00FF00 );
+	}
+	else
+	{
+		neuPunkte->setText( "" );
+		neuPunkte->setSchriftFarbe( 0xFFFF0000 );
+	}
+	punkte->zText()->append( p > 0 ? p : 0 );
+	punkte->zText()->append( "/" );
+	punkte->zText()->append( mP );
+	neuPunkte->zText()->append( nP );
+	rahmen->render( zRObj );
+	name->render( zRObj );
+	punkte->render( zRObj );
+	neuPunkte->render( zRObj );
+	status->render( zRObj );
+	Array< bool > *gemahlt = new Array< bool >();
+	for( int i = 0; i < spielerAnzahl; i++ )
+		gemahlt->set( 0, i );
+	int min = -1;
+	int tmp = -1;
+	for( int h = 0; h < spielerAnzahl; h++ )
+	{
+		min = -1;
+		tmp = -1;
+		for( int i = 0; i < spielerAnzahl; i++ )
+		{
+			if( !spieler->z( i ) )
+				continue;
+			if( gemahlt->hat( i ) && gemahlt->get( i ) )
+				continue;
+			int p = spieler->z( i )->getPunkte();
+			if( p > min )
+			{
+				min = p;
+				tmp = i;
+			}
+		}
+		if( tmp >= 0 )
+		{
+			gemahlt->set( 1, tmp );
+			spieler->z( tmp )->render( 20 + 20 * h, zRObj );
+		}
+		else
+			break;
+	}
+	gemahlt->release();
+	zRObj.releaseDrawOptions();
+}
+
+// constant
+int VideoBLTeam::getSpielerAnzahl() const
+{
+	return spielerAnzahl;
+}
+
+int VideoBLTeam::getPunkte() const
+{
+	return ( p + nP ) < 0 ? 0 : ( p + nP );
+}
+
+int VideoBLTeam::getHeight() const
+{
+	return 21 + spielerAnzahl * 20;
+}
+
+bool VideoBLTeam::hatGewonnen() const
+{
+	return p + nP >= mP;
+}
+
+int VideoBLTeam::getSpielerPunkte( int sNum ) const
+{
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( spieler->z( i )->getSpielerNummer() == sNum )
+			return spieler->z( i )->getPunkte();
+	}
+	return 0;
+}
+
+// Reference Counting
+VideoBLTeam *VideoBLTeam::getThis()
+{
+	ref++;
+	return this;
+}
+
+VideoBLTeam *VideoBLTeam::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+// Inhalt der VideoBestenliste Klasse aus VideoBestenliste.h
+// Konstruktor
+VideoBestenliste::VideoBestenliste( Schrift *s )
+{
+	rahmen = new LRahmen();
+	rahmen->setRamenBreite( 1 );
+	rahmen->setFarbe( 0xFFFFFFFF );
+	rahmen->setSize( 420, 200 );
+
+	teams = new RCArray< VideoBLTeam >();
+
+	name = new TextFeld();
+	name->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( s )
+	    name->setSchriftZ( s->getThis() );
+	name->setSchriftFarbe( 0xFFFFFFFF );
+	name->setSchriftSize( 12 );
+	name->setText( "Name" );
+	name->setSize( 100, 20 );
+	name->setPosition( 0, 0 );
+
+	punkte = new TextFeld();
+	punkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( s )
+	    punkte->setSchriftZ( s->getThis() );
+	punkte->setSchriftFarbe( 0xFFFFFFFF );
+	punkte->setSchriftSize( 12 );
+	punkte->setText( "Punkte" );
+	punkte->setSize( 100, 20 );
+	punkte->setPosition( 100, 0 );
+
+	neuPunkte = new TextFeld();
+	neuPunkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( s )
+	    neuPunkte->setSchriftZ( s->getThis() );
+	neuPunkte->setSchriftFarbe( 0xFFFFFFFF );
+	neuPunkte->setSchriftSize( 12 );
+	neuPunkte->setText( "+Punkte" );
+	neuPunkte->setSize( 100, 20 );
+	neuPunkte->setPosition( 200, 0 );
+
+	status = new TextFeld();
+	status->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	if( s )
+	    status->setSchriftZ( s->getThis() );
+	status->setSchriftFarbe( 0xFFFFFFFF );
+	status->setSchriftSize( 12 );
+	status->setText( "Status" );
+	status->setSize( 100, 20 );
+	status->setPosition( 300, 0 );
+
+	scroll = new VScrollBar();
+	scroll->setKlickScroll( 7 );
+
+	schrift = s;
+	update = 0;
+	teamAnzahl = 0;
+	ref = 1;
+}
+
+// Destruktor
+VideoBestenliste::~VideoBestenliste()
+{
+	rahmen->release();
+	teams->release();
+	name->release();
+	punkte->release();
+	neuPunkte->release();
+	status->release();
+	scroll->release();
+	if( schrift )
+	    schrift->release();
+}
+
+// nicht constant
+void VideoBestenliste::setTeamAnzahl( int anz )
+{
+	teamAnzahl = anz;
+}
+
+void VideoBestenliste::setTeamStatus( int team, const char *txt, int f )
+{
+	if( teams->z( team ) )
+		teams->z( team )->setStatus( txt, f );
+}
+
+void VideoBestenliste::addSpieler( VideoSpieler *zSpieler )
+{
+	int team = zSpieler->getTeam();
+	if( team < 0 )
+		return;
+	if( !teams->z( team ) )
+		teams->set( new VideoBLTeam( team, zSpieler->getTeamFarbe(), schrift ? schrift->getThis() : 0, zSpieler->zTeamName()->getText() ), team );
+	teams->z( team )->addSpieler( zSpieler );
+}
+
+void VideoBestenliste::updateSpielerStatus( VideoSpieler *zSpieler )
+{
+	if( teams->z( zSpieler->getTeam() ) )
+		teams->z( zSpieler->getTeam() )->updateSpielerStatus( zSpieler );
+}
+
+void VideoBestenliste::setTeamPunkte( int teamId, int punkte )
+{
+	if( teams->z( teamId ) )
+		teams->z( teamId )->setPunkte( punkte );
+}
+
+void VideoBestenliste::setTeamMaxPunkte( int teamId, int mPunkte )
+{
+	if( teams->z( teamId ) )
+		teams->z( teamId )->setMaxPunkte( mPunkte );
+}
+
+void VideoBestenliste::setSpielerPunkte( int teamNum, int sNum, int punkte )
+{
+	if( teams->z( teamNum ) )
+		teams->z( teamNum )->setSpielerPunkte( sNum, punkte );
+}
+
+void VideoBestenliste::addPunkt( int tNum, bool plus )
+{
+	if( teams->z( tNum ) )
+		teams->z( tNum )->addPunkt( plus );
+}
+
+void VideoBestenliste::addPunkt( int tNum, int sNum, bool plus )
+{
+	if( teams->z( tNum ) )
+		teams->z( tNum )->addPunkt( sNum, plus );
+}
+
+void VideoBestenliste::updatePunkte( bool vorwärts )
+{
+	for( int i = 0; i < teamAnzahl; i++ )
+	{
+		if( teams->z( i ) )
+			teams->z( i )->updatePunkte( vorwärts );
+	}
+}
+
+void VideoBestenliste::doMausEreignis( MausEreignis &me )
+{
+	scroll->doMausMessage( rahmen->getBreite() - 15, 1, 15, rahmen->getHeight() - 2, me );
+}
+
+void VideoBestenliste::render( Bild &zRObj )
+{
+	if( !zRObj.setDrawOptions( 0, 0, rahmen->getBreite(), rahmen->getHeight() ) )
+		return;
+	rahmen->render( zRObj );
+	zRObj.addScrollOffset( 0, scroll->getScroll() );
+	name->render( zRObj );
+	punkte->render( zRObj );
+	neuPunkte->render( zRObj );
+	status->render( zRObj );
+	int yOff = 20;
+	Array< bool > *gemahlt = new Array< bool >();
+	for( int i = 0; i < teamAnzahl; i++ )
+		gemahlt->set( 0, i );
+	int min = -1;
+	int tmp = -1;
+	for( int h = 0; h < teamAnzahl; h++ )
+	{
+		min = -1;
+		tmp = -1;
+		for( int i = 0; i < teamAnzahl; i++ )
+		{
+			if( !teams->z( i ) )
+				continue;
+			if( gemahlt->hat( i ) && gemahlt->get( i ) )
+				continue;
+			int p = teams->z( i )->getPunkte();
+			if( p > min )
+			{
+				min = p;
+				tmp = i;
+			}
+		}
+		if( tmp >= 0 )
+		{
+			gemahlt->set( 1, tmp );
+			teams->z( tmp )->render( yOff, zRObj );
+			yOff += teams->z( tmp )->getHeight();
+		}
+		else
+			break;
+	}
+	gemahlt->release();
+	zRObj.addScrollOffset( 0, -scroll->getScroll() );
+	scroll->update( yOff, rahmen->getHeight() - 2 );
+	scroll->render( rahmen->getBreite() - 16, 1, 15, rahmen->getHeight() - 2, zRObj );
+	zRObj.releaseDrawOptions();
+}
+
+// constant
+int VideoBestenliste::getTeamAnzahl() const
+{
+	return teamAnzahl;
+}
+
+bool VideoBestenliste::teamExistiert( int team ) const
+{
+	return teams->z( team ) != 0;
+}
+
+int VideoBestenliste::getTeamPunkte( int team ) const
+{
+	return teams->z( team ) ? teams->z( team )->getPunkte() : 0;
+}
+
+bool VideoBestenliste::hatTeamGewonnen( int team ) const
+{
+	if( !teams->z( team ) )
+		return 0;
+	return teams->z( team )->hatGewonnen();
+}
+
+int VideoBestenliste::getSpielerPunkte( int team, int sNum ) const
+{
+	if( !teams->z( team ) )
+		return 0;
+	return teams->z( team )->getSpielerPunkte( sNum );
+}
+
+// Reference Counting
+VideoBestenliste *VideoBestenliste::getThis()
+{
+	ref++;
+	return this;
+}
+
+VideoBestenliste *VideoBestenliste::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 137 - 0
Linie/Aufzeichnung/Bestenliste/VideoBestenliste.h

@@ -0,0 +1,137 @@
+#ifndef VideoBestenliste_H
+#define VideoBestenliste_H
+
+#include <TextFeld.h>
+#include <Array.h>
+
+using namespace Framework;
+
+class VideoSpieler; // VideoSpieler.h
+
+class VideoBLSpieler
+{
+private:
+	int sNum;
+	int farbe;
+	int p;
+	int nP;
+	LRahmen *rahmen;
+	TextFeld *name;
+	TextFeld *punkte;
+	TextFeld *neuPunkte;
+	TextFeld *status;
+	Array< int > *rundenNP;
+	int runde;
+	int ref;
+
+public:
+	// Konstruktor
+	VideoBLSpieler( int sNum, int farbe, Schrift *zS );
+	// Destruktor
+	~VideoBLSpieler();
+	// nicht constant
+	bool updateStatus( VideoSpieler *zSpieler );
+	void setPunkte( int p );
+	void addPunkt( bool plus );
+	void updatePunkte( bool vorwärts );
+	void render( int y, Bild &zRObj );
+	// constant
+	int getSpielerNummer() const;
+	int getPunkte() const;
+	// Reference Counting
+	VideoBLSpieler *getThis();
+	VideoBLSpieler *release();
+};
+
+class VideoBLTeam
+{
+private:
+	int teamId;
+	int spielerAnzahl;
+	int p;
+	int mP;
+	int nP;
+	int farbe;
+	Schrift *schrift;
+	LRahmen *rahmen;
+	RCArray< VideoBLSpieler > *spieler;
+	TextFeld *name;
+	TextFeld *punkte;
+	TextFeld *neuPunkte;
+	TextFeld *status;
+	Array< int > *rundenNP;
+	int runde;
+	int ref;
+
+public:
+	// Konstruktor
+	VideoBLTeam( int id, int farbe, Schrift *s, char *n );
+	// Destruktor
+	~VideoBLTeam();
+	// nicht constant
+	bool addSpieler( VideoSpieler *zSpieler );
+	bool updateSpielerStatus( VideoSpieler *zSpieler );
+	void setStatus( const char *txt, int f );
+	void setPunkte( int p );
+	void setMaxPunkte( int mP );
+	bool setSpielerPunkte( int sNum, int p );
+	void addPunkt( bool plus );
+	bool addPunkt( int sNum, bool plus );
+	void updatePunkte( bool vorwärts );
+	void render( int y, Bild &zRObj );
+	// constant
+	int getSpielerAnzahl() const;
+	int getPunkte() const;
+	int getHeight() const;
+	bool hatGewonnen() const;
+	int getSpielerPunkte( int sNum ) const;
+	// Reference Counting
+	VideoBLTeam *getThis();
+	VideoBLTeam *release();
+};
+
+class VideoBestenliste
+{
+private:
+	LRahmen *rahmen;
+	RCArray< VideoBLTeam > *teams;
+	TextFeld *name;
+	TextFeld *punkte;
+	TextFeld *neuPunkte;
+	TextFeld *status;
+	VScrollBar *scroll;
+	Schrift *schrift;
+	bool update;
+	int teamAnzahl;
+	int ref;
+
+public:
+	// Konstruktor
+	VideoBestenliste( Schrift *s );
+	// Destruktor
+	~VideoBestenliste();
+	// nicht constant
+	void setTeamAnzahl( int anz );
+	void addSpieler( VideoSpieler *zSpieler );
+	void updateSpielerStatus( VideoSpieler *zSpieler );
+	void setTeamStatus( int team, const char *txt, int f );
+	void setTeamPunkte( int teamId, int punkte );
+	void setTeamMaxPunkte( int teamId, int mPunkte );
+	void setSpielerPunkte( int teamNum, int sNum, int punkte );
+	void addPunkt( int tNum, bool plus );
+	void addPunkt( int tNum, int sNum, bool plus );
+	void updatePunkte( bool vorwärts = 1 );
+	void doMausEreignis( MausEreignis &me );
+	void render( Bild &zRObj );
+	// constant
+	int getTeamAnzahl() const;
+	bool teamExistiert( int team ) const;
+	int getTeamPunkte( int team ) const;
+	bool hatTeamGewonnen( int team ) const;
+	int getSpielerPunkte( int team, int sNum ) const;
+	// Reference Counting
+	VideoBestenliste *getThis();
+	VideoBestenliste *release();
+};
+
+#endif

+ 109 - 0
Linie/Aufzeichnung/Chat/VideoChat.cpp

@@ -0,0 +1,109 @@
+#include "VideoChat.h"
+#include <Rahmen.h>
+#include <MausEreignis.h>
+#include <TastaturEreignis.h>
+#include <Text.h>
+#include <Schrift.h>
+#include <Punkt.h>
+#include <Bild.h>
+
+// Inhalt der VideoChat Klasse aus VideoChat.h
+// Konstruktor
+VideoChat::VideoChat( Schrift *zSchrift )
+{
+	verlauf = new TextFeld();
+	verlauf->setStyle( TextFeld::Style::TextGebiet & ~TextFeld::Style::Erlaubt );
+	verlauf->setLinienRahmenFarbe( 0xFF909090 );
+	verlauf->setLinienRahmenBreite( 1 );
+	verlauf->setText( "" );
+	verlauf->setSchriftFarbe( 0xFFFFFFFF );
+	verlauf->setSchriftSize( 12 );
+	verlauf->setPosition( 20, BildschirmGröße().y - 210 );
+	verlauf->setSize( 450, 200 );
+	verlauf->setSchriftZ( zSchrift->getThis() );
+	ref = 1;
+}
+
+// Destruktor
+VideoChat::~VideoChat()
+{
+	verlauf->release();
+}
+
+// nicht constant
+void VideoChat::addNachricht( char *nachricht )
+{
+	verlauf->addZeile( nachricht );
+	verlauf->updateVScroll();
+}
+
+void VideoChat::addNachricht( char *nachricht, int farbe )
+{
+	verlauf->zText()->appendColor( farbe );
+	verlauf->addZeile( nachricht );
+	verlauf->zText()->appendColor( 0xFFFFFFFF );
+	verlauf->updateVScroll();
+}
+
+void VideoChat::removeNachricht( char *nachricht )
+{
+	Text *txt = new Text( nachricht );
+	txt->append( "\n" );
+	Schrift *schrift = verlauf->zSchrift();
+	if( schrift )
+	{
+		schrift->lock();
+		schrift->textFormatieren( txt, verlauf->getBreite() - 15 - 2, 12 );
+		schrift->unlock();
+	}
+	int n = txt->anzahlVon( '\n' );
+	int n2 = verlauf->zText()->anzahlVon( '\n' );
+	if( n2 > n )
+		verlauf->zText()->remove( verlauf->zText()->positionVon( '\n', n2 - n - 1 ) + 1 );
+	else
+		verlauf->setText( "" );
+	verlauf->updateVScroll();
+}
+
+void VideoChat::doMausEreignis( MausEreignis &me )
+{
+	bool vera = me.verarbeitet;
+	verlauf->doMausEreignis( me );
+	if( !vera && me.verarbeitet )
+	{
+		verlauf->setLinienRahmenFarbe( 0xFFFFFFFF );
+		verlauf->setVertikalScrollFarbe( 0xFF808080, 0 );
+	}
+	else
+	{
+		verlauf->setLinienRahmenFarbe( 0xFF909090 );
+		verlauf->setVertikalScrollFarbe( 0xFF404040, 0 );
+	}
+}
+
+void VideoChat::tick( double z )
+{
+	verlauf->tick( z );
+}
+
+void VideoChat::render( Bild &zRObj )
+{
+	verlauf->render( zRObj );
+}
+
+// constant
+
+// Reference Counting
+VideoChat *VideoChat::getThis()
+{
+	ref++;
+	return this;
+}
+
+VideoChat *VideoChat::relese()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 33 - 0
Linie/Aufzeichnung/Chat/VideoChat.h

@@ -0,0 +1,33 @@
+#ifndef VideoChat_H
+#define VideoChat_H
+
+#include <TextFeld.h>
+
+using namespace Framework;
+
+class VideoChat
+{
+private:
+	TextFeld *verlauf;
+	int ref;
+
+public:
+	// Konstruktor
+	VideoChat( Schrift *zSchrift );
+	// Destruktor
+	~VideoChat();
+	// nicht constant
+	void addNachricht( char *nachricht );
+	void addNachricht( char *nachricht, int farbe );
+	void removeNachricht( char *nachricht );
+	void doMausEreignis( MausEreignis &me );
+	void tick( double z );
+	void render( Bild &zRObj );
+	// constant
+
+	// Reference Counting
+	VideoChat *getThis();
+	VideoChat *relese();
+};
+
+#endif

+ 72 - 0
Linie/Aufzeichnung/Ende/VideoEnde.cpp

@@ -0,0 +1,72 @@
+#include "VideoEnde.h"
+#include <Bild.h>
+#include <MausEreignis.h>
+#include <Rahmen.h>
+#include <Schrift.h>
+#include <Text.h>
+
+// Inhalt der VideoEnde Klasse aus VideoEnde.h
+// Konstruktor
+VideoEnde::VideoEnde( Schrift *zSchrift )
+{
+	text = new TextFeld();
+	text->setStyle( TextFeld::Style::Text | TextFeld::Style::Center | TextFeld::Style::Rahmen | TextFeld::Style::Hintergrund | TextFeld::Style::HAlpha );
+	text->removeStyle( TextFeld::Style::Sichtbar );
+	text->setSchriftZ( zSchrift->getThis() );
+	text->setText( "" );
+	text->setSchriftFarbe( 0xFFFFFFFF );
+	text->setSize( 220, 70 );
+	text->setLinienRahmenBreite( 2 );
+	text->setLinienRahmenFarbe( 0xFFFFFFFF );
+	text->setHintergrundFarbe( 0xA0000000 );
+	ref = 1;
+}
+
+// Destruktor
+VideoEnde::~VideoEnde()
+{
+	text->release();
+}
+
+// nicht constant
+void VideoEnde::setSichtbar( bool b )
+{
+	text->setStyle( TextFeld::Style::Sichtbar, b );
+}
+
+void VideoEnde::setText( const char *txt )
+{
+	text->zSchrift()->lock();
+	text->zSchrift()->setSchriftSize( 12 );
+	Text t = txt;
+	text->setSize( 10 + text->zSchrift()->getTextBreite( &t ), 10 + text->zSchrift()->getTextHeight( &t ) );
+	text->zSchrift()->unlock();
+	text->setText( txt );
+}
+
+void VideoEnde::render( Bild &zRObj )
+{
+	text->setPosition( zRObj.getBreite() / 2 - text->getBreite() / 2, zRObj.getHeight() / 2 - text->getHeight() / 2 );
+	text->render( zRObj );
+}
+
+// constant
+bool VideoEnde::istSichtbar() const
+{
+	return text->hatStyle( TextFeld::Style::Sichtbar );
+}
+
+// Reference Counting
+VideoEnde *VideoEnde::getThis()
+{
+	ref++;
+	return this;
+}
+
+VideoEnde *VideoEnde::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 30 - 0
Linie/Aufzeichnung/Ende/VideoEnde.h

@@ -0,0 +1,30 @@
+#ifndef VideoEnde_H
+#define VideoEnde_H
+
+#include <TextFeld.h>
+
+using namespace Framework;
+
+class VideoEnde
+{
+private:
+	TextFeld *text;
+	int ref;
+
+public:
+	// Konstruktor
+	VideoEnde( Schrift *zSchrift );
+	// Destruktor
+	~VideoEnde();
+	// nicht constant
+	void setSichtbar( bool b );
+	void setText( const char *txt );
+	void render( Bild &zRObj );
+	// constant
+	bool istSichtbar() const;
+	// Reference Counting
+	VideoEnde *getThis();
+	VideoEnde *release();
+};
+
+#endif

+ 145 - 0
Linie/Aufzeichnung/Kamera/VideoKamera.cpp

@@ -0,0 +1,145 @@
+#include "VideoKamera.h"
+#include "..\Karte\VideoKarte.h"
+#include <Punkt.h>
+#include <Rahmen.h>
+
+// Inhalt der VideoKamera Klasse aus VideoKamera.h
+// Konstruktor
+VideoKamera::VideoKamera()
+{
+	pos = Punkt( 0, 0 );
+	gr = Punkt( 0, 0 );
+	runde = 0;
+	rundePos = new Array< Punkt >();
+	rundeGr = new Array< Punkt >();
+	rGr = Punkt( 0, 0 );
+	rahmen = new LRahmen();
+	rahmen->setFarbe( 0xFF505050 );
+	rahmen->setRamenBreite( 1 );
+	ref = 1;
+}
+
+// Destruktor
+VideoKamera::~VideoKamera()
+{
+	rundePos->release();
+	rundeGr->release();
+	rahmen->release();
+}
+
+// nicht constant
+void VideoKamera::setPosition( int x, int y )
+{
+	pos.x = x;
+	pos.y = y;
+}
+
+void VideoKamera::addPosition( int x, int y, VideoKarte *zMap )
+{
+	pos.x += x;
+	pos.y += y;
+	if( pos.x < 0 )
+		pos.x = 0;
+	if( pos.y < 0 )
+		pos.y = 0;
+	if( pos.x > zMap->getBreite() )
+		pos.x = zMap->getBreite();
+	if( pos.y > zMap->getHeight() )
+		pos.y = zMap->getHeight();
+}
+
+void VideoKamera::setSize( int br, int hö )
+{
+	gr.x = br;
+	gr.y = hö;
+}
+
+void VideoKamera::render( Bild &zRObj )
+{
+	rGr = zRObj.getSize();
+	rahmen->setPosition( getRX( getLinks() ), getRY( getOben() ) );
+	rahmen->setSize( gr );
+	rahmen->render( zRObj );
+}
+
+void VideoKamera::nextRunde( bool vorwärts )
+{
+	if( vorwärts )
+	{
+		rundePos->set( pos, runde );
+		rundeGr->set( gr, runde );
+		runde++;
+	}
+	else
+	{
+		runde--;
+		pos = rundePos->hat( runde ) ? rundePos->get( runde ) : Punkt( 0, 0 );
+		gr = rundeGr->hat( runde ) ? rundeGr->get( runde ) : Punkt( 0, 0 );
+	}
+}
+
+// constant
+int VideoKamera::getLinks() const
+{
+	return pos.x - (int)( gr.x / 2.0 + 0.5 );
+}
+
+int VideoKamera::getOben() const
+{
+	return pos.y - gr.y / 2;
+}
+
+int VideoKamera::getRechts() const
+{
+	return pos.x + gr.x / 2;
+}
+
+int VideoKamera::getUnten() const
+{
+	return pos.y + gr.y / 2;
+}
+
+bool VideoKamera::istSichtbar( int x, int y ) const
+{
+	return ( x >= getLinks() && x < getRechts() && y >= getOben() && y < getUnten() );
+}
+
+bool VideoKamera::istMausIn( int x, int y ) const
+{
+	return ( x >= ( rGr.x / 2 - gr.x / 2 ) && x < ( rGr.x / 2 + gr.x / 2 ) && y >= ( rGr.y / 2 - gr.y / 2 ) && y < ( rGr.y / 2 + gr.y / 2 ) );
+}
+
+int VideoKamera::getRX( int mapX ) const
+{
+	return rGr.x / 2 - ( pos.x - mapX );
+}
+
+int VideoKamera::getRY( int mapY ) const
+{
+	return rGr.y / 2 - ( pos.y - mapY );
+}
+
+int VideoKamera::getX() const
+{
+	return pos.x;
+}
+
+int VideoKamera::getY() const
+{
+	return pos.y;
+}
+
+// Reference Counting
+VideoKamera *VideoKamera::getThis()
+{
+	ref++;
+	return this;
+}
+
+VideoKamera *VideoKamera::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 45 - 0
Linie/Aufzeichnung/Kamera/VideoKamera.h

@@ -0,0 +1,45 @@
+#ifndef VideoKamera_H
+#define VideoKamera_H
+
+#include "../Karte/VideoKarte.h"
+
+class VideoKamera
+{
+private:
+	Punkt pos;
+	Punkt gr;
+	int runde;
+	Array< Punkt > *rundePos;
+	Array< Punkt > *rundeGr;
+	Punkt rGr;
+	LRahmen *rahmen;
+	int ref;
+
+public:
+	// Konstruktor
+	VideoKamera();
+	// Destruktor
+	~VideoKamera();
+	// nicht constant
+	void setPosition( int x, int y );
+	void addPosition( int x, int y, VideoKarte *zMap );
+	void setSize( int br, int hö );
+	void render( Bild &zRObj );
+	void nextRunde( bool vorwärts );
+	// constant
+	int getLinks() const;
+	int getOben() const;
+	int getRechts() const;
+	int getUnten() const;
+	bool istSichtbar( int x, int y ) const;
+	bool istMausIn( int x, int y ) const;
+	int getRX( int mapX ) const;
+	int getRY( int mapY ) const;
+	int getX() const;
+	int getY() const;
+	// Reference Counting
+	VideoKamera *release();
+	VideoKamera *getThis();
+};
+
+#endif

+ 89 - 0
Linie/Aufzeichnung/Karte/VideoKarte.cpp

@@ -0,0 +1,89 @@
+#include "VideoKarte.h"
+#include <Rahmen.h>
+#include <Punkt.h>
+#include "..\Kamera\VideoKamera.h"
+
+// Inhalt der VideoKarte Klasse aus VideoKarte.h
+// Konstruktor
+VideoKarte::VideoKarte()
+{
+	map = new RCArray< Bild >();
+	rahmen = new RCArray< LRahmen >();
+	runde = 0;
+	map->set( new Bild(), runde );
+	rahmen->set( new LRahmen(), runde );
+	rahmen->z( runde )->setFarbe( 0xFFFFFFFF );
+	rahmen->z( runde )->setRamenBreite( 2 );
+	ref = 1;
+}
+
+// Destruktor
+VideoKarte::~VideoKarte()
+{
+	map->release();
+	rahmen->release();
+}
+
+// nicht constant
+void VideoKarte::setSize( int br, int hö )
+{
+	map->z( runde )->neuBild( br, hö, 0 );
+	rahmen->z( runde )->setSize( br, hö );
+}
+
+void VideoKarte::nextRunde( bool vorwärts )
+{
+	if( vorwärts )
+	{
+		runde++;
+		map->set( new Bild(), runde );
+		rahmen->set( new LRahmen(), runde );
+		rahmen->z( runde )->setFarbe( 0xFFFFFFFF );
+		rahmen->z( runde )->setRamenBreite( 2 );
+	}
+	else
+		runde--;
+}
+
+void VideoKarte::render( VideoKamera *zKam, Bild &zRObj )
+{
+	rahmen->z( runde )->setPosition( zKam->getRX( 0 ), zKam->getRY( 0 ) );
+	zRObj.drawBild( rahmen->z( runde )->getX(), rahmen->z( runde )->getY(), map->z( runde )->getBreite(), map->z( runde )->getHeight(), *map->z( runde ) );
+	rahmen->z( runde )->render( zRObj );
+}
+
+// constant
+int VideoKarte::getBreite() const
+{
+	return map->z( runde )->getBreite();
+}
+
+int VideoKarte::getHeight() const
+{
+	return map->z( runde )->getHeight();
+}
+
+Bild *VideoKarte::zMap() const
+{
+	return ( map->z( runde )->getBreite() != 0 && map->z( runde )->getHeight() != 0 ) ? map->z( runde ) : 0;
+}
+
+Bild *VideoKarte::zMap( int runde ) const
+{
+	return ( map->z( runde )->getBreite() != 0 && map->z( runde )->getHeight() != 0 ) ? map->z( runde ) : 0;
+}
+
+// Reference Counting
+VideoKarte *VideoKarte::getThis()
+{
+	ref++;
+	return this;
+}
+
+VideoKarte *VideoKarte::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 37 - 0
Linie/Aufzeichnung/Karte/VideoKarte.h

@@ -0,0 +1,37 @@
+#ifndef VideoKarte_H
+#define VideoKarte_H
+
+#include <Bild.h>
+
+using namespace Framework;
+
+class VideoKamera;
+
+class VideoKarte
+{
+private:
+	RCArray< LRahmen > *rahmen;
+	RCArray< Bild > *map;
+	int runde;
+	int ref;
+
+public:
+	// Konstruktor
+	VideoKarte();
+	// Destruktor
+	~VideoKarte();
+	// nicht constant
+	void setSize( int br, int hö );
+	void nextRunde( bool vorwärts );
+	void render( VideoKamera *zKam, Bild &zRObj );
+	// constant
+	int getBreite() const;
+	int getHeight() const;
+	Bild *zMap() const;
+	Bild *zMap( int runde ) const;
+	// Reference Counting
+	VideoKarte *getThis();
+	VideoKarte *release();
+};
+
+#endif

+ 366 - 0
Linie/Aufzeichnung/Nachricht/VideoNachricht.cpp

@@ -0,0 +1,366 @@
+#include "VideoNachricht.h"
+
+// Inhalt der RundeNachricht Klasse aus VideoNachricht.h
+// Konstruktor
+RundeNachricht::RundeNachricht( Datei *d, int spielerAnzahl )
+{
+	index = 0;
+	maxNachricht = 0;
+	nachrichten = new Array< VideoMSG* >();
+	vDat = d;
+	rvd = new RundeVideoDaten();
+	rsvd = new Array< RundeSpielerVideoDaten* >();
+	aktiv = 1;
+	ref = 1;
+	vDat->lese( (char*)&rvd->mapBreite, 4 );
+	vDat->lese( (char*)&rvd->mapHöhe, 4 );
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		RundeSpielerVideoDaten *svd = new RundeSpielerVideoDaten();
+		vDat->lese( (char*)&svd->wendigkeit, 8 );
+		vDat->lese( (char*)&svd->xPos, 8 );
+		vDat->lese( (char*)&svd->yPos, 8 );
+		vDat->lese( (char*)&svd->xSpeed, 8 );
+		vDat->lese( (char*)&svd->ySpeed, 8 );
+		rsvd->set( svd, i );
+	}
+}
+
+// Destruktor
+RundeNachricht::~RundeNachricht()
+{
+	for( int i = 0; i < maxNachricht; i++ )
+	{
+		VideoMSG *tmp = nachrichten->get( i );
+		if( !tmp->typ )
+			delete (VideoMSG*)tmp;
+		else
+		{
+			if( ( (VideoAktionMSG*)tmp )->aktion == 4 )
+				delete (VideoChatMSG*)tmp;
+			else if( ( (VideoAktionMSG*)tmp )->aktion == 5 )
+				delete (VideoLinieMSG*)tmp;
+			else
+				delete (VideoAktionMSG*)tmp;
+		}
+	}
+	nachrichten->release();
+	vDat->release();
+	delete rvd;
+	int anz = rsvd->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+		delete rsvd->get( i );
+	rsvd->release();
+}
+
+// nicht constant
+VideoMSG *RundeNachricht::GetNextNachricht()
+{
+	if( index < maxNachricht )
+	{
+		index++;
+		return nachrichten->get( index - 1 );
+	}
+	else if( aktiv )
+	{
+		char typ = 0;
+		vDat->lese( &typ, 1 );
+		if( !typ )
+		{
+			VideoMSG *vtmsg = new VideoMSG();
+			vtmsg->typ = typ;
+			nachrichten->set( vtmsg, index );
+			index++;
+			maxNachricht++;
+			return vtmsg;
+		}
+		else if( typ == 1 )
+		{
+			NachrichtVideoDaten nvd;
+			vDat->lese( (char*)&nvd.spielerNummer, 4 );
+			vDat->lese( (char*)&nvd.län, 2 );
+			char *bytes = new char[ nvd.län ];
+			vDat->lese( bytes, nvd.län );
+			if( bytes[ 0 ] >= 0 && bytes[ 0 ] <= 3 )
+			{
+				VideoAktionMSG *vamsg = new VideoAktionMSG();
+				vamsg->typ = typ;
+				vamsg->spielerNummer = nvd.spielerNummer;
+				vamsg->aktion = bytes[ 0 ];
+				nachrichten->set( vamsg, index );
+				index++;
+				maxNachricht++;
+				delete[] bytes;
+				return vamsg;
+			}
+			if( bytes[ 0 ] == 4 )
+			{
+				VideoChatMSG *vcmsg = new VideoChatMSG();
+				vcmsg->typ = typ;
+				vcmsg->spielerNummer = nvd.spielerNummer;
+				vcmsg->aktion = bytes[ 0 ];
+				vcmsg->län = nvd.län - 1;
+				vcmsg->msg.setText( bytes + 1, vcmsg->län );
+				nachrichten->set( vcmsg, index );
+				index++;
+				maxNachricht++;
+				delete[] bytes;
+				return vcmsg;
+			}
+			if( bytes[ 0 ] == 5 )
+			{
+				VideoLinieMSG *vlmsg = new VideoLinieMSG();
+				vlmsg->typ = typ;
+				vlmsg->spielerNummer = nvd.spielerNummer;
+				vlmsg->aktion = bytes[ 0 ];
+				vlmsg->unterbrechung = *( bytes + 1 );
+				nachrichten->set( vlmsg, index );
+				index++;
+				maxNachricht++;
+				delete[] bytes;
+				return vlmsg;
+			}
+			delete[] bytes;
+		}
+		else
+		{
+			VideoMSG *msg = new VideoMSG();
+			msg->typ = typ;
+			nachrichten->set( msg, index );
+			index++;
+			maxNachricht++;
+			return msg;
+		}
+	}
+	return 0;
+}
+
+VideoMSG *RundeNachricht::GetLastNachricht()
+{
+	if( index == 0 )
+		return 0;
+	index--;
+	return nachrichten->get( index );
+}
+
+void RundeNachricht::setEnde()
+{
+	aktiv = 0;
+}
+
+// constant
+RundeVideoDaten *RundeNachricht::getRVD() const
+{
+	return rvd;
+}
+
+RundeSpielerVideoDaten *RundeNachricht::getRSVD( int index ) const
+{
+	if( !rsvd->hat( index ) )
+		return 0;
+	return rsvd->get( index );
+}
+
+// Reference Counting
+RundeNachricht *RundeNachricht::getThis()
+{
+	ref++;
+	return this;
+}
+
+RundeNachricht *RundeNachricht::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der SpielNachricht Klasse aus VideoNachricht.h
+// Konatruktor
+SpielNachricht::SpielNachricht( int num )
+{
+	runde = 0;
+	maxRunde = 0;
+	teamAnzahl = 0;
+	runden = new RCArray< RundeNachricht >();
+	vDat = new Datei();
+	svd = new SpielVideoDaten();
+	spvd = new Array< SpielerVideoDaten* >();
+	tvd = new Array< TeamVideoDaten* >();
+	error = 0;
+	fehler = new Text();
+	ref = 1;
+	Text pfad( "data/tmp/historie/" );
+	pfad += num;
+	pfad += "/verlauf.ksggl";
+	vDat->setDatei( pfad );
+	if( !vDat->open( Datei::Style::lesen ) )
+	{
+		*fehler = "Die Videodatei '";
+		*fehler += pfad;
+		*fehler += "' konnte nicht geöffnet werden.\nEs existiert eventuell keine Aufzeichnung von diesem Spiel.";
+		error = 1;
+	}
+	Array< int > team;
+	if( !error )
+	{
+		vDat->lese( (char*)&svd->spielerAnzahl, 4 );
+		for( int i = 0; i < svd->spielerAnzahl; i++ )
+		{
+			SpielerVideoDaten *svd = new SpielerVideoDaten();
+			vDat->lese( (char*)&svd->index, 4 );
+			vDat->lese( (char*)&svd->spielerNummer, 4 );
+			vDat->lese( (char*)&svd->kamBreite, 4 );
+			vDat->lese( (char*)&svd->kamHöhe, 4 );
+			vDat->lese( (char*)&svd->team, 4 );
+			vDat->lese( (char*)&svd->spielerFarbe, 4 );
+			vDat->lese( (char*)&svd->teamFarbe, 4 );
+			char län = 0;
+			vDat->lese( &län, 1 );
+			char *n = new char[ län + 1 ];
+			n[ län ] = 0;
+			if( län )
+				vDat->lese( n, län );
+			svd->name.setText( n );
+			delete[] n;
+			vDat->lese( &län, 1 );
+			n = new char[ län + 1 ];
+			n[ län ] = 0;
+			if( län )
+				vDat->lese( n, län );
+			svd->teamName.setText( n );
+			delete[] n;
+			spvd->set( svd, svd->index );
+			if( team.getWertIndex( svd->team ) < 0 )
+			{
+				team.set( svd->team, teamAnzahl );
+				teamAnzahl++;
+			}
+		}
+		for( int i = 0; i < teamAnzahl; i++ )
+		{
+			TeamVideoDaten *t = new TeamVideoDaten();
+			vDat->lese( (char*)&t->teamNummer, 4 );
+			vDat->lese( (char*)&t->maxPunkte, 4 );
+			vDat->lese( (char*)&t->punkte, 4 );
+			tvd->set( t, i );
+		}
+		RundeNachricht *r = new RundeNachricht( vDat->getThis(), svd->spielerAnzahl );
+		runden->set( r, runde );
+	}
+}
+
+// Destruktor
+SpielNachricht::~SpielNachricht()
+{
+	runden->release();
+	vDat->close();
+	vDat->release();
+	for( int i = 0; i < svd->spielerAnzahl; i++ )
+		delete spvd->get( i );
+	delete svd;
+	spvd->release();
+	for( int i = 0; i < teamAnzahl; i++ )
+		delete tvd->get( i );
+	tvd->release();
+	fehler->release();
+}
+
+// nicht constant
+VideoMSG *SpielNachricht::GetNextNachricht()
+{
+	return runden->z( runde )->GetNextNachricht();
+}
+
+VideoMSG *SpielNachricht::GetLastNachricht()
+{
+	return runden->z( runde )->GetLastNachricht();
+}
+
+int SpielNachricht::setRundenEnde( bool vorwärts )
+{
+	if( vorwärts )
+	{
+		if( runde < maxRunde )
+			runde++;
+		else
+		{
+			runden->z( runde )->setEnde();
+			runde++;
+			maxRunde++;
+			RundeNachricht *tmp = new RundeNachricht( vDat->getThis(), svd->spielerAnzahl );
+			runden->set( tmp, runde );
+		}
+	}
+	else
+		runde--;
+	if( runde < 0 )
+	{
+		runde = 0;
+		return -1;
+	}
+	return runde;
+}
+
+// constant
+SpielVideoDaten *SpielNachricht::getSVD() const
+{
+	return svd;
+}
+
+SpielerVideoDaten *SpielNachricht::getSPVD( int index ) const
+{
+	if( !spvd->hat( index ) )
+		return 0;
+	return spvd->get( index );
+}
+
+TeamVideoDaten *SpielNachricht::getTVD( int index ) const
+{
+	if( !tvd->hat( index ) )
+		return 0;
+	return tvd->get( index );
+}
+
+RundeVideoDaten *SpielNachricht::getRVD() const
+{
+	return runden->z( runde )->getRVD();
+}
+
+RundeSpielerVideoDaten *SpielNachricht::getRSVD( int index ) const
+{
+	return runden->z( runde )->getRSVD( index );
+}
+
+bool SpielNachricht::hatFehler( Text *txt ) const
+{
+	txt->setText( fehler->getText() );
+	return error;
+}
+
+int SpielNachricht::getTeamAnzahl() const
+{
+	return teamAnzahl;
+}
+
+int SpielNachricht::getRunde() const
+{
+	return runde;
+}
+
+// Reference Counting
+SpielNachricht *SpielNachricht::getThis()
+{
+	ref++;
+	return this;
+}
+
+SpielNachricht *SpielNachricht::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 102 - 0
Linie/Aufzeichnung/Nachricht/VideoNachricht.h

@@ -0,0 +1,102 @@
+#ifndef VideoNachricht_H
+#define VideoNachricht_H
+
+#include <Datei.h>
+#include <Text.h>
+#include "../VideoDaten/VideoDaten.h"
+
+using namespace Framework;
+
+struct VideoMSG
+{
+	char typ; // 0 = Tick, 1 = Aktion
+};
+
+// typ = 1
+struct VideoAktionMSG : public VideoMSG
+{
+	int spielerNummer;
+	char aktion; // 0 = T_Links press, 1 = T_Links release, 2 = T_Rechts press, 3 = T_Rechts release, 4 = Chat Nachricht, 5 = Linien Unterbrechung
+};
+
+// action = 4
+struct VideoChatMSG : public VideoAktionMSG
+{
+	int län;
+	Text msg;
+};
+
+// aktion = 5
+struct VideoLinieMSG : public VideoAktionMSG
+{
+	char unterbrechung;
+};
+
+class RundeNachricht
+{
+private:
+	int index;
+	int maxNachricht;
+	Array< VideoMSG* > *nachrichten;
+	Datei *vDat;
+	RundeVideoDaten *rvd;
+	Array< RundeSpielerVideoDaten* > *rsvd;
+	bool aktiv;
+	int ref;
+
+public:
+	// Konstruktor
+	RundeNachricht( Datei *d, int spielerAnzahl );
+	// Destruktor
+	~RundeNachricht();
+	// nicht constant
+	VideoMSG *GetNextNachricht();
+	VideoMSG *GetLastNachricht();
+	void setEnde();
+	// constant
+	RundeVideoDaten *getRVD() const;
+	RundeSpielerVideoDaten *getRSVD( int index ) const;
+	// Reference Counting
+	RundeNachricht *getThis();
+	RundeNachricht *release();
+};
+
+class SpielNachricht
+{
+private:
+	int runde;
+	int maxRunde;
+	int teamAnzahl;
+	RCArray< RundeNachricht > *runden;
+	Datei *vDat;
+	SpielVideoDaten *svd;
+	Array< SpielerVideoDaten* > *spvd;
+	Array< TeamVideoDaten* > *tvd;
+	bool error;
+	Text *fehler;
+	int ref;
+
+public:
+	// Konstruktor
+	SpielNachricht( int num );
+	// Destruktor
+	~SpielNachricht();
+	// nicht constant
+	VideoMSG *GetNextNachricht();
+	VideoMSG *GetLastNachricht();
+	int setRundenEnde( bool vorwärts );
+	// constant
+	SpielVideoDaten *getSVD() const;
+	SpielerVideoDaten *getSPVD( int index ) const;
+	TeamVideoDaten *getTVD( int index ) const;
+	RundeVideoDaten *getRVD() const;
+	RundeSpielerVideoDaten *getRSVD( int index ) const;
+	bool hatFehler( Text *txt ) const;
+	int getTeamAnzahl() const;
+	int getRunde() const;
+	// Reference Counting
+	SpielNachricht *getThis();
+	SpielNachricht *release();
+};
+
+#endif

+ 385 - 0
Linie/Aufzeichnung/Spieler/VideoSpieler.cpp

@@ -0,0 +1,385 @@
+#include "VideoSpieler.h"
+#include <Punkt.h>
+#include <math.h>
+#include <Rahmen.h>
+#include <InitDatei.h>
+
+// Inhalt der VideoSpieler Klasse aus VideoSpieler.h
+// Konstruktor
+VideoSpieler::VideoSpieler( SpielerVideoDaten *vDaten )
+{
+	spielerNummer = vDaten->spielerNummer;
+	team = vDaten->team;
+	spielerFarbe = 0;
+	teamFarbe = 0;
+	daten = new Array< VideoSpielerRundeDaten* >();
+	daten->set( new VideoSpielerRundeDaten( { 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0 } ), 0 );
+	runde = -1;
+	name = new Text();
+	teamName = new Text();
+	teamRahmen = new LRahmen();
+	teamRahmen->setRamenBreite( 1 );
+	teamRahmen->setSize( 10, 10 );
+	ref = 1;
+	spielerFarbe = vDaten->spielerFarbe;
+	teamFarbe = vDaten->teamFarbe;
+	name->setText( vDaten->name.getText() );
+	teamName->setText( vDaten->teamName.getText() );
+	teamRahmen->setFarbe( vDaten->teamFarbe );
+	gewonneneRunden = 0;
+	linienLänge = 0;
+	zeitAmLeben = 0;
+	zeitTod = 0;
+	kills = 0;
+	tode = 0;
+	killFarbe = 0;
+}
+
+// Destruktor
+VideoSpieler::~VideoSpieler()
+{
+	teamRahmen->release();
+	name->release();
+	teamName->release();
+	int anz = daten->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( daten->hat( i ) )
+			delete daten->get( i );
+	}
+	daten->release();
+}
+
+// nicht constant
+void VideoSpieler::addKill()
+{
+	kills++;
+	rKills.set( rKills.get( runde ) + 1, runde );
+}
+
+void VideoSpieler::neuRunde( bool vorwärts, RundeSpielerVideoDaten *vDaten, bool amLeben )
+{
+	if( vorwärts )
+	{
+		if( runde >= 0 )
+		{
+			if( daten->get( runde )->amLeben )
+				gewonneneRunden++;
+		}
+		runde++;
+		rLinienLänge.set( 0, runde );
+		rKills.set( 0, runde );
+		rTodesZeit.set( 0, runde );
+		if( daten->hat( runde ) )
+			delete daten->get( runde );
+		daten->set( new VideoSpielerRundeDaten( { vDaten->xPos, vDaten->yPos, vDaten->xSpeed,
+												  vDaten->ySpeed, vDaten->wendigkeit, 1, amLeben, 0, 0, 1, 0, 0 } ), runde );
+	}
+	else
+		runde--;
+}
+
+void VideoSpieler::setLinksKurve( bool lKurve )
+{
+	daten->get( runde )->lKurve = lKurve;
+}
+
+void VideoSpieler::setRechtsKurve( bool rKurve )
+{
+	daten->get( runde )->rKurve = rKurve;
+}
+
+void VideoSpieler::setLinienUnterbrechung( bool unterbrechung )
+{
+	daten->get( runde )->linieUnterbrochen = unterbrechung;
+}
+
+void VideoSpieler::prozessKurve( double zeit )
+{
+	VideoSpielerRundeDaten *dat = daten->get( runde );
+	if( dat->amLeben )
+	{
+		if( dat->lKurve || dat->rKurve )
+		{
+			double grad = dat->kurve * zeit;
+			if( dat->lKurve )
+				grad = -grad;
+			double cs = cos( grad );
+			double sn = sin( grad );
+			double tmpX = ( dat->xSpeed * cs - dat->ySpeed * sn );
+			double tmpY = ( dat->xSpeed * sn + dat->ySpeed * cs );
+			dat->xSpeed = tmpX;
+			dat->ySpeed = tmpY;
+		}
+	}
+}
+
+void VideoSpieler::tick( Bild *zMap, double zeit )
+{
+	VideoSpielerRundeDaten *dat = daten->get( runde );
+	dat->spielZeit += zeit;
+	bool wiederbelebt = 0;
+	bool rückwärts = zeit < 0;
+	if( rückwärts && !dat->amLeben )
+	{
+		if( dat->todesZeit >= dat->spielZeit )
+		{
+			dat->amLeben = 1;
+			wiederbelebt = 1;
+		}
+	}
+	if( dat->amLeben )
+	{
+		zeitAmLeben += zeit;
+		if( !rückwärts )
+			prozessKurve( zeit );
+		int dpx = 0;
+		int dpy = 0;
+		int dgx = zMap->getBreite();
+		int dgy = zMap->getHeight();
+		int *buff = zMap->getBuffer();
+		if( zMap && !dat->linieUnterbrochen )
+		{
+			int x1 = (int)( dat->xPos + 0.5 );
+			int y1 = (int)( dat->yPos + 0.5 );
+			int x2 = (int)( dat->xPos + dat->xSpeed * zeit + 0.5 );
+			int y2 = (int)( dat->yPos + dat->ySpeed * zeit + 0.5 );
+			int xlän = x2 - x1, axlän = abs( xlän );
+			int ylän = y2 - y1, aylän = abs( ylän );
+			double xf = (double)xlän / ( aylän ? aylän : 1 );
+			double yf = (double)ylän / ( axlän ? axlän : 1 );
+			if( axlän > aylän )
+				xf = xf < 0 ? -1 : 1;
+			else
+				yf = yf < 0 ? -1 : 1;
+			double x = (double)x1, y = (double)y1;
+			int maxP = (int)( sqrt( (double)( xlän * xlän + ylän * ylän ) ) + 0.5 );
+			int count = 0;
+			int lastX = (int)( x + 0.5 ), lastY = (int)( y + 0.5 );
+			if( !rückwärts )
+			{
+				while( !( (int)( x + 0.5 ) == x2 && (int)( y + 0.5 ) == y2 ) && count < maxP )
+				{
+					if( (int)( x + 0.5 ) < dpx || (int)( x + 0.5 ) >= dgx || (int)( y + 0.5 ) < dpy || (int)( y + 0.5 ) >= dgy )
+					{
+						killFarbe = 0;
+						tode++;
+						dat->todesZeit = dat->spielZeit;
+						rTodesZeit.set( (int)dat->spielZeit, runde );
+						dat->amLeben = 0;
+						dat->renderVorTod = count;
+						break;
+					}
+					if( buff[ (int)( x + 0.5 ) + (int)( y + 0.5 ) * zMap->getBreite() ] )
+					{
+						if( buff[ (int)( x + 0.5 ) + (int)( y + 0.5 ) * zMap->getBreite() ] != spielerFarbe )
+							killFarbe = buff[ (int)( x + 0.5 ) + (int)( y + 0.5 ) * zMap->getBreite() ];
+						else
+							killFarbe = 0;
+						tode++;
+						dat->todesZeit = dat->spielZeit;
+						rTodesZeit.set( (int)dat->spielZeit, runde );
+						dat->amLeben = 0;
+						dat->renderVorTod = count;
+						break;
+					}
+					buff[ (int)( x + 0.5 ) + (int)( y + 0.5 ) * zMap->getBreite() ] = spielerFarbe;
+					linienLänge++;
+					rLinienLänge.set( rLinienLänge.get( runde ) + 1, runde );
+					x += xf, y += yf;
+					if( lastX != (int)( x + 0.5 ) && lastY != (int)( yf + 0.5 ) )
+					{
+						if( (int)xf )
+						{
+							if( !( lastX < dpx || lastX >= dgx || (int)( y + 0.5 ) < dpy || (int)( y + 0.5 ) >= dgy ) )
+							    buff[ lastX + (int)( y + 0.5 ) * zMap->getBreite() ] = spielerFarbe;
+						}
+						else
+						{
+							if( !( (int)( x + 0.5 ) < dpx || (int)( x + 0.5 ) >= dgx || lastY < dpy || lastY >= dgy ) )
+								buff[ (int)( x + 0.5 ) + lastY * zMap->getBreite() ] = spielerFarbe;
+						}
+					}
+					lastX = (int)( x + 0.5 );
+					lastY = (int)( y + 0.5 );
+					count++;
+				}
+			}
+			if( rückwärts )
+			{
+				if( wiederbelebt )
+					maxP = dat->renderVorTod;
+				while( !( (int)( x ) == x2 && (int)( y + 0.5 ) == y2 ) && count < maxP )
+				{
+					count++;
+					x += xf, y += yf;
+					if( lastX != (int)( x + 0.5 ) && lastY != (int)( yf + 0.5 ) )
+					{
+						if( (int)xf )
+						{
+							if( !( (int)( x + 0.5 ) < dpx || (int)( x + 0.5 ) >= dgx || lastY < dpy || lastY >= dgy ) )
+								buff[ (int)( x + 0.5 ) + lastY * zMap->getBreite() ] = 0;
+						}
+						else
+						{
+							if( !( lastX < dpx || lastX >= dgx || (int)( y + 0.5 ) < dpy || (int)( y + 0.5 ) >= dgy ) )
+								buff[ lastX + (int)( y + 0.5 ) * zMap->getBreite() ] = 0;
+						}
+					}
+					lastX = (int)( x + 0.5 );
+					lastY = (int)( y + 0.5 );
+					if( !( (int)( x + 0.5 ) < dpx || (int)( x + 0.5 ) >= dgx || (int)( y + 0.5 ) < dpy || (int)( y + 0.5 ) >= dgy ) )
+						buff[ (int)( x + 0.5 ) + (int)( y + 0.5 ) * zMap->getBreite() ] = 0;
+				}
+			}
+		}
+		dat->xPos += dat->xSpeed * zeit;
+		dat->yPos += dat->ySpeed * zeit;
+		if( rückwärts )
+			prozessKurve( zeit );
+	}
+	else
+		zeitTod += zeit;
+}
+
+void VideoSpieler::render( VideoKamera *zKam, Bild &zRObj )
+{
+	VideoSpielerRundeDaten *dat = daten->get( runde );
+	if( dat->amLeben )
+	{
+		if( zKam->istSichtbar( (int)dat->xPos, (int)dat->yPos ) )
+		{
+			teamRahmen->setPosition( zKam->getRX( (int)dat->xPos ) - 5, zKam->getRY( (int)dat->yPos ) - 5 );
+			zRObj.fillRegion( teamRahmen->getX(), teamRahmen->getY(), 10, 10, spielerFarbe );
+			teamRahmen->render( zRObj );
+		}
+	}
+}
+
+// constant
+double VideoSpieler::getX() const
+{
+	return daten->get( runde )->xPos;
+}
+
+double VideoSpieler::getY() const
+{
+	return daten->get( runde )->yPos;
+}
+
+int VideoSpieler::getTeam() const
+{
+	return team;
+}
+
+int VideoSpieler::getTeamFarbe() const
+{
+	return teamFarbe;
+}
+
+int VideoSpieler::getFarbe() const
+{
+	return spielerFarbe;
+}
+
+int VideoSpieler::getSpielerNummer() const
+{
+	return spielerNummer;
+}
+
+bool VideoSpieler::istAmLeben() const
+{
+	return daten->get( runde )->amLeben;
+}
+
+Text *VideoSpieler::getName() const
+{
+	return name ? name->getThis() : 0;
+}
+
+Text *VideoSpieler::zName() const
+{
+	return name;
+}
+
+Text *VideoSpieler::getTeamName() const
+{
+	return teamName ? teamName->getThis() : 0;
+}
+
+Text *VideoSpieler::zTeamName() const
+{
+	return teamName;
+}
+
+bool VideoSpieler::istMausIn( int mx, int my ) const
+{
+	VideoSpielerRundeDaten *dat = daten->get( runde );
+	return mx >= (int)dat->xPos - 5 && mx <= (int)dat->xPos + 5 &&
+		   my >= (int)dat->yPos - 5 && my <= (int)dat->yPos + 5;
+}
+
+int VideoSpieler::getGewonneneRunden() const
+{
+	return gewonneneRunden;
+}
+
+int VideoSpieler::getLinienLänge() const
+{
+	return linienLänge;
+}
+
+int VideoSpieler::getZeitAmLeben() const
+{
+	return (int)zeitAmLeben;
+}
+
+int VideoSpieler::getZeitTod() const
+{
+	return (int)zeitTod;
+}
+
+int VideoSpieler::getKills() const
+{
+	return kills;
+}
+
+int VideoSpieler::getTode() const
+{
+	return tode;
+}
+
+int VideoSpieler::getKillFarbe() const
+{
+	return killFarbe;
+}
+
+int VideoSpieler::getLinienLänge( int r ) const
+{
+	return rLinienLänge.get( r );
+}
+
+int VideoSpieler::getKills( int r ) const
+{
+	return rKills.get( r );
+}
+
+int VideoSpieler::getTodesZeit( int r ) const
+{
+	return rTodesZeit.get( r );
+}
+
+// Reference Counting
+VideoSpieler *VideoSpieler::getThis()
+{
+	ref++;
+	return this;
+}
+
+VideoSpieler *VideoSpieler::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 95 - 0
Linie/Aufzeichnung/Spieler/VideoSpieler.h

@@ -0,0 +1,95 @@
+#ifndef VideoSpieler_H
+#define VideoSpieler_H
+
+#include "../Kamera/VideoKamera.h"
+#include "../VideoDaten/VideoDaten.h"
+#include <Text.h>
+
+#define TICK 0.03333333
+
+using namespace Framework;
+
+struct VideoSpielerRundeDaten
+{
+	double xPos;
+	double yPos;
+	double xSpeed;
+	double ySpeed;
+	double kurve;
+	int radius;
+	bool amLeben;
+	bool lKurve;
+	bool rKurve;
+	bool linieUnterbrochen;
+	double todesZeit;
+	double spielZeit;
+	int renderVorTod;
+};
+
+class VideoSpieler
+{
+private:
+	int spielerNummer;
+	int team;
+	int spielerFarbe;
+	int teamFarbe;
+	Array< VideoSpielerRundeDaten* > *daten;
+	int runde;
+	Text *name;
+	Text *teamName;
+	LRahmen *teamRahmen;
+	int gewonneneRunden;
+	int linienLänge;
+	double zeitAmLeben;
+	double zeitTod;
+	int kills;
+	int tode;
+	int killFarbe;
+	Array< int > rLinienLänge;
+	Array< int > rKills;
+	Array< int > rTodesZeit;
+	int ref;
+
+public:
+	// Konstruktor
+	VideoSpieler( SpielerVideoDaten *vDaten );
+	// Destruktor
+	~VideoSpieler();
+	// nicht constant
+	void addKill();
+	void neuRunde( bool vorwärts, RundeSpielerVideoDaten *vDaten, bool amLeben );
+	void setLinksKurve( bool lKurve );
+	void setRechtsKurve( bool rKurve );
+	void setLinienUnterbrechung( bool unterbrechung );
+	void prozessKurve( double zeit );
+	void tick( Bild *zMap, double zeit );
+	void render( VideoKamera *zKam, Bild &zRObj );
+	// constant
+	double getX() const;
+	double getY() const;
+	int getTeam() const;
+	int getTeamFarbe() const;
+	int getFarbe() const;
+	int getSpielerNummer() const;
+	bool istAmLeben() const;
+	Text *getName() const;
+	Text *zName() const;
+	Text *getTeamName() const;
+	Text *zTeamName() const;
+	bool istMausIn( int mx, int my ) const;
+	int getGewonneneRunden() const;
+	int getLinienLänge() const;
+	int getZeitAmLeben() const;
+	int getZeitTod() const;
+	int getKills() const;
+	int getTode() const;
+	int getKillFarbe() const;
+	int getLinienLänge( int r ) const;
+	int getKills( int r ) const;
+	int getTodesZeit( int r ) const;
+	// Reference Counting
+	VideoSpieler *getThis();
+	VideoSpieler *release();
+};
+
+#endif

+ 219 - 0
Linie/Aufzeichnung/Steuerung/VideoSteuerung.cpp

@@ -0,0 +1,219 @@
+#include "VideoSteuerung.h"
+#include "../../Initialisierung/Initialisierung.h"
+#include <DateiSystem.h>
+#include <Text.h>
+#include <Punkt.h>
+#include <Bildschirm.h>
+#include <MausEreignis.h>
+
+// Inhalt der VideoSteuerung Klasse aus VideoSteuerung.h
+// Konstruktor
+VideoSteuerung::VideoSteuerung( Schrift *zSchrift, Bildschirm *zScreen )
+{
+	pos = zScreen->getBackBufferSize() - Punkt( 285, 30 );
+	verlassen = initKnopf( 0, 0, 100, 22, zSchrift, Knopf::Style::Sichtbar, "Verlassen" );
+	initToolTip( verlassen, "Aufzeichnung verlassen", zSchrift->getThis(), zScreen );
+	langsamer = initKnopf( 105, 0, 22, 22, 0, 0, "" );
+	langsamer->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::Hintergrund | Knopf::Style::KlickBuffer | Knopf::Style::Rahmen );
+	langsamer->setLinienRahmenBreite( 1 );
+	stop = initKnopf( 130, 0, 22, 22, 0, 0, "" );
+	stop->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::Hintergrund | Knopf::Style::KlickBuffer | Knopf::Style::Rahmen );
+	stop->setLinienRahmenBreite( 1 );
+	schneller = initKnopf( 155, 0, 22, 22, 0, 0, "" );
+	schneller->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::Hintergrund | Knopf::Style::KlickBuffer | Knopf::Style::Rahmen );
+	schneller->setLinienRahmenBreite( 1 );
+	LTDBDatei *vBilder = new LTDBDatei();
+	vBilder->setDatei( new Text( "data/client/bilder/video.ltdb" ) );
+	vBilder->leseDaten( 0 );
+	langsamer->setHintergrundBildZ( vBilder->laden( 0, new Text( "zurück.png" ) ) );
+	stop->setHintergrundBildZ( vBilder->laden( 0, new Text( "pause.png" ) ) );
+	schneller->setHintergrundBildZ( vBilder->laden( 0, new Text( "vor.png" ) ) );
+	vBilder->release();
+	initToolTip( langsamer, "Langsammer abspielen", zSchrift->getThis(), zScreen );
+	initToolTip( stop, "Pause", zSchrift->getThis(), zScreen );
+	initToolTip( schneller, "Schneller abspielen", zSchrift->getThis(), zScreen );
+	zeit = initTextFeld( 180, 0, 100, 22, zSchrift, TextFeld::Style::Text | TextFeld::Style::Center, "0:0:0" );
+	spielZeit = 0;
+	speed = 1;
+	vorwärts = 1;
+	zeitlupe = 0;
+	beendet = 0;
+	bJetzt = 0;
+	ref = 1;
+}
+
+// Destruktor
+VideoSteuerung::~VideoSteuerung()
+{
+	verlassen->release();
+	langsamer->release();
+	stop->release();
+	schneller->release();
+	zeit->release();
+}
+
+// Nicht constant
+void VideoSteuerung::doMausEreignis( MausEreignis &me )
+{
+	me.mx -= pos.x;
+	me.my -= pos.y;
+	bool vera = me.verarbeitet;
+	verlassen->doMausEreignis( me );
+	if( !vera && me.verarbeitet )
+	{
+		if( me.id == ME_RLinks )
+		{
+			bJetzt = 1;
+			beendet = 1;
+		}
+		vera = 1;
+	}
+	langsamer->doMausEreignis( me );
+	if( !vera && me.verarbeitet )
+	{
+		if( me.id == ME_RLinks )
+		{
+			if( !speed )
+			{
+				vorwärts = 0;
+				speed = 1;
+				stop->addStyle( Knopf::Style::Erlaubt );
+				schneller->addStyle( Knopf::Style::Erlaubt );
+			}
+			else
+			{
+				speed += ( vorwärts && zeitlupe ) || ( !vorwärts && !zeitlupe );
+				speed -= ( vorwärts && !zeitlupe ) || ( !vorwärts && zeitlupe );
+				zeitlupe |= vorwärts && ( speed == 0 );
+				zeitlupe &= vorwärts || ( speed != 0 );
+				speed += speed == 0;
+			}
+		}
+		vera = 1;
+	}
+	stop->doMausEreignis( me );
+	if( !vera && me.verarbeitet )
+	{
+		if( me.id == ME_RLinks )
+		{
+			speed = 0;
+			zeitlupe = 0;
+			stop->removeStyle( Knopf::Style::Erlaubt );
+		}
+		vera = 1;
+	}
+	schneller->doMausEreignis( me );
+	if( !vera && me.verarbeitet )
+	{
+		if( me.id == ME_RLinks )
+		{
+			if( !speed )
+			{
+				vorwärts = 1;
+				speed = 1;
+				stop->addStyle( Knopf::Style::Erlaubt );
+				langsamer->addStyle( Knopf::Style::Erlaubt );
+			}
+			else
+			{
+				speed += ( vorwärts && !zeitlupe ) || ( !vorwärts && zeitlupe );
+				speed -= ( vorwärts && zeitlupe ) || ( !vorwärts && !zeitlupe );
+				zeitlupe |= !vorwärts && ( speed == 0 );
+				zeitlupe &= !vorwärts || ( speed != 0 );
+				speed += speed == 0;
+			}
+		}
+		vera = 1;
+	}
+	me.mx += pos.x;
+	me.my += pos.y;
+}
+
+bool VideoSteuerung::tick( double zeit )
+{
+	bool ret = langsamer->tick( zeit );
+	ret |= verlassen->tick( zeit );
+	ret |= stop->tick( zeit );
+	ret |= schneller->tick( zeit );
+	spielZeit += zeit;
+	if( (int)spielZeit != (int)( spielZeit - zeit ) )
+	{
+		Text z;
+		z = (int)spielZeit / 60 / 60;
+		z += ":";
+		z += (int)spielZeit / 60 % 60;
+		z += ":";
+		z += (int)spielZeit % 60;
+		this->zeit->setText( z );
+	}
+	ret |= this->zeit->tick( zeit );
+	return ret;
+}
+
+void VideoSteuerung::render( Bild &zRObj )
+{
+	if( !zRObj.setDrawOptions( pos.x, pos.y, 300, 30 ) )
+		return;
+	verlassen->render( zRObj );
+	langsamer->render( zRObj );
+	stop->render( zRObj );
+	schneller->render( zRObj );
+	zeit->render( zRObj );
+	zRObj.releaseDrawOptions();
+}
+
+void VideoSteuerung::pause( bool ende )
+{
+	speed = 0;
+	zeitlupe = 0;
+	stop->removeStyle( Knopf::Style::Erlaubt );
+	if( ende )
+		schneller->removeStyle( Knopf::Style::Erlaubt );
+	else
+		langsamer->removeStyle( Knopf::Style::Erlaubt );
+}
+
+bool VideoSteuerung::istBeendet( bool jetzt )
+{
+	if( jetzt )
+	{
+		if( bJetzt )
+		{
+			bJetzt = 0;
+			return 1;
+		}
+		return 0;
+	}
+	return beendet;
+}
+
+// constant
+int VideoSteuerung::getSpeed() const
+{
+	return speed + zeitlupe;
+}
+
+bool VideoSteuerung::istVorwärts() const
+{
+	return vorwärts;
+}
+
+bool VideoSteuerung::istZeitlupe() const
+{
+	return zeitlupe;
+}
+
+// Reference Counting
+VideoSteuerung *VideoSteuerung::getThis()
+{
+	ref++;
+	return this;
+}
+
+VideoSteuerung *VideoSteuerung::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 45 - 0
Linie/Aufzeichnung/Steuerung/VideoSteuerung.h

@@ -0,0 +1,45 @@
+#ifndef VideoSteuerung_H
+#define VideoSteuerung_H
+
+#include <Knopf.h>
+
+using namespace Framework;
+
+class VideoSteuerung
+{
+private:
+	Punkt pos;
+	Knopf *verlassen;
+	Knopf *langsamer;
+	Knopf *stop;
+	Knopf *schneller;
+	TextFeld *zeit;
+	double spielZeit;
+	int speed;
+	bool vorwärts;
+	bool zeitlupe;
+	bool beendet;
+	bool bJetzt;
+	int ref;
+
+public:
+	// Konstruktor
+	VideoSteuerung( Schrift *zSchrift, Bildschirm *zScreen );
+	// Destruktor
+	~VideoSteuerung();
+	// Nicht constant
+	void doMausEreignis( MausEreignis &me );
+	bool tick( double zeit );
+	void render( Bild &zRObj );
+	void pause( bool ende );
+	bool istBeendet( bool jetzt );
+	// constant
+	int getSpeed() const;
+	bool istVorwärts() const;
+	bool istZeitlupe() const;
+	// Reference Counting
+	VideoSteuerung *getThis();
+	VideoSteuerung *release();
+};
+
+#endif

+ 55 - 0
Linie/Aufzeichnung/VideoDaten/VideoDaten.h

@@ -0,0 +1,55 @@
+#ifndef VideoDaten_H
+#define VideoDaten_H
+
+#include <Text.h>
+
+using namespace Framework;
+
+// Dateikopf (ersten 4 bytes)
+struct SpielVideoDaten
+{
+	int spielerAnzahl;
+};
+// Für jeden Spieler nach dem Dateikopf (folgenden 28 bytes)
+struct SpielerVideoDaten
+{
+	int index;
+	int spielerNummer;
+	int kamBreite;
+	int kamHöhe;
+	int team;
+	int spielerFarbe;
+	int teamFarbe;
+	Text name;
+	Text teamName;
+};
+// Für jedes Team (folgenden 12 bytes)
+struct TeamVideoDaten
+{
+	int teamNummer;
+	int maxPunkte;
+	int punkte;
+};
+// Für jede neue Runde (folgenden 8 bytes)
+struct RundeVideoDaten
+{
+	int mapBreite;
+	int mapHöhe;
+};
+// Für jede Runde für jeden Spieler (folgenden 36 bytes)
+struct RundeSpielerVideoDaten
+{
+	double wendigkeit;
+	double xPos;
+	double yPos;
+	double xSpeed;
+	double ySpeed;
+};
+// Für jede Netzwerk Nachricht (folgenden 6 bytes) mit 0x01 Eingeleitet
+struct NachrichtVideoDaten
+{
+	int spielerNummer;
+	short län;
+};
+// Dann folgen 'län' bytes Daten für jede Nachricht
+#endif

+ 214 - 0
Linie/HistorieStatistik/HistorieStatistik.cpp

@@ -0,0 +1,214 @@
+#include "HistorieStatistik.h"
+#include <Knopf.h>
+#include <MausEreignis.h>
+#include <Bildschirm.h>
+#include "../Initialisierung/Initialisierung.h"
+#include <InitDatei.h>
+#include <DateiSystem.h>
+#include "StatistikLeser.h"
+
+// Inhalt der HistorieStatistik Klasse aus HistorieStatistik.h
+// Konstruktor
+HistorieStatistik::HistorieStatistik()
+{
+	schrift = 0;
+	screen = 0;
+	gss = new Array< SSDGesamtSpieler* >();
+	gts = new Array< SSDGesamtTeam* >();
+	rs = new Array< SSDRunde* >();
+	runde = 0;
+	tabelle = 0;
+	fertig = 0;
+	geladen = 0;
+	geschlossen = 0;
+	alpha = 0;
+	sichtbar = 0;
+	tickVal = 0;
+	rend = 0;
+	ref = 1;
+}
+
+// Destruktor
+HistorieStatistik::~HistorieStatistik()
+{
+	if( schrift )
+		schrift->release();
+	if( screen )
+		screen->release();
+	if( !geladen )
+	{
+		gss->release();
+		gts->release();
+		rs->release();
+	}
+	else
+	{
+		int anz = gss->getEintragAnzahl();
+		for( int i = 0; i < anz; i++ )
+		{
+			if( gss->hat( i ) )
+				delete gss->get( i );
+		}
+		gss->release();
+		anz = gts->getEintragAnzahl();
+		for( int i = 0; i < anz; i++ )
+		{
+			if( gts->hat( i ) )
+				delete gts->get( i );
+		}
+		gts->release();
+		anz = rs->getEintragAnzahl();
+		for( int i = 0; i < anz; i++ )
+		{
+			if( rs->hat( i ) )
+			{
+				int anz2 = rs->get( i )->spieler.getEintragAnzahl();
+				for( int j = 0; j < anz2; j++ )
+				{
+					if( rs->get( i )->spieler.hat( j ) )
+						delete rs->get( i )->spieler.get( j );
+				}
+				anz2 = rs->get( i )->teams.getEintragAnzahl();
+				for( int j = 0; j < anz2; j++ )
+				{
+					if( rs->get( i )->teams.hat( j ) )
+						delete rs->get( i )->teams.get( j );
+				}
+				delete rs->get( i );
+			}
+		}
+		rs->release();
+	}
+	if( runde )
+		runde->release();
+	if( tabelle )
+		tabelle->release();
+	if( fertig )
+		fertig->release();
+}
+
+// nicht constant
+void HistorieStatistik::setSchrift( Schrift *schrift )
+{
+	if( this->schrift )
+		this->schrift->release();
+	this->schrift = schrift;
+}
+
+void HistorieStatistik::setBildschirm( Bildschirm *screen )
+{
+	if( this->screen )
+		this->screen->release();
+	this->screen = screen;
+}
+
+void HistorieStatistik::ladeDaten( int spielId )
+{
+	if( geladen )
+		return;
+	StatistikLeser *reader = new StatistikLeser( spielId );
+	for( int i = 0; i < reader->getSpielerAnzahl(); i++ )
+		gss->set( reader->getSSDGS( i ), i );
+	for( int i = 0; i < reader->getTeamAnzahl(); i++ )
+		gts->set( reader->getSSDGT( i ), i );
+	for( int i = 0; i < reader->getRundenAnzahl(); i++ )
+		rs->set( reader->getSSDR( i ), i );
+	reader->release();
+	tabelle = new StatistikTabelle( gss->getThis(), gts->getThis(), rs->getThis(), schrift, screen, 1 );
+	runde = new StatistikRunde( schrift, rs->getThis(), 1 );
+	fertig = initKnopf( 600, 390, 100, 20, schrift, Knopf::Style::Sichtbar, "Zurück" );
+	geladen = 1;
+}
+
+void HistorieStatistik::setSichtbar( bool sichtbar )
+{
+	this->sichtbar = sichtbar;
+}
+
+void HistorieStatistik::doMausEreignis( MausEreignis &me )
+{
+	if( !geladen )
+		return;
+	tabelle->doMausEreignis( me );
+	runde->doMausEreignis( me );
+	bool vera = me.verarbeitet;
+	fertig->doMausEreignis( me );
+	if( !vera && me.verarbeitet && me.id == ME_RLinks )
+		geschlossen = 1;
+}
+
+void HistorieStatistik::doTastaturEreignis( TastaturEreignis &te )
+{
+}
+
+bool HistorieStatistik::tick( double tickVal )
+{
+	if( !geladen )
+		return 0;
+	runde->setRunde( tabelle->getRunde() );
+	rend |= tabelle->tick( tickVal );
+	rend |= runde->tick( tickVal );
+	rend |= fertig->tick( tickVal );
+	this->tickVal += tickVal * 150;
+	int val = ( int )this->tickVal;
+	this->tickVal -= val;
+	if( val )
+	{
+		if( sichtbar && alpha != 255 )
+		{
+			if( alpha + val > 255 )
+				alpha = 255;
+			else
+				alpha += val;
+			rend = 1;
+		}
+		if( !sichtbar && alpha )
+		{
+			if( alpha - val < 0 )
+				alpha = 0;
+			else
+				alpha -= val;
+			rend = 1;
+		}
+	}
+	bool ret = rend;
+	rend = 0;
+	return ret;
+}
+
+void HistorieStatistik::render( Bild &zRObj )
+{
+	if( !geladen )
+		return;
+	zRObj.setAlpha( alpha );
+	tabelle->render( zRObj );
+	runde->render( zRObj );
+	fertig->render( zRObj );
+	zRObj.releaseAlpha();
+}
+
+// constant
+bool HistorieStatistik::istNochSichtbar() const
+{
+	return alpha != 0 || sichtbar;
+}
+
+bool HistorieStatistik::wurdeGeschlossen() const
+{
+	return geschlossen;
+}
+
+// Reference Counting
+AccountHistorieStatistikV *HistorieStatistik::getThis()
+{
+	ref++;
+	return this;
+}
+
+AccountHistorieStatistikV *HistorieStatistik::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 50 - 0
Linie/HistorieStatistik/HistorieStatistik.h

@@ -0,0 +1,50 @@
+#ifndef HistorieStatistik_H
+#define HistorieStatistik_H
+
+#include <AccountHistorieStatistikV.h>
+#include "../SpielStatistik/SpielStatistikDaten.h"
+#include "../SpielStatistik/Runde/StatistikRunde.h"
+#include "../SpielStatistik/Tabelle/StatistikTabelle.h"
+
+class HistorieStatistik : public AccountHistorieStatistikV
+{
+private:
+	Schrift *schrift;
+	Bildschirm *screen;
+	Array< SSDGesamtSpieler* > *gss;
+	Array< SSDGesamtTeam* > *gts;
+	Array< SSDRunde* > *rs;
+	StatistikRunde *runde;
+	StatistikTabelle *tabelle;
+	Knopf *fertig;
+	bool geladen;
+	bool geschlossen;
+	unsigned char alpha;
+	bool sichtbar;
+	double tickVal;
+	bool rend;
+	int ref;
+
+public:
+	// Konstruktor
+	HistorieStatistik();
+	// Destruktor
+	~HistorieStatistik();
+	// nicht constant
+	virtual void setSchrift( Schrift *schrift );
+	virtual void setBildschirm( Bildschirm *schrift );
+	virtual void ladeDaten( int spielId );
+	virtual void setSichtbar( bool sichtbar );
+	virtual void doMausEreignis( MausEreignis &me );
+	virtual void doTastaturEreignis( TastaturEreignis &te );
+	virtual bool tick( double tickVal );
+	virtual void render( Bild &zRObj );
+	// constant
+	virtual bool istNochSichtbar() const;
+	virtual bool wurdeGeschlossen() const;
+	// Reference Counting
+	virtual AccountHistorieStatistikV *getThis();
+	virtual AccountHistorieStatistikV *release();
+};
+
+#endif

+ 411 - 0
Linie/HistorieStatistik/StatistikLeser.cpp

@@ -0,0 +1,411 @@
+#include "StatistikLeser.h"
+
+// Inhalt der StatistikLeser Klasse aus StatistikLeser.h
+// Konstruktor
+StatistikLeser::StatistikLeser( int spielId )
+{
+	nachrichten = new SpielNachricht( spielId );
+	bestenliste = new VideoBestenliste( 0 );
+	map = new VideoKarte();
+	spieler = new RCArray< VideoSpieler >();
+	ssdgs = new Array< SSDGesamtSpieler* >();
+	ssdgt = new Array< SSDGesamtTeam* >();
+	ssdr = new Array< SSDRunde* >();
+	spielerAnzahl = 0;
+	teamAnzahl = 0;
+	rundenAnzahl = 0;
+	ref = 1;
+	Text f;
+	fehler = nachrichten->hatFehler( &f );
+	if( fehler )
+		return;
+	// Spiel Initialisieren
+	spielerAnzahl = nachrichten->getSVD()->spielerAnzahl;
+	teamAnzahl = nachrichten->getTeamAnzahl();
+	int maxTeam = 0;
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		SpielerVideoDaten *dat = nachrichten->getSPVD( i );
+		VideoSpieler *tmp = new VideoSpieler( dat );
+		bestenliste->addSpieler( tmp );
+		spieler->set( tmp, i );
+		maxTeam = maxTeam < dat->team ? dat->team : maxTeam;
+	}
+	maxTeam++;
+	bestenliste->setTeamAnzahl( maxTeam );
+	for( int i = 0; i < nachrichten->getTeamAnzahl(); i++ )
+	{
+		TeamVideoDaten *dat = nachrichten->getTVD( i );
+		bestenliste->setTeamMaxPunkte( dat->teamNummer, dat->maxPunkte );
+		bestenliste->setTeamPunkte( dat->teamNummer, dat->punkte );
+	}
+	RundeVideoDaten *rDat = nachrichten->getRVD();
+	map->setSize( rDat->mapBreite, rDat->mapHöhe );
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		RundeSpielerVideoDaten *dat = nachrichten->getRSVD( i );
+		spieler->z( i )->neuRunde( 1, dat, 1 );
+	}
+	Array< int > rundenSieger;
+	Array< int > rundenDauer;
+	VideoMSG *nMsg = 0;
+	double sZeit = 0;
+	// Spiel nachstellen
+	while( 1 )
+	{
+		while( !nMsg || nMsg->typ )
+		{
+			if( !nMsg )
+				nMsg = nachrichten->GetNextNachricht();
+			if( !nMsg )
+				break;
+			if( !nMsg->typ )
+				break;
+			VideoAktionMSG *ak = (VideoAktionMSG*)nMsg;
+			switch( ak->aktion )
+			{
+			case 0: // T_Links Press
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+					{
+						spieler->z( i )->setLinksKurve( 1 );
+						break;
+					}
+				}
+				break;
+			case 1: // T_Links Release
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+					{
+						spieler->z( i )->setLinksKurve( 0 );
+						break;
+					}
+				}
+				break;
+			case 2: // T_Rechts Press
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+					{
+						spieler->z( i )->setRechtsKurve( 1 );
+						break;
+					}
+				}
+				break;
+			case 3: // T_Rechts Release
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+					{
+						spieler->z( i )->setRechtsKurve( 0 );
+						break;
+					}
+				}
+				break;
+			case 5: // Linien Unterbrechung
+				if( 1 )
+				{
+					VideoLinieMSG *lMsg = (VideoLinieMSG*)ak;
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == ak->spielerNummer )
+						{
+							spieler->z( i )->setLinienUnterbrechung( lMsg->unterbrechung != 0 );
+							break;
+						}
+					}
+				}
+				break;
+			}
+			nMsg = 0;
+		}
+		if( !nMsg )
+			break;
+		sZeit += TICK;
+		bool rEnd = 0;
+		int tmpTeam = -1;
+		for( int i = 0; i < spielerAnzahl; i++ )
+		{
+			VideoSpieler *tmp = spieler->z( i );
+			if( tmp )
+			{
+				bool amLeben = tmp->istAmLeben();
+				tmp->tick( map->zMap(), TICK );
+				if( amLeben != tmp->istAmLeben() )
+				{
+					for( int j = 0; j < spielerAnzahl; j++ )
+					{
+						VideoSpieler *s = spieler->z( j );
+						if( s && s->getFarbe() == tmp->getKillFarbe() )
+							s->addKill();
+						if( s && s != tmp && s->istAmLeben() )
+							bestenliste->addPunkt( s->getTeam(), s->getSpielerNummer(), 1 );
+					}
+				}
+				if( amLeben && !tmp->istAmLeben() )
+				{ // gestorben
+					int team = tmp->getTeam();
+					bool teamLebt = 0;
+					for( int k = 0; k < spielerAnzahl; k++ )
+					{
+						if( spieler->z( k ) && spieler->z( k )->getTeam() == team )
+							teamLebt |= spieler->z( k )->istAmLeben();
+					}
+					if( !teamLebt )
+					{
+						int teamAmLebenAnzahl = 0;
+						for( int k = 0; k < maxTeam; k++ )
+						{
+							if( !bestenliste->teamExistiert( k ) )
+								continue;
+							bool amLeben = 0;
+							for( int l = 0; l < spielerAnzahl; l++ )
+							{
+								if( spieler->z( l ) && spieler->z( l )->getTeam() == k )
+									amLeben |= spieler->z( l )->istAmLeben();
+							}
+							if( amLeben )
+							{
+								tmpTeam = k;
+								teamAmLebenAnzahl++;
+								bestenliste->addPunkt( k, 1 );
+							}
+							else
+								bestenliste->addPunkt( k, 0 );
+							if( !bestenliste->getTeamPunkte( k ) )
+								bestenliste->setTeamStatus( k, "tod", 0xFFFF0000 );
+						}
+						if( teamAmLebenAnzahl <= 1 )
+							rEnd = 1;
+					}
+				}
+			}
+		}
+		if( rEnd )
+		{ // Runden Ende
+			rundenSieger.set( tmpTeam, rundenAnzahl );
+			rundenDauer.set( (int)sZeit, rundenAnzahl );
+			rundenAnzahl++;
+			sZeit = 0;
+			int nAnz = 0;
+			int nAnz2 = 0;
+			for( int i = 0; i < maxTeam; i++ )
+			{
+				if( bestenliste->teamExistiert( i ) )
+				{
+					nAnz += bestenliste->hatTeamGewonnen( i );
+					nAnz2 += bestenliste->getTeamPunkte( i ) >= 0;
+				}
+			}
+			if( nAnz || nAnz2 <= 1 || rundenAnzahl >= 10 )
+			{
+				RundeSpielerVideoDaten dat;
+				for( int i = 0; i < spielerAnzahl; i++ )
+					spieler->z( i )->neuRunde( 1, &dat, 1 );
+				break; // Spiel Ende
+			}
+			int r = nachrichten->setRundenEnde( 1 );
+			bestenliste->updatePunkte();
+			map->nextRunde( 1 );
+			RundeVideoDaten *dat = nachrichten->getRVD();
+			map->setSize( dat->mapBreite, dat->mapHöhe );
+			for( int i = 0; i < spielerAnzahl; i++ )
+				spieler->z( i )->neuRunde( 1, nachrichten->getRSVD( i ), bestenliste->getTeamPunkte( spieler->z( i )->getTeam() ) != 0 );
+		}
+		nMsg = 0;
+	}
+	// Statistik erstellen
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		SSDGesamtSpieler *ssdgs = new SSDGesamtSpieler();
+		VideoSpieler *tmp = spieler->z( i );
+		ssdgs->spielerNummer = tmp->getSpielerNummer();
+		ssdgs->spielerName.setText( tmp->zName()->getText() );
+		ssdgs->teamName.setText( tmp->zTeamName()->getText() );
+		ssdgs->spielerFarbe = tmp->getFarbe();
+		ssdgs->teamFarbe = tmp->getTeamFarbe();
+		ssdgs->gewonneneRunden = tmp->getGewonneneRunden();
+		ssdgs->punkte = bestenliste->getSpielerPunkte( tmp->getTeam(), tmp->getSpielerNummer() );
+		ssdgs->linienLänge = tmp->getLinienLänge();
+		ssdgs->zeitAmLeben = tmp->getZeitAmLeben();
+		ssdgs->zeitTod = tmp->getZeitTod();
+		ssdgs->kills = tmp->getKills();
+		ssdgs->tode = tmp->getTode();
+		this->ssdgs->set( ssdgs, i );
+	}
+	Array< int > teams;
+	for( int i = 0; i < teamAnzahl; i++ )
+	{
+		for( int j = 0; j < spielerAnzahl; j++ )
+		{
+			if( teams.getWertIndex( spieler->z( j )->getTeam() ) < 0 )
+			{
+				teams.set( spieler->z( j )->getTeam(), i );
+				break;
+			}
+		}
+		if( teams.hat( i ) )
+		{
+			SSDGesamtTeam *ssdgt = new SSDGesamtTeam();
+			ssdgt->teamNummer = teams.get( i );
+			for( int j = 0; j < spielerAnzahl; j++ )
+			{
+				VideoSpieler *tmp = spieler->z( j );
+				if( tmp->getTeam() == ssdgt->teamNummer )
+				{
+					ssdgt->teamName.setText( tmp->zTeamName()->getText() );
+					ssdgt->teamFarbe = tmp->getTeamFarbe();
+					break;
+				}
+			}
+			ssdgt->gewonneneRunden = 0;
+			for( int j = 0; j < rundenAnzahl; j++ )
+			{
+				if( rundenSieger.get( j ) == ssdgt->teamNummer )
+					ssdgt->gewonneneRunden++;
+			}
+			ssdgt->punkte = 0;
+			ssdgt->linienLänge = 0;
+			ssdgt->kills = 0;
+			ssdgt->tode = 0;
+			for( int j = 0; j < spielerAnzahl; j++ )
+			{
+				VideoSpieler *tmp = spieler->z( j );
+				if( tmp->getTeam() == ssdgt->teamNummer )
+				{
+					ssdgt->punkte += bestenliste->getSpielerPunkte( tmp->getTeam(), tmp->getSpielerNummer() );
+					ssdgt->linienLänge += tmp->getLinienLänge();
+					ssdgt->kills += tmp->getKills();
+					ssdgt->tode += tmp->getTode();
+				}
+			}
+			this->ssdgt->set( ssdgt, i );
+		}
+	}
+	for( int i = 0; i < rundenAnzahl; i++ )
+	{
+		SSDRunde *ssdr = new SSDRunde();
+		ssdr->rundenNummer = i;
+		ssdr->rundenDauer = rundenDauer.get( i );
+		ssdr->rundenSieger = rundenSieger.get( i );
+		ssdr->rundenBild.neuBild( map->zMap( i )->getBreite(), map->zMap( i )->getHeight(), 0 );
+		ssdr->rundenBild.drawBild( 0, 0, map->zMap( i )->getBreite(), map->zMap( i )->getHeight(), *map->zMap( i ) );
+		ssdr->spielfeldNutzung = 0;
+		int *rbBuff = ssdr->rundenBild.getBuffer();
+		for( int j = 0; j < ssdr->rundenBild.getBreite() * ssdr->rundenBild.getHeight(); j++ )
+		{
+			if( rbBuff[ j ] )
+				ssdr->spielfeldNutzung++;
+		}
+		ssdr->spielfeldNutzung = (int)( ( ssdr->spielfeldNutzung / ( (double)( ssdr->rundenBild.getBreite() * ssdr->rundenBild.getHeight() ) / 25 ) ) * 100 );
+		for( int j = 0; j < spielerAnzahl; j++ )
+		{
+			VideoSpieler *tmp = spieler->z( j );
+			SSDRundeSpieler *ssdrs = new SSDRundeSpieler();
+			ssdrs->spielerNummer = tmp->getSpielerNummer();
+			ssdrs->spielerName.setText( tmp->zName()->getText() );
+			ssdrs->teamName.setText( tmp->zTeamName()->getText() );
+			ssdrs->spielerFarbe = tmp->getFarbe();
+			ssdrs->teamFarbe = tmp->getTeamFarbe();
+			ssdrs->linienLänge = tmp->getLinienLänge( i );
+			ssdrs->kills = tmp->getKills( i );
+			ssdrs->todesZeit = tmp->getTodesZeit( i );
+			ssdr->spieler.set( ssdrs, j );
+		}
+		for( int j = 0; j < teamAnzahl; j++ )
+		{
+			SSDRundeTeam *ssdrt = new SSDRundeTeam();
+			ssdrt->teamNummer = teams.get( j );
+			for( int k = 0; k < spielerAnzahl; k++ )
+			{
+				if( spieler->z( k )->getTeam() == ssdrt->teamNummer )
+				{
+					ssdrt->teamName.setText( spieler->z( k )->zTeamName()->getText() );
+					ssdrt->teamFarbe = spieler->z( k )->getTeamFarbe();
+					break;
+				}
+			}
+			ssdrt->ergebnis = rundenSieger.get( i ) == ssdrt->teamNummer;
+			ssdrt->linienLänge = 0;
+			ssdrt->kills = 0;
+			ssdrt->tode = 0;
+			for( int k = 0; k < spielerAnzahl; k++ )
+			{
+				VideoSpieler *tmp = spieler->z( j );
+				if( tmp->getTeam() == ssdrt->teamNummer )
+				{
+					ssdrt->linienLänge += tmp->getLinienLänge( i );
+					ssdrt->kills += tmp->getKills( i );
+					ssdrt->tode += tmp->getTodesZeit( i ) != 0;
+				}
+			}
+			ssdr->teams.set( ssdrt, j );
+		}
+		this->ssdr->set( ssdr, i );
+	}
+}
+
+// Destruktor
+StatistikLeser::~StatistikLeser()
+{
+	nachrichten->release();
+	bestenliste->release();
+	map->release();
+	spieler->release();
+	ssdgs->release();
+	ssdgt->release();
+	ssdr->release();
+}
+
+// constant
+bool StatistikLeser::hatFehler() const
+{
+	return fehler;
+}
+
+int StatistikLeser::getSpielerAnzahl() const
+{
+	return spielerAnzahl;
+}
+
+int StatistikLeser::getTeamAnzahl() const
+{
+	return teamAnzahl;
+}
+
+int StatistikLeser::getRundenAnzahl() const
+{
+	return rundenAnzahl;
+}
+
+SSDGesamtSpieler *StatistikLeser::getSSDGS( int index ) const
+{
+	return ssdgs->get( index );
+}
+
+SSDGesamtTeam *StatistikLeser::getSSDGT( int index ) const
+{
+	return ssdgt->get( index );
+}
+
+SSDRunde *StatistikLeser::getSSDR( int runde ) const
+{
+	return ssdr->get( runde );
+}
+
+// Reference Counting
+StatistikLeser *StatistikLeser::getThis()
+{
+	ref++;
+	return this;
+}
+
+StatistikLeser *StatistikLeser::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 44 - 0
Linie/HistorieStatistik/StatistikLeser.h

@@ -0,0 +1,44 @@
+#ifndef StatistikLeser_H
+#define StatistikLeser_H
+
+#include "../Aufzeichnung/Bestenliste/VideoBestenliste.h"
+#include "../Aufzeichnung/Karte/VideoKarte.h"
+#include "../Aufzeichnung/Spieler/VideoSpieler.h"
+#include "../Aufzeichnung/Nachricht/VideoNachricht.h"
+#include "../SpielStatistik/SpielStatistikDaten.h"
+
+class StatistikLeser
+{
+private:
+	SpielNachricht *nachrichten;
+	VideoBestenliste *bestenliste;
+	VideoKarte *map;
+	RCArray< VideoSpieler > *spieler;
+	Array< SSDGesamtSpieler* > *ssdgs;
+	Array< SSDGesamtTeam* > *ssdgt;
+	Array< SSDRunde* > *ssdr;
+	int spielerAnzahl;
+	int teamAnzahl;
+	int rundenAnzahl;
+	bool fehler;
+	int ref;
+
+public:
+	// Konstruktor
+	StatistikLeser( int spielId );
+	// Destruktor
+	~StatistikLeser();
+	// constant
+	bool hatFehler() const;
+	int getSpielerAnzahl() const;
+	int getTeamAnzahl() const;
+	int getRundenAnzahl() const;
+	SSDGesamtSpieler *getSSDGS( int index ) const;
+	SSDGesamtTeam *getSSDGT( int index ) const;
+	SSDRunde *getSSDR( int runde ) const;
+	// Reference Counting
+	StatistikLeser *getThis();
+	StatistikLeser *release();
+};
+
+#endif

+ 218 - 0
Linie/Initialisierung/Initialisierung.cpp

@@ -0,0 +1,218 @@
+#include "Initialisierung.h"
+#include <ToolTip.h>
+#include <Bildschirm.h>
+#include <MausEreignis.h>
+
+Knopf *initKnopf( int x, int y, int br, int hö, Schrift *zSchrift, int style, char *titel )
+{
+	Knopf *ret = new Knopf();
+	ret->addStyle( style );
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	if( zSchrift )
+		ret->setSchriftZ( zSchrift->getThis() );
+	if( titel )
+	    ret->setText( titel );
+	return ret;
+}
+
+KontrollKnopf *initKontrollKnopf( int x, int y, int br, int hö, Schrift *zSchrift, int style, char *txt )
+{
+	KontrollKnopf *ret = new KontrollKnopf();
+	ret->setStyle( style );
+	if( zSchrift )
+		ret->setSchriftZ( zSchrift->getThis() );
+	if( txt )
+	{
+		ret->setText( txt );
+		ret->setSText( txt );
+	}
+	ret->setSFarbe( 0xFFFFFFFF );
+	ret->setSSize( 12 );
+	if( ret->hatStyle( TextFeld::Style::Buffered ) )
+	{
+		ret->setAlphaFeldFarbe( 0x5500FF00 );
+		ret->setAlphaFeldStrength( -5 );
+	}
+	if( ret->hatStyle( TextFeld::Style::Rahmen ) )
+	{
+		ret->setLinienRahmenBreite( 1 );
+		ret->setLinienRahmenFarbe( 0xFF00FF00 );
+	}
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	ret->loadData( "data/bilder/system.ltdb" );
+	return ret;
+}
+
+Fenster *initFenster( int x, int y, int br, int hö, Schrift *zSchrift, int style, char *titel )
+{
+	Fenster *ret = new Fenster();
+	ret->setStyle( style );
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	if( ret->hatStyle( Fenster::Style::Rahmen ) )
+	{
+		ret->setRBreite( 1 );
+		ret->setRFarbe( 0xFFFFFFFF );
+	}
+	if( ret->hatStyle( Fenster::Style::Titel ) )
+	{
+		if( titel )
+		    ret->setTitel( titel );
+		if( zSchrift )
+		    ret->setTSchriftZ( zSchrift->getThis() );
+		ret->setTSFarbe( 0xFFFFFFFF );
+		ret->zTTextFeld()->setSize( 0, 20 );
+		ret->zTTextFeld()->addStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center | TextFeld::Style::Rahmen );
+		ret->setTRFarbe( 0xFF00FF00 );
+		ret->setTRBreite( 1 );
+		if( ret->hatStyle( Fenster::Style::TitelBuffered ) )
+		{
+			ret->setTAfFarbe( 0x1000FF00 );
+			ret->setTAfStrength( -15 );
+		}
+	}
+	return ret;
+}
+
+TextFeld *initTextFeld( int x, int y, int br, int hö, Schrift *zSchrift, int style, char *txt )
+{
+	TextFeld *ret = new TextFeld();
+	ret->setStyle( style );
+	if( zSchrift )
+	    ret->setSchriftZ( zSchrift->getThis() );
+	if( txt )
+	   ret->setText( txt );
+	ret->setSchriftFarbe( 0xFFFFFFFF );
+	ret->setSchriftSize( 12 );
+	if( ret->hatStyle( TextFeld::Style::Buffered ) )
+	{
+		ret->setAlphaFeldFarbe( 0x5500FF00 );
+		ret->setAlphaFeldStrength( -5 );
+	}
+	if( ret->hatStyle( TextFeld::Style::Rahmen ) )
+	{
+		ret->setLinienRahmenBreite( 1 );
+		ret->setLinienRahmenFarbe( 0xFF00FF00 );
+	}
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	return ret;
+}
+
+BildZ *initBildZ( int x, int y, int br, int hö, int style, Bild *b )
+{
+	BildZ *ret = new BildZ();
+	ret->setStyle( style );
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	if( b )
+		ret->setBildZ( b );
+	if( ( style | BildZ::Style::Rahmen ) == style )
+	{
+		ret->setLinienRahmenBreite( 1 );
+		ret->setLinienRahmenFarbe( 0xFFFFFFFF );
+	}
+	return ret;
+}
+
+AuswahlBox *initAuswahlBox( int x, int y, int br, int hö, Schrift *zSchrift, int style, std::initializer_list< char * > values )
+{
+	AuswahlBox *ret = new AuswahlBox();
+	ret->setStyle( style );
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	if( ( style | AuswahlBox::Style::Hintergrund ) == style )
+		ret->setHintergrundFarbe( 0xFF000000 );
+	if( ( style | AuswahlBox::Style::Erlaubt ) == style )
+		ret->setMausEreignis( _ret1ME );
+	if( zSchrift )
+	    ret->setSchriftZ( zSchrift->getThis() );
+	if( ( style | AuswahlBox::Style::Rahmen ) == style )
+	{
+		ret->setLinienRahmenBreite( 1 );
+		ret->setLinienRahmenFarbe( 0xFFFFFFFF );
+	}
+	if( ( style | AuswahlBox::Style::MaxHeight ) == style )
+		ret->setMaxAuskappHeight( 100 );
+	if( ( style | AuswahlBox::Style::MausRahmen ) == style )
+	{
+		ret->setMausRahmenBreite( 1 );
+		ret->setMausRahmenFarbe( 0xFF005500 );
+	}
+	if( ( style | AuswahlBox::Style::MausBuffer ) == style )
+	{
+		ret->setMausAlphaFeldFarbe( 0x00008700 );
+		ret->setMausAlphaFeldStrength( -8 );
+	}
+	if( ( style | AuswahlBox::Style::AuswahlRahmen ) == style )
+	{
+		ret->setAuswRahmenBreite( 1 );
+		ret->setAuswRahmenFarbe( 0xFF00FF00 );
+	}
+	if( ( style | AuswahlBox::Style::AuswahlBuffer ) == style )
+	{
+		ret->setAuswAlphaFeldFarbe( 0x0000FF00 );
+		ret->setAuswAlphaFeldStrength( -8 );
+	}
+	for( auto i = values.begin(); i != values.end(); i++ )
+	{
+		ret->addEintrag( *i );
+	}
+	return ret;
+}
+
+ObjTabelle *initObjTabelle( int x, int y, int br, int hö, Schrift *zSchrift, int style, std::initializer_list< OBJTabelleSpalteIni > spalten, int überschriftHöhe )
+{
+	ObjTabelle *ret = new ObjTabelle();
+	ret->setStyle( style );
+	ret->setPosition( x, y );
+	ret->setSize( br, hö );
+	if( ( style | ObjTabelle::Style::Erlaubt ) == style )
+		ret->setMausEreignis( _ret1ME );
+	if( ( style | ObjTabelle::Style::Rahmen ) == style )
+	{
+		ret->setLinienRahmenBreite( 1 );
+		ret->setLinienRahmenFarbe( 0xFFFFFFFF );
+	}
+	if( ( style | ObjTabelle::Style::Raster ) == style )
+	{
+		ret->setRasterBreite( 1 );
+		ret->setRasterFarbe( 0xFFFFFFFF );
+	}
+	if( ( style | ObjTabelle::Style::VScroll ) == style )
+		ret->setVertikalKlickScroll( 5 );
+	if( ( style | ObjTabelle::Style::HScroll ) == style )
+		ret->setHorizontalKlickScroll( 5 );
+	for( auto i = spalten.begin(); i != spalten.end(); i++ )
+	{
+		ret->addSpalte( i->name );
+		ret->setSpaltenBreite( i->name, i->breite );
+		if( ( style | ObjTabelle::Style::SpaltenBreiteMin ) == style )
+			ret->setMinSpaltenBreite( i->name, i->minBreite );
+		if( ( style | ObjTabelle::Style::SpaltenBreiteMax ) == style )
+			ret->setMaxSpaltenBreite( i->name, i->maxBreite );
+		if( überschriftHöhe )
+		{
+			if( ret->getZeilenNummer( "Überschrift" ) < 0 )
+			{
+				ret->addZeile( 0, "Überschrift" );
+				ret->setZeilenHeight( 0, 20 );
+			}
+			ret->setZeichnungZ( i->name, "Überschrift", initTextFeld( 0, 0, i->breite, 20, zSchrift, TextFeld::Style::Text, i->name ) );
+		}
+	}
+	return ret;
+}
+
+void initToolTip( Zeichnung *obj, const char *txt, Schrift *schrift, Bildschirm *zBs )
+{
+	obj->setToolTipText( txt, zBs );
+	if( schrift )
+	    obj->zToolTip()->setSchriftZ( schrift );
+	obj->zToolTip()->addStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Rahmen | TextFeld::Style::Hintergrund | TextFeld::Style::HAlpha | TextFeld::Style::Mehrzeilig );
+	obj->zToolTip()->setHintergrundFarbe( 0xA0000000 );
+	obj->zToolTip()->setLinienRahmenFarbe( 0xFFFFFFFF );
+	obj->zToolTip()->setSchriftFarbe( 0xFFFFFFFF );
+}

+ 32 - 0
Linie/Initialisierung/Initialisierung.h

@@ -0,0 +1,32 @@
+#ifndef Initialisierung_H
+#define Initialisierung_H
+
+#include <Knopf.h>
+#include <Fenster.h>
+#include <TextFeld.h>
+#include <Schrift.h>
+#include <Bild.h>
+#include <AuswahlBox.h>
+#include <Tabelle.h>
+#include <initializer_list>
+
+using namespace Framework;
+
+struct OBJTabelleSpalteIni
+{
+	char *name;
+	int breite;
+	int minBreite;
+	int maxBreite;
+};
+
+ Knopf *initKnopf( int x, int y, int br, int hö, Schrift *zSchrift, int style, char *titel );
+ KontrollKnopf *initKontrollKnopf( int x, int y, int br, int hö, Schrift *zSchrift, int style, char *txt );
+ Fenster *initFenster( int x, int y, int br, int hö, Schrift *zSchrift, int style, char *titel );
+ TextFeld *initTextFeld( int x, int y, int br, int hö, Schrift *zSchrift, int style, char *txt );
+ BildZ *initBildZ( int x, int y, int br, int hö, int style, Bild *b );
+ AuswahlBox *initAuswahlBox( int x, int y, int br, int hö, Schrift *zSchrift, int style, std::initializer_list< char * > values );
+ ObjTabelle *initObjTabelle( int x, int y, int br, int hö, Schrift *zSchrift, int style, std::initializer_list< OBJTabelleSpalteIni > spalten, int überschriftHöhe );
+ void initToolTip( Zeichnung *obj, const char *txt, Schrift *schrift, Bildschirm *zBs );
+
+#endif

+ 235 - 0
Linie/Linie.vcxproj

@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup Label="ProjectConfigurations">
+    <ProjectConfiguration Include="Debug|Win32">
+      <Configuration>Debug</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Debug|x64">
+      <Configuration>Debug</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|Win32">
+      <Configuration>Release</Configuration>
+      <Platform>Win32</Platform>
+    </ProjectConfiguration>
+    <ProjectConfiguration Include="Release|x64">
+      <Configuration>Release</Configuration>
+      <Platform>x64</Platform>
+    </ProjectConfiguration>
+  </ItemGroup>
+  <PropertyGroup Label="Globals">
+    <ProjectGuid>{B2E0B9EF-0131-42B7-A7AC-A5A74C7547A7}</ProjectGuid>
+    <Keyword>Win32Proj</Keyword>
+    <RootNamespace>Linie</RootNamespace>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>Unicode</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>true</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
+    <ConfigurationType>DynamicLibrary</ConfigurationType>
+    <UseDebugLibraries>false</UseDebugLibraries>
+    <PlatformToolset>v141</PlatformToolset>
+    <WholeProgramOptimization>true</WholeProgramOptimization>
+    <CharacterSet>MultiByte</CharacterSet>
+  </PropertyGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+  <ImportGroup Label="ExtensionSettings">
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
+    <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+  </ImportGroup>
+  <PropertyGroup Label="UserMacros" />
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>..\..\..\..\..\Allgemein\Framework;..\..\..\..\Klient\Include;..\..\..\..\..\Allgemein\Network\Network;..\..\..\..\..\Allgemein\GSL\GSL\Include;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <LinkIncremental>true</LinkIncremental>
+    <IncludePath>..\..\..\..\..\Allgemein\Framework;..\..\..\..\Klient\Include;..\..\..\..\..\Allgemein\Network\Network;..\..\..\..\..\Allgemein\GSL\GSL\Include;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\..\..\Allgemein\Framework\x64\Debug;$(LibraryPath)</LibraryPath>
+    <CustomBuildBeforeTargets>
+    </CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>..\..\..\..\..\Allgemein\Framework;..\..\..\..\Klient\Include;..\..\..\..\..\Allgemein\Network\Network;..\..\..\..\..\Allgemein\GSL\GSL\Include;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\..\..\Allgemein\Framework\Release;$(LibraryPath)</LibraryPath>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <LinkIncremental>false</LinkIncremental>
+    <IncludePath>..\..\..\..\..\Allgemein\Framework;..\..\..\..\Klient\Include;..\..\..\..\..\Allgemein\Network\Network;..\..\..\..\..\Allgemein\GSL\GSL\Include;$(IncludePath)</IncludePath>
+    <LibraryPath>..\..\..\..\..\Allgemein\Framework\x64\Release;$(LibraryPath)</LibraryPath>
+    <CustomBuildBeforeTargets>Build</CustomBuildBeforeTargets>
+  </PropertyGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LINIE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+    </Link>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <ClCompile>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <WarningLevel>Level3</WarningLevel>
+      <Optimization>Disabled</Optimization>
+      <PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;LINIE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <AdditionalDependencies>framework.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <CustomBuildStep>
+      <Command>copy "..\x64\Debug\Linie.dll" "..\..\..\..\Klient\Fertig\Debug\Spiele\x64\Linie\bin\Linie.dll";%(Outputs)</Command>
+    </CustomBuildStep>
+    <CustomBuildStep>
+      <Outputs>kopieren;%(Outputs)</Outputs>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LINIE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>framework.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <CustomBuildStep>
+      <Command>copy "..\Release\Linie.dll" "..\..\..\..\Klient\Fertig\Spiele\x32\Linie\bin\Linie.dll"</Command>
+    </CustomBuildStep>
+    <CustomBuildStep>
+      <Outputs>kopieren...;%(Outputs)</Outputs>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
+    <ClCompile>
+      <WarningLevel>Level3</WarningLevel>
+      <PrecompiledHeader>
+      </PrecompiledHeader>
+      <Optimization>MaxSpeed</Optimization>
+      <FunctionLevelLinking>true</FunctionLevelLinking>
+      <IntrinsicFunctions>true</IntrinsicFunctions>
+      <PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;LINIE_EXPORTS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+      <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+    </ClCompile>
+    <Link>
+      <SubSystem>Windows</SubSystem>
+      <GenerateDebugInformation>true</GenerateDebugInformation>
+      <EnableCOMDATFolding>true</EnableCOMDATFolding>
+      <OptimizeReferences>true</OptimizeReferences>
+      <AdditionalDependencies>framework.lib;%(AdditionalDependencies)</AdditionalDependencies>
+    </Link>
+    <CustomBuildStep>
+      <Command>copy "..\x64\Release\Linie.dll" "..\..\..\..\Klient\Fertig\Spiele\x64\Linie\bin\linie.dll</Command>
+    </CustomBuildStep>
+    <CustomBuildStep>
+      <Outputs>kopieren...;%(Outputs)</Outputs>
+    </CustomBuildStep>
+  </ItemDefinitionGroup>
+  <ItemGroup>
+    <ClInclude Include="Aufzeichnung\Aufzeichnung.h" />
+    <ClInclude Include="Aufzeichnung\Bestenliste\VideoBestenliste.h" />
+    <ClInclude Include="Aufzeichnung\Chat\VideoChat.h" />
+    <ClInclude Include="Aufzeichnung\Ende\VideoEnde.h" />
+    <ClInclude Include="Aufzeichnung\Kamera\VideoKamera.h" />
+    <ClInclude Include="Aufzeichnung\Karte\VideoKarte.h" />
+    <ClInclude Include="Aufzeichnung\Nachricht\VideoNachricht.h" />
+    <ClInclude Include="Aufzeichnung\Spieler\VideoSpieler.h" />
+    <ClInclude Include="Aufzeichnung\Steuerung\VideoSteuerung.h" />
+    <ClInclude Include="Aufzeichnung\VideoDaten\VideoDaten.h" />
+    <ClInclude Include="HistorieStatistik\HistorieStatistik.h" />
+    <ClInclude Include="HistorieStatistik\StatistikLeser.h" />
+    <ClInclude Include="Initialisierung\Initialisierung.h" />
+    <ClInclude Include="Netzwerk\STKNachricht.h" />
+    <ClInclude Include="SpielStatistik\Chat\StatistikChat.h" />
+    <ClInclude Include="SpielStatistik\Runde\StatistikRunde.h" />
+    <ClInclude Include="SpielStatistik\SpielStatistik.h" />
+    <ClInclude Include="SpielStatistik\SpielStatistikDaten.h" />
+    <ClInclude Include="SpielStatistik\Tabelle\StatistikTabelle.h" />
+    <ClInclude Include="Spiel\Bestenliste\Bestenliste.h" />
+    <ClInclude Include="Spiel\Chat\Chat.h" />
+    <ClInclude Include="Spiel\Ende\Ende.h" />
+    <ClInclude Include="Spiel\Ende\RundenEnde.h" />
+    <ClInclude Include="Spiel\Kamera\Kamera.h" />
+    <ClInclude Include="Spiel\Karte\Karte.h" />
+    <ClInclude Include="Spiel\Spieler\Spieler.h" />
+    <ClInclude Include="Spiel\SpielKlasse.h" />
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Aufzeichnung\Aufzeichnung.cpp" />
+    <ClCompile Include="Aufzeichnung\Bestenliste\VideoBestenliste.cpp" />
+    <ClCompile Include="Aufzeichnung\Chat\VideoChat.cpp" />
+    <ClCompile Include="Aufzeichnung\Ende\VideoEnde.cpp" />
+    <ClCompile Include="Aufzeichnung\Kamera\VideoKamera.cpp" />
+    <ClCompile Include="Aufzeichnung\Karte\VideoKarte.cpp" />
+    <ClCompile Include="Aufzeichnung\Nachricht\VideoNachricht.cpp" />
+    <ClCompile Include="Aufzeichnung\Spieler\VideoSpieler.cpp" />
+    <ClCompile Include="Aufzeichnung\Steuerung\VideoSteuerung.cpp" />
+    <ClCompile Include="HistorieStatistik\HistorieStatistik.cpp" />
+    <ClCompile Include="HistorieStatistik\StatistikLeser.cpp" />
+    <ClCompile Include="Initialisierung\Initialisierung.cpp" />
+    <ClCompile Include="Netzwerk\STKNachricht.cpp" />
+    <ClCompile Include="SpielStatistik\Chat\StatistikChat.cpp" />
+    <ClCompile Include="SpielStatistik\Runde\StatistikRunde.cpp" />
+    <ClCompile Include="SpielStatistik\SpielStatistik.cpp" />
+    <ClCompile Include="SpielStatistik\Tabelle\StatistikTabelle.cpp" />
+    <ClCompile Include="Spiel\Bestenliste\Bestenliste.cpp" />
+    <ClCompile Include="Spiel\Chat\Chat.cpp" />
+    <ClCompile Include="Spiel\Ende\Ende.cpp" />
+    <ClCompile Include="Spiel\Ende\RundenEnde.cpp" />
+    <ClCompile Include="Spiel\Kamera\Kamera.cpp" />
+    <ClCompile Include="Spiel\Karte\Karte.cpp" />
+    <ClCompile Include="Spiel\Spieler\Spieler.cpp" />
+    <ClCompile Include="Spiel\SpielKlasse.cpp" />
+    <ClCompile Include="Start\DllStart.cpp" />
+  </ItemGroup>
+  <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+  <ImportGroup Label="ExtensionTargets">
+  </ImportGroup>
+</Project>

+ 180 - 0
Linie/Linie.vcxproj.filters

@@ -0,0 +1,180 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+  <ItemGroup>
+    <Filter Include="Quelldateien">
+      <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+      <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+    </Filter>
+    <Filter Include="Headerdateien">
+      <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+      <Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
+    </Filter>
+    <Filter Include="Ressourcendateien">
+      <UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
+      <Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
+    </Filter>
+  </ItemGroup>
+  <ItemGroup>
+    <ClInclude Include="Spiel\SpielKlasse.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Spiel\Spieler\Spieler.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Spiel\Karte\Karte.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Spiel\Chat\Chat.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Spiel\Ende\Ende.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Spiel\Bestenliste\Bestenliste.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Spiel\Ende\RundenEnde.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Netzwerk\STKNachricht.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Spiel\Kamera\Kamera.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielStatistik\SpielStatistik.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Initialisierung\Initialisierung.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielStatistik\SpielStatistikDaten.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielStatistik\Chat\StatistikChat.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielStatistik\Runde\StatistikRunde.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="SpielStatistik\Tabelle\StatistikTabelle.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="HistorieStatistik\HistorieStatistik.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Aufzeichnung\Aufzeichnung.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Aufzeichnung\VideoDaten\VideoDaten.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Aufzeichnung\Nachricht\VideoNachricht.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Aufzeichnung\Steuerung\VideoSteuerung.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Aufzeichnung\Bestenliste\VideoBestenliste.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Aufzeichnung\Chat\VideoChat.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Aufzeichnung\Ende\VideoEnde.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Aufzeichnung\Kamera\VideoKamera.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Aufzeichnung\Karte\VideoKarte.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="Aufzeichnung\Spieler\VideoSpieler.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+    <ClInclude Include="HistorieStatistik\StatistikLeser.h">
+      <Filter>Headerdateien</Filter>
+    </ClInclude>
+  </ItemGroup>
+  <ItemGroup>
+    <ClCompile Include="Spiel\SpielKlasse.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Start\DllStart.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Spiel\Spieler\Spieler.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Spiel\Karte\Karte.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Spiel\Chat\Chat.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Spiel\Ende\Ende.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Spiel\Bestenliste\Bestenliste.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Spiel\Ende\RundenEnde.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Netzwerk\STKNachricht.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Spiel\Kamera\Kamera.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="SpielStatistik\SpielStatistik.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Initialisierung\Initialisierung.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="SpielStatistik\Chat\StatistikChat.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="SpielStatistik\Runde\StatistikRunde.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="HistorieStatistik\HistorieStatistik.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="SpielStatistik\Tabelle\StatistikTabelle.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Aufzeichnung\Aufzeichnung.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Aufzeichnung\Steuerung\VideoSteuerung.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Aufzeichnung\Bestenliste\VideoBestenliste.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Aufzeichnung\Chat\VideoChat.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Aufzeichnung\Ende\VideoEnde.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Aufzeichnung\Nachricht\VideoNachricht.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Aufzeichnung\Kamera\VideoKamera.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Aufzeichnung\Karte\VideoKarte.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="Aufzeichnung\Spieler\VideoSpieler.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+    <ClCompile Include="HistorieStatistik\StatistikLeser.cpp">
+      <Filter>Quelldateien</Filter>
+    </ClCompile>
+  </ItemGroup>
+</Project>

+ 62 - 0
Linie/Netzwerk/STKNachricht.cpp

@@ -0,0 +1,62 @@
+#include "STKNachricht.h"
+
+// Inhalt der STKNachricht Klasse aus STKNachricht.h
+// Konstruktor
+STKNachricht::STKNachricht( int län, char *nachricht )
+{
+	verarbeitet = 0;
+	spielZeit = *(double*)nachricht;
+	this->län = län - 8;
+	this->nachricht = new char[ this->län ];
+	for( int i = 0; i < this->län; i++ )
+		this->nachricht[ i ] = nachricht[ i + 8 ];
+	ref = 1;
+}
+
+// Destruktor
+STKNachricht::~STKNachricht()
+{
+	delete[] nachricht;
+}
+
+// nicht constant
+void STKNachricht::setVerarbeitet()
+{
+	verarbeitet = 1;
+}
+
+// constant
+bool STKNachricht::istVerarbeitet() const
+{
+	return verarbeitet;
+}
+
+double STKNachricht::getSpielZeit() const
+{
+	return spielZeit;
+}
+
+int STKNachricht::getLength() const
+{
+	return län;
+}
+
+char *STKNachricht::getNachricht() const
+{
+	return nachricht;
+}
+
+// Reference Counting
+STKNachricht *STKNachricht::getThis()
+{
+	ref++;
+	return this;
+}
+
+STKNachricht *STKNachricht::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 30 - 0
Linie/Netzwerk/STKNachricht.h

@@ -0,0 +1,30 @@
+#ifndef STKNachricht_H
+#define STKNachricht_H
+
+class STKNachricht
+{
+private:
+	double spielZeit;
+	int län;
+	char *nachricht;
+	bool verarbeitet;
+	int ref;
+
+public:
+	// Konstruktor
+	STKNachricht( int län, char *nachricht );
+	// Destruktor
+	~STKNachricht();
+	// nicht constant
+	void setVerarbeitet();
+	// constant
+	bool istVerarbeitet() const;
+	double getSpielZeit() const;
+	int getLength() const;
+	char *getNachricht() const;
+	// Reference Counting
+	STKNachricht *getThis();
+	STKNachricht *release();
+};
+
+#endif

+ 654 - 0
Linie/Spiel/Bestenliste/Bestenliste.cpp

@@ -0,0 +1,654 @@
+#include "Bestenliste.h"
+#include "..\Spieler\Spieler.h"
+#include <Rahmen.h>
+#include <Schrift.h>
+#include <Punkt.h>
+#include <Scroll.h>
+
+// Inhalt der BLSpieler Klasse aus Bestenliste.h
+// Konstruktor
+BLSpieler::BLSpieler( int sNum, int farbe, Schrift *zS )
+{
+	this->sNum = sNum;
+	this->farbe = farbe;
+	p = 0;
+	nP = 0;
+
+	rahmen = new LRahmen();
+	rahmen->setFarbe( farbe );
+	rahmen->setRamenBreite( 1 );
+	rahmen->setSize( 400, 20 );
+
+	name = new TextFeld();
+	name->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	name->setSchriftZ( zS->getThis() );
+	name->setSchriftFarbe( farbe );
+	name->setSchriftSize( 12 );
+	name->setSize( 100, 20 );
+	name->setPosition( 0, 0 );
+	name->setText( "" );
+
+	punkte = new TextFeld();
+	punkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	punkte->setSchriftZ( zS->getThis() );
+	punkte->setSchriftFarbe( farbe );
+	punkte->setSchriftSize( 12 );
+	punkte->setSize( 100, 20 );
+	punkte->setPosition( 100, 0 );
+	punkte->setText( "" );
+
+	neuPunkte = new TextFeld();
+	neuPunkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	neuPunkte->setSchriftZ( zS->getThis() );
+	neuPunkte->setSchriftFarbe( farbe );
+	neuPunkte->setSchriftSize( 12 );
+	neuPunkte->setSize( 100, 20 );
+	neuPunkte->setPosition( 200, 0 );
+	neuPunkte->setText( "" );
+
+	status = new TextFeld();
+	status->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	status->setSchriftZ( zS->getThis() );
+	status->setSchriftFarbe( 0xFF00FF00 );
+	status->setSchriftSize( 12 );
+	status->setSize( 100, 20 );
+	status->setPosition( 300, 0 );
+	status->setText( "lebt" );
+
+	ref = 1;
+}
+
+// Destruktor
+BLSpieler::~BLSpieler()
+{
+	rahmen->release();
+	name->release();
+	punkte->release();
+	neuPunkte->release();
+	status->release();
+}
+
+// nicht constant
+bool BLSpieler::updateStatus( Spieler *zSpieler )
+{
+	if( sNum != zSpieler->getSpielerNummer() )
+		return 0;
+	if( zSpieler->istAmLeben() )
+	{
+		status->setSchriftFarbe( 0xFF00FF00 );
+		status->setText( "lebt" );
+	}
+	else
+	{
+		status->setSchriftFarbe( 0xFFFF0000 );
+		status->setText( "tot" );
+	}
+	name->setText( zSpieler->zName()->getText() );
+	return 1;
+}
+
+void BLSpieler::setPunkte( int p )
+{
+	this->p = p;
+}
+
+void BLSpieler::addPunkt( bool plus )
+{
+	if( plus )
+		nP++;
+	else
+		nP--;
+}
+
+void BLSpieler::updatePunkte()
+{
+	p += nP;
+	nP = 0;
+}
+
+void BLSpieler::render( int y, Bild &zRObj )
+{
+	if( !zRObj.setDrawOptions( 1, y, rahmen->getBreite(), rahmen->getHeight() ) )
+		return;
+	punkte->setText( "" );
+	if( nP == 0 )
+	{
+		neuPunkte->setText( "" );
+		neuPunkte->setSchriftFarbe( 0xFFFFFFFF );
+	}
+	else if( nP > 0 )
+	{
+		neuPunkte->setText( "+" );
+		neuPunkte->setSchriftFarbe( 0xFF00FF00 );
+	}
+	else
+	{
+		neuPunkte->setText( "" );
+		neuPunkte->setSchriftFarbe( 0xFFFF0000 );
+	}
+	punkte->zText()->append( p );
+	neuPunkte->zText()->append( nP );
+	rahmen->render( zRObj );
+	name->render( zRObj );
+	punkte->render( zRObj );
+	neuPunkte->render( zRObj );
+	status->render( zRObj );
+	zRObj.releaseDrawOptions();
+}
+
+// constant
+int BLSpieler::getSpielerNummer() const
+{
+	return sNum;
+}
+
+int BLSpieler::getPunkte() const
+{
+	return p + nP;
+}
+
+// Reference Counting
+BLSpieler *BLSpieler::getThis()
+{
+	ref++;
+	return this;
+}
+
+BLSpieler *BLSpieler::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+// Inhalt der BLTeam Klasse aus Bestenliste.h
+// Konstruktor
+BLTeam::BLTeam( int id, int farbe, Schrift *s )
+{
+	teamId = id;
+	spielerAnzahl = 0;
+	p = 0;
+	mP = 0;
+	nP = 0;
+	this->farbe = farbe;
+	schrift = s;
+
+	rahmen = new LRahmen();
+	rahmen->setFarbe( farbe );
+	rahmen->setRamenBreite( 1 );
+
+	spieler = new RCArray< BLSpieler >();
+
+	name = new TextFeld();
+	name->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	name->setSchriftZ( s->getThis() );
+	name->setSchriftFarbe( farbe );
+	name->setSchriftSize( 12 );
+	name->setSize( 100, 20 );
+	name->setPosition( 0, 0 );
+	name->setText( "" );
+
+	punkte = new TextFeld();
+	punkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	punkte->setSchriftZ( s->getThis() );
+	punkte->setSchriftFarbe( farbe );
+	punkte->setSchriftSize( 12 );
+	punkte->setSize( 100, 20 );
+	punkte->setPosition( 100, 0 );
+	punkte->setText( "" );
+
+	neuPunkte = new TextFeld();
+	neuPunkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	neuPunkte->setSchriftZ( s->getThis() );
+	neuPunkte->setSchriftFarbe( farbe );
+	neuPunkte->setSchriftSize( 12 );
+	neuPunkte->setSize( 100, 20 );
+	neuPunkte->setPosition( 200, 0 );
+	neuPunkte->setText( "" );
+
+	status = new TextFeld();
+	status->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	status->setSchriftZ( s->getThis() );
+	status->setSchriftFarbe( 0xFF00FF00 );
+	status->setSchriftSize( 12 );
+	status->setSize( 100, 20 );
+	status->setPosition( 300, 0 );
+	status->setText( "lebt" );
+
+	ref = 1;
+}
+
+// Destruktor
+BLTeam::~BLTeam()
+{
+	schrift->release();
+	rahmen->release();
+	spieler->release();
+	name->release();
+	punkte->release();
+	neuPunkte->release();
+	status->release();
+}
+
+// nicht constant
+bool BLTeam::addSpieler( Spieler *zSpieler )
+{
+	bool gefunden = 0;
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( spieler->z( i )->getSpielerNummer() == zSpieler->getSpielerNummer() )
+		{
+			gefunden = 1;
+			break;
+		}
+	}
+	if( gefunden )
+		return 0;
+	BLSpieler *tmp = new BLSpieler( zSpieler->getSpielerNummer(), zSpieler->getFarbe(), schrift );
+	spieler->set( tmp, spielerAnzahl );
+	spielerAnzahl++;
+	return 1;
+}
+
+void BLTeam::setName( char *name )
+{
+	this->name->setText( name );
+}
+
+bool BLTeam::updateSpielerStatus( Spieler *zSpieler )
+{
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( spieler->z( i )->getSpielerNummer() == zSpieler->getSpielerNummer() )
+		{
+			spieler->z( i )->updateStatus( zSpieler );
+			return 1;
+		}
+	}
+	return 0;
+}
+
+void BLTeam::setStatus( const char *txt, int f )
+{
+	status->setText( txt );
+	status->setSchriftFarbe( f );
+}
+
+void BLTeam::setPunkte( int p )
+{
+	this->p = p;
+}
+
+void BLTeam::setMaxPunkte( int mP )
+{
+	this->mP = mP;
+}
+
+bool BLTeam::setSpielerPunkte( int sNum, int p )
+{
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( spieler->z( i )->getSpielerNummer() == sNum )
+		{
+			spieler->z( i )->setPunkte( p );
+			return 1;
+		}
+	}
+	return 0;
+}
+
+void BLTeam::addPunkt( bool plus )
+{
+	if( plus )
+		nP++;
+	else
+		nP--;
+	if( p + nP < 0 )
+		nP++;
+}
+
+bool BLTeam::addPunkt( int sNum, bool plus )
+{
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( spieler->z( i )->getSpielerNummer() == sNum )
+		{
+			spieler->z( i )->addPunkt( plus );
+			return 1;
+		}
+	}
+	return 0;
+}
+
+void BLTeam::updatePunkte()
+{
+	p += nP;
+	if( p < 0 )
+		p = 0;
+	nP = 0;
+	for( int i = 0; i < spielerAnzahl; i++ )
+		spieler->z( i )->updatePunkte();
+}
+
+void BLTeam::render( int y, Bild &zRObj )
+{
+	rahmen->setSize( 402, 21 + 20 * spielerAnzahl );
+	if( !zRObj.setDrawOptions( 1, y, rahmen->getBreite(), rahmen->getHeight() ) )
+		return;
+	punkte->setText( "" );
+	if( nP == 0 )
+	{
+		neuPunkte->setText( "" );
+		neuPunkte->setSchriftFarbe( 0xFFFFFFFF );
+	}
+	else if( nP > 0 )
+	{
+		neuPunkte->setText( "+" );
+		neuPunkte->setSchriftFarbe( 0xFF00FF00 );
+	}
+	else
+	{
+		neuPunkte->setText( "" );
+		neuPunkte->setSchriftFarbe( 0xFFFF0000 );
+	}
+	punkte->zText()->append( p );
+	punkte->zText()->append( "/" );
+	punkte->zText()->append( mP );
+	neuPunkte->zText()->append( nP );
+	rahmen->render( zRObj );
+	name->render( zRObj );
+	punkte->render( zRObj );
+	neuPunkte->render( zRObj );
+	status->render( zRObj );
+	Array< bool > *gemahlt = new Array< bool >();
+	for( int i = 0; i < spielerAnzahl; i++ )
+		gemahlt->set( 0, i );
+	int min = -1;
+	int tmp = -1;
+	for( int h = 0; h < spielerAnzahl; h++ )
+	{
+		min = -1;
+		tmp = -1;
+		for( int i = 0; i < spielerAnzahl; i++ )
+		{
+			if( !spieler->z( i ) )
+				continue;
+			if( gemahlt->hat( i ) && gemahlt->get( i ) )
+				continue;
+			int p = spieler->z( i )->getPunkte();
+			if( p > min )
+			{
+				min = p;
+				tmp = i;
+			}
+		}
+		if( tmp >= 0 )
+		{
+			gemahlt->set( 1, tmp );
+			spieler->z( tmp )->render( 20 + 20 * h, zRObj );
+		}
+		else
+			break;
+	}
+	gemahlt->release();
+	zRObj.releaseDrawOptions();
+}
+
+// constant
+int BLTeam::getSpielerAnzahl() const
+{
+	return spielerAnzahl;
+}
+
+int BLTeam::getPunkte() const
+{
+	return ( p + nP ) < 0 ? 0 : ( p + nP );
+}
+
+int BLTeam::getHeight() const
+{
+	return 21 + spielerAnzahl * 20;
+}
+
+// Reference Counting
+BLTeam *BLTeam::getThis()
+{
+	ref++;
+	return this;
+}
+
+BLTeam *BLTeam::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+// Inhalt der Bestenliste Klasse aus Bestenliste.h
+// Konstruktor
+Bestenliste::Bestenliste( Schrift *s )
+{
+	rahmen = new LRahmen();
+	rahmen->setRamenBreite( 1 );
+	rahmen->setFarbe( 0xFFFFFFFF );
+	rahmen->setSize( 420, 200 );
+
+	teams = new RCArray< BLTeam >();
+
+	name = new TextFeld();
+	name->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	name->setSchriftZ( s->getThis() );
+	name->setSchriftFarbe( 0xFFFFFFFF );
+	name->setSchriftSize( 12 );
+	name->setText( "Name" );
+	name->setSize( 100, 20 );
+	name->setPosition( 0, 0 );
+
+	punkte = new TextFeld();
+	punkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	punkte->setSchriftZ( s->getThis() );
+	punkte->setSchriftFarbe( 0xFFFFFFFF );
+	punkte->setSchriftSize( 12 );
+	punkte->setText( "Punkte" );
+	punkte->setSize( 100, 20 );
+	punkte->setPosition( 100, 0 );
+
+	neuPunkte = new TextFeld();
+	neuPunkte->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	neuPunkte->setSchriftZ( s->getThis() );
+	neuPunkte->setSchriftFarbe( 0xFFFFFFFF );
+	neuPunkte->setSchriftSize( 12 );
+	neuPunkte->setText( "+Punkte" );
+	neuPunkte->setSize( 100, 20 );
+	neuPunkte->setPosition( 200, 0 );
+
+	status = new TextFeld();
+	status->setStyle( TextFeld::Style::Sichtbar | TextFeld::Style::Center );
+	status->setSchriftZ( s->getThis() );
+	status->setSchriftFarbe( 0xFFFFFFFF );
+	status->setSchriftSize( 12 );
+	status->setText( "Status" );
+	status->setSize( 100, 20 );
+	status->setPosition( 300, 0 );
+
+	scroll = new VScrollBar();
+	scroll->setKlickScroll( 7 );
+
+	schrift = s;
+	update = 0;
+	teamAnzahl = 0;
+	ref = 1;
+}
+
+// Destruktor
+Bestenliste::~Bestenliste()
+{
+	rahmen->release();
+	teams->release();
+	name->release();
+	punkte->release();
+	neuPunkte->release();
+	status->release();
+	scroll->release();
+	schrift->release();
+}
+
+// nicht constant
+void Bestenliste::setTeamAnzahl( int anz )
+{
+	teamAnzahl = anz;
+}
+
+void Bestenliste::setTeamStatus( int team, const char *txt, int f )
+{
+	if( teams->z( team ) )
+		teams->z( team )->setStatus( txt, f );
+}
+
+void Bestenliste::addSpieler( Spieler *zSpieler )
+{
+	int team = zSpieler->getTeam();
+	if( team < 0 )
+		return;
+	if( !teams->z( team ) )
+		teams->set( new BLTeam( team, zSpieler->getTeamFarbe(), schrift->getThis() ), team );
+	teams->z( team )->addSpieler( zSpieler );
+}
+
+void Bestenliste::updateSpielerStatus( Spieler *zSpieler )
+{
+	if( teams->z( zSpieler->getTeam() ) )
+		teams->z( zSpieler->getTeam() )->updateSpielerStatus( zSpieler );
+}
+
+void Bestenliste::setTeamName( int team, char *name )
+{
+	if( teams->z( team ) )
+		teams->z( team )->setName( name );
+}
+
+void Bestenliste::setTeamPunkte( int teamId, int punkte )
+{
+	if( teams->z( teamId ) )
+		teams->z( teamId )->setPunkte( punkte );
+}
+
+void Bestenliste::setTeamMaxPunkte( int teamId, int mPunkte )
+{
+	if( teams->z( teamId ) )
+		teams->z( teamId )->setMaxPunkte( mPunkte );
+}
+
+void Bestenliste::setSpielerPunkte( int teamNum, int sNum, int punkte )
+{
+	if( teams->z( teamNum ) )
+		teams->z( teamNum )->setSpielerPunkte( sNum, punkte );
+}
+
+void Bestenliste::addPunkt( int tNum, bool plus )
+{
+	if( teams->z( tNum ) )
+		teams->z( tNum )->addPunkt( plus );
+}
+
+void Bestenliste::addPunkt( int tNum, int sNum, bool plus )
+{
+	if( teams->z( tNum ) )
+		teams->z( tNum )->addPunkt( sNum, plus );
+}
+
+void Bestenliste::updatePunkte()
+{
+	for( int i = 0; i < teamAnzahl; i++ )
+	{
+		if( teams->z( i ) )
+			teams->z( i )->updatePunkte();
+	}
+}
+
+void Bestenliste::doMausEreignis( MausEreignis &me )
+{
+	scroll->doMausMessage( rahmen->getBreite() - 15, 1, 15, rahmen->getHeight() - 2, me );
+}
+
+void Bestenliste::render( Bild &zRObj )
+{
+	if( !zRObj.setDrawOptions( 0, 0, rahmen->getBreite(), rahmen->getHeight() ) )
+		return;
+	rahmen->render( zRObj );
+	zRObj.addScrollOffset( 0, scroll->getScroll() );
+	name->render( zRObj );
+	punkte->render( zRObj );
+	neuPunkte->render( zRObj );
+	status->render( zRObj );
+	int yOff = 20;
+	Array< bool > *gemahlt = new Array< bool >();
+	for( int i = 0; i < teamAnzahl; i++ )
+		gemahlt->set( 0, i );
+	int min = -1;
+	int tmp = -1;
+	for( int h = 0; h < teamAnzahl; h++ )
+	{
+		min = -1;
+		tmp = -1;
+		for( int i = 0; i < teamAnzahl; i++ )
+		{
+			if( !teams->z( i ) )
+				continue;
+			if( gemahlt->hat( i ) && gemahlt->get( i ) )
+				continue;
+			int p = teams->z( i )->getPunkte();
+			if( p > min )
+			{
+				min = p;
+				tmp = i;
+			}
+		}
+		if( tmp >= 0 )
+		{
+			gemahlt->set( 1, tmp );
+			teams->z( tmp )->render( yOff, zRObj );
+			yOff += teams->z( tmp )->getHeight();
+		}
+		else
+			break;
+	}
+	gemahlt->release();
+	zRObj.addScrollOffset( 0, -scroll->getScroll() );
+	scroll->update( yOff, rahmen->getHeight() - 2 );
+	scroll->render( rahmen->getBreite() - 16, 1, 15, rahmen->getHeight() - 2, zRObj );
+	zRObj.releaseDrawOptions();
+}
+
+// constant
+int Bestenliste::getTeamAnzahl() const
+{
+	return teamAnzahl;
+}
+
+bool Bestenliste::teamExistiert( int team ) const
+{
+	return teams->z( team ) != 0;
+}
+
+int Bestenliste::getTeamPunkte( int team ) const
+{
+	return teams->z( team ) ? teams->z( team )->getPunkte() : 0;
+}
+
+// Reference Counting
+Bestenliste *Bestenliste::getThis()
+{
+	ref++;
+	return this;
+}
+
+Bestenliste *Bestenliste::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 131 - 0
Linie/Spiel/Bestenliste/Bestenliste.h

@@ -0,0 +1,131 @@
+#ifndef Bestenliste_H
+#define Bestenliste_H
+
+#include <TextFeld.h>
+#include <Array.h>
+
+using namespace Framework;
+
+class Spieler; // Spieler.h
+
+class BLSpieler
+{
+private:
+	int sNum;
+	int farbe;
+	int p;
+	int nP;
+	LRahmen *rahmen;
+	TextFeld *name;
+	TextFeld *punkte;
+	TextFeld *neuPunkte;
+	TextFeld *status;
+	int ref;
+
+public:
+	// Konstruktor
+	BLSpieler( int sNum, int farbe, Schrift *zS );
+	// Destruktor
+	~BLSpieler();
+	// nicht constant
+	bool updateStatus( Spieler *zSpieler );
+	void setPunkte( int p );
+	void addPunkt( bool plus );
+	void updatePunkte();
+	void render( int y, Bild &zRObj );
+	// constant
+	int getSpielerNummer() const;
+	int getPunkte() const;
+	// Reference Counting
+	BLSpieler *getThis();
+	BLSpieler *release();
+};
+
+class BLTeam
+{
+private:
+	int teamId;
+	int spielerAnzahl;
+	int p;
+	int mP;
+	int nP;
+	int farbe;
+	Schrift *schrift;
+	LRahmen *rahmen;
+	RCArray< BLSpieler > *spieler;
+	TextFeld *name;
+	TextFeld *punkte;
+	TextFeld *neuPunkte;
+	TextFeld *status;
+	int ref;
+
+public:
+	// Konstruktor
+	BLTeam( int id, int farbe, Schrift *s );
+	// Destruktor
+	~BLTeam();
+	// nicht constant
+	bool addSpieler( Spieler *zSpieler );
+	void setName( char *name );
+	bool updateSpielerStatus( Spieler *zSpieler );
+	void setStatus( const char *txt, int f );
+	void setPunkte( int p );
+	void setMaxPunkte( int mP );
+	bool setSpielerPunkte( int sNum, int p );
+	void addPunkt( bool plus );
+	bool addPunkt( int sNum, bool plus );
+	void updatePunkte();
+	void render( int y, Bild &zRObj );
+	// constant
+	int getSpielerAnzahl() const;
+	int getPunkte() const;
+	int getHeight() const;
+	// Reference Counting
+	BLTeam *getThis();
+	BLTeam *release();
+};
+
+class Bestenliste
+{
+private:
+	LRahmen *rahmen;
+	RCArray< BLTeam > *teams;
+	TextFeld *name;
+	TextFeld *punkte;
+	TextFeld *neuPunkte;
+	TextFeld *status;
+	VScrollBar *scroll;
+	Schrift *schrift;
+	bool update;
+	int teamAnzahl;
+	int ref;
+
+public:
+	// Konstruktor
+	Bestenliste( Schrift *s );
+	// Destruktor
+	~Bestenliste();
+	// nicht constant
+	void setTeamAnzahl( int anz );
+	void addSpieler( Spieler *zSpieler );
+	void updateSpielerStatus( Spieler *zSpieler );
+	void setTeamName( int team, char *name );
+	void setTeamStatus( int team, const char *txt, int f );
+	void setTeamPunkte( int teamId, int punkte );
+	void setTeamMaxPunkte( int teamId, int mPunkte );
+	void setSpielerPunkte( int teamNum, int sNum, int punkte );
+	void addPunkt( int tNum, bool plus );
+	void addPunkt( int tNum, int sNum, bool plus );
+	void updatePunkte();
+	void doMausEreignis( MausEreignis &me );
+	void render( Bild &zRObj );
+	// constant
+	int getTeamAnzahl() const;
+	bool teamExistiert( int team ) const;
+	int getTeamPunkte( int team ) const;
+	// Reference Counting
+	Bestenliste *getThis();
+	Bestenliste *release();
+};
+
+#endif

+ 161 - 0
Linie/Spiel/Chat/Chat.cpp

@@ -0,0 +1,161 @@
+#include "Chat.h"
+#include <Rahmen.h>
+#include <MausEreignis.h>
+#include <TastaturEreignis.h>
+#include <Text.h>
+#include <Schrift.h>
+#include <Punkt.h>
+#include <Bild.h>
+
+// Inhalt der SpielChat Klasse aus Chat.h
+// Konstruktor
+SpielChat::SpielChat()
+{
+	rahmen = new LRahmen();
+	rahmen->setFarbe( 0xFF909090 );
+	rahmen->setRamenBreite( 1 );
+	rahmen->setSize( 450, 200 );
+	rahmen->setPosition( 10, BildschirmGröße().y - 210 );
+	verlauf = new TextFeld();
+	verlauf->setStyle( TextFeld::Style::TextGebiet & ~( TextFeld::Style::Erlaubt | TextFeld::Style::Rahmen ) );
+	verlauf->setText( "" );
+	verlauf->setSchriftFarbe( 0xFFFFFFFF );
+	verlauf->setSchriftSize( 12 );
+	verlauf->setPosition( rahmen->getX() + 2, rahmen->getY() + 2 );
+	verlauf->setSize( 446, 174 );
+	nachricht = new TextFeld();
+	nachricht->setStyle( TextFeld::Style::TextFeld & ~TextFeld::Style::Buffered );
+	nachricht->setText( "" );
+	nachricht->setSchriftFarbe( 0xFF909090 );
+	nachricht->setSchriftSize( 12 );
+	nachricht->setLinienRahmenBreite( 1 );
+	nachricht->setLinienRahmenFarbe( 0xFF909090 );
+	nachricht->setPosition( rahmen->getX() + 2, rahmen->getY() + 178 );
+	nachricht->setSize( 446, 20 );
+	ref = 1;
+}
+
+// Destruktor
+SpielChat::~SpielChat()
+{
+	rahmen->release();
+	verlauf->release();
+	nachricht->release();
+}
+
+// nicht constant
+void SpielChat::setSchrift( Schrift *zSchrift )
+{
+	verlauf->setSchriftZ( zSchrift->getThis() );
+	nachricht->setSchriftZ( zSchrift->getThis() );
+}
+
+void SpielChat::addNachricht( char *nachricht )
+{
+	verlauf->addZeile( nachricht );
+	verlauf->updateVScroll();
+}
+
+void SpielChat::addNachricht( char *nachricht, int farbe )
+{
+	verlauf->zText()->appendColor( farbe );
+	verlauf->addZeile( nachricht );
+	verlauf->zText( )->appendColor( 0xFFFFFFFF );
+	verlauf->updateVScroll( );
+}
+
+void SpielChat::doMausEreignis( MausEreignis &me )
+{
+	bool vera = me.verarbeitet;
+	verlauf->doMausEreignis( me );
+	nachricht->doMausEreignis( me );
+	if( !vera && me.verarbeitet )
+	{
+		nachricht->setLinienRahmenFarbe( 0xFFFFFFFF );
+		nachricht->setSchriftFarbe( 0xFFFFFFFF );
+		verlauf->setVertikalScrollFarbe( 0xFF808080, 0 );
+		rahmen->setFarbe( 0xFFFFFFFF );
+	}
+	else
+	{
+		nachricht->setLinienRahmenFarbe( 0xFF909090 );
+		nachricht->setSchriftFarbe( 0xFF909090 );
+		verlauf->setVertikalScrollFarbe( 0xFF404040, 0 );
+		rahmen->setFarbe( 0xFF909090 );
+	}
+}
+
+void SpielChat::doTastaturEreignis( TastaturEreignis &te, SpielKlientV *zKlient )
+{
+	if( te.id == TE_Release && te.taste == T_Enter && !te.verarbeitet )
+	{
+		if( nachricht->hatStyle( TextFeld::Style::Fokus ) )
+		{
+			if( nachricht->zText()->getLength() )
+			{
+				short län = 1 + nachricht->zText()->getLength();
+				char *bytes = new char[ län + 1 ];
+				*bytes = 4;
+				for( int i = 1; i <= län; i++ )
+					bytes[ i ] = nachricht->zText()->getText()[ i - 1 ];
+				nachricht->setText( "" );
+				nachricht->setAuswahl( 0, 0 );
+				nachricht->removeStyle( TextFeld::Style::Fokus );
+				zKlient->spielNachricht( län, bytes );
+				delete[] bytes;
+				te.verarbeitet = 1;
+			}
+		}
+		else
+		{
+			nachricht->addStyle( TextFeld::Style::Fokus );
+			nachricht->setAuswahl( 0, nachricht->zText()->getLength() );
+			te.verarbeitet = 1;
+		}
+	}
+	if( !te.verarbeitet )
+		nachricht->doTastaturEreignis( te );
+	if( nachricht->hatStyle( TextFeld::Style::Fokus ) )
+	{
+		nachricht->setLinienRahmenFarbe( 0xFFFFFFFF );
+		nachricht->setSchriftFarbe( 0xFFFFFFFF );
+		verlauf->setVertikalScrollFarbe( 0xFF808080, 0 );
+		rahmen->setFarbe( 0xFFFFFFFF );
+	}
+	else
+	{
+		nachricht->setLinienRahmenFarbe( 0xFF909090 );
+		nachricht->setSchriftFarbe( 0xFF909090 );
+		verlauf->setVertikalScrollFarbe( 0xFF404040, 0 );
+		rahmen->setFarbe( 0xFF909090 );
+	}
+}
+
+void SpielChat::tick( double z )
+{
+	nachricht->tick( z );
+}
+
+void SpielChat::render( Bild &zRObj )
+{
+	rahmen->render( zRObj );
+	verlauf->render( zRObj );
+	nachricht->render( zRObj );
+}
+
+// constant
+
+// Reference Counting
+SpielChat *SpielChat::getThis()
+{
+	ref++;
+	return this;
+}
+
+SpielChat *SpielChat::relese()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 37 - 0
Linie/Spiel/Chat/Chat.h

@@ -0,0 +1,37 @@
+#ifndef Chat_H
+#define Chat_H
+
+#include <KSGKlientV.h>
+#include <TextFeld.h>
+
+using namespace Framework;
+
+class SpielChat
+{
+private:
+	LRahmen *rahmen = 0;
+	TextFeld *verlauf;
+	TextFeld *nachricht;
+	int ref;
+
+public:
+	// Konstruktor
+	SpielChat();
+	// Destruktor
+	~SpielChat();
+	// nicht constant
+	void setSchrift( Schrift *zSchrift );
+	void addNachricht( char *nachricht );
+	void addNachricht( char *nachricht, int farbe );
+	void doMausEreignis( MausEreignis &me );
+	void doTastaturEreignis( TastaturEreignis &te, SpielKlientV *zKlient );
+	void tick( double z );
+	void render( Bild &zRObj );
+	// constant
+
+	// Reference Counting
+	SpielChat *getThis();
+	SpielChat *relese();
+};
+
+#endif

+ 111 - 0
Linie/Spiel/Ende/Ende.cpp

@@ -0,0 +1,111 @@
+#include "Ende.h"
+#include <TextFeld.h>
+#include <Bild.h>
+#include <MausEreignis.h>
+#include <Rahmen.h>
+#include <Schrift.h>
+
+// Inhalt der Ende Klasse aus Ende.h
+// Konstruktor
+Ende::Ende( Schrift *zSchrift )
+{
+	rahmen = new LRahmen();
+	rahmen->setSize( 200, 100 );
+	rahmen->setRamenBreite( 2 );
+	rahmen->setFarbe( 0xFFFFFFFF );
+	text = new TextFeld();
+	text->setStyle( TextFeld::Style::Text | TextFeld::Style::Center );
+	text->setSchriftZ( zSchrift->getThis() );
+	text->setText( "" );
+	text->setSchriftFarbe( 0xFFFFFFFF );
+	text->setSize( 200, 50 );
+	warten = new TextFeld();
+	warten->setStyle( ( TextFeld::Style::Text | TextFeld::Style::Center ) & ~TextFeld::Style::Sichtbar );
+	warten->setSchriftZ( zSchrift->getThis() );
+	warten->setText( "Bitte warten..." );
+	warten->setSchriftFarbe( 0xFFFFFFFF );
+	warten->setSize( 200, 50 );
+	ok = new Knopf( );
+	ok->setStyle( Knopf::Style::Normal );
+	ok->setSize( 100, 20 );
+	ok->setText( "Weiter" );
+	ok->setSchriftZ( zSchrift->getThis() );
+	weiter = 0;
+	ref = 1;
+}
+
+// Destruktor
+Ende::~Ende()
+{
+	rahmen->release();
+	text->release();
+	warten->release();
+	ok->release();
+}
+
+// nicht constant
+void Ende::setGewonnen( char gewonnen )
+{
+	if( gewonnen == 1 )
+	{
+		text->setText( "Du hast gewonnen." );
+		text->setSchriftFarbe( 0xFF00FF00 );
+	}
+	else if( !gewonnen )
+	{
+		text->setText( "Du hast verloren." );
+		text->setSchriftFarbe( 0xFFFF0000 );
+	}
+	else
+	{
+		text->setText( "Unentschieden." );
+		text->setSchriftFarbe( 0xFFFFFFFF );
+	}
+}
+
+void Ende::doMausEreignis( MausEreignis &me )
+{
+	bool vera = me.verarbeitet;
+	ok->doMausEreignis( me );
+	if( !vera && me.verarbeitet && me.id == ME_RLinks )
+	{
+		ok->removeStyle( Knopf::Style::Sichtbar );
+		warten->addStyle( TextFeld::Style::Sichtbar );
+		weiter = 1;
+	}
+	me.verarbeitet = 1;
+}
+
+void Ende::render( Bild &zRObj )
+{
+	rahmen->setPosition( zRObj.getBreite() / 2 - rahmen->getBreite() / 2, zRObj.getHeight() / 2 - rahmen->getHeight() / 2 );
+	zRObj.alphaRegion( rahmen->getX(), rahmen->getY(), rahmen->getBreite(), rahmen->getHeight(), 0xA0000000 );
+	rahmen->render( zRObj );
+	text->setPosition( rahmen->getX(), rahmen->getY() );
+	text->render( zRObj );
+	warten->setPosition( rahmen->getX(), rahmen->getY() + 50 );
+	warten->render( zRObj );
+	ok->setPosition( rahmen->getX() + rahmen->getBreite() / 2 - ok->getBreite() / 2, rahmen->getY() + 65 );
+	ok->render( zRObj );
+}
+
+// constant
+bool Ende::getWeiter() const
+{
+	return weiter;
+}
+
+// Reference Counting
+Ende *Ende::getThis()
+{
+	ref++;
+	return this;
+}
+
+Ende *Ende::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 34 - 0
Linie/Spiel/Ende/Ende.h

@@ -0,0 +1,34 @@
+#ifndef Ende_H
+#define Ende_H
+
+#include <Knopf.h>
+
+using namespace Framework;
+
+class Ende
+{
+private:
+	LRahmen *rahmen;
+	TextFeld *text;
+	TextFeld *warten;
+	Knopf *ok;
+	bool weiter;
+	int ref;
+
+public:
+	// Konstruktor
+	Ende( Schrift *zSchrift );
+	// Destruktor
+	~Ende( );
+	// nicht constant
+	void setGewonnen( char gewonnen );
+	void doMausEreignis( MausEreignis &me );
+	void render( Bild &zRObj );
+	// constant
+	bool getWeiter( ) const;
+	// Reference Counting
+	Ende *getThis( );
+	Ende *release( );
+};
+
+#endif

+ 99 - 0
Linie/Spiel/Ende/RundenEnde.cpp

@@ -0,0 +1,99 @@
+#include "RundenEnde.h"
+#include <Bild.h>
+#include <MausEreignis.h>
+#include <Rahmen.h>
+#include <Schrift.h>
+#include <Text.h>
+
+// Inhalt der RundenEnde Klasse aus RundenEnde.h
+// Konstruktor
+RundenEnde::RundenEnde( Schrift *zSchrift )
+{
+	rahmen = new LRahmen();
+	rahmen->setSize( 220, 70 );
+	rahmen->setRamenBreite( 2 );
+	rahmen->setFarbe( 0xFFFFFFFF );
+	text = new TextFeld();
+	text->setStyle( TextFeld::Style::Text | TextFeld::Style::Center );
+	text->setSchriftZ( zSchrift->getThis() );
+	text->setText( "" );
+	text->setSchriftFarbe( 0xFFFFFFFF );
+	text->setSize( 220, 50 );
+	warten = new TextFeld();
+	warten->setStyle( TextFeld::Style::Text | TextFeld::Style::Center );
+	warten->setSchriftZ( zSchrift->getThis() );
+	warten->setText( "Nächste Runde startet in: 5" );
+	warten->setSchriftFarbe( 0xFFFFFFFF );
+	warten->setSize( 220, 45 );
+	sichtbar = 0;
+	ref = 1;
+}
+
+// Destruktor
+RundenEnde::~RundenEnde()
+{
+	rahmen->release();
+	text->release();
+	warten->release();
+}
+
+// nicht constant
+void RundenEnde::setSichtbar( bool b )
+{
+	sichtbar = b;
+}
+
+void RundenEnde::setGewonnen( bool gewonnen )
+{
+	if( gewonnen )
+	{
+		text->setText( "Du hast die Runde gewonnen." );
+		text->setSchriftFarbe( 0xFF00FF00 );
+	}
+	else
+	{
+		text->setText( "Du hast die Runde verloren." );
+		text->setSchriftFarbe( 0xFFFF0000 );
+	}
+}
+
+void RundenEnde::setZeit( int sekunden )
+{
+	warten->setText( "Nächste Runde startet in: " );
+	warten->zText()->append( sekunden );
+}
+
+void RundenEnde::render( Bild &zRObj )
+{
+	if( sichtbar )
+	{
+		rahmen->setPosition( zRObj.getBreite() / 2 - rahmen->getBreite() / 2, zRObj.getHeight() / 2 - rahmen->getHeight() / 2 );
+		zRObj.alphaRegion( rahmen->getX(), rahmen->getY(), rahmen->getBreite(), rahmen->getHeight(), 0xA0000000 );
+		rahmen->render( zRObj );
+		text->setPosition( rahmen->getX(), rahmen->getY() );
+		text->render( zRObj );
+		warten->setPosition( rahmen->getX(), rahmen->getY() + 25 );
+		warten->render( zRObj );
+	}
+}
+
+// constant
+bool RundenEnde::istSichtbar() const
+{
+	return sichtbar;
+}
+
+// Reference Counting
+RundenEnde *RundenEnde::getThis()
+{
+	ref++;
+	return this;
+}
+
+RundenEnde *RundenEnde::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 34 - 0
Linie/Spiel/Ende/RundenEnde.h

@@ -0,0 +1,34 @@
+#ifndef Rundenende_H
+#define Rundenende_H
+
+#include <TextFeld.h>
+
+using namespace Framework;
+
+class RundenEnde
+{
+private:
+	LRahmen *rahmen;
+	TextFeld *text;
+	TextFeld *warten;
+	bool sichtbar;
+	int ref;
+
+public:
+	// Konstruktor
+	RundenEnde( Schrift *zSchrift );
+	// Destruktor
+	~RundenEnde();
+	// nicht constant
+	void setSichtbar( bool b );
+	void setGewonnen( bool gewonnen );
+	void setZeit( int sekunden );
+	void render( Bild &zRObj );
+	// constant
+	bool istSichtbar() const;
+	// Reference Counting
+	RundenEnde *getThis();
+	RundenEnde *release();
+};
+
+#endif

+ 124 - 0
Linie/Spiel/Kamera/Kamera.cpp

@@ -0,0 +1,124 @@
+#include "Kamera.h"
+#include "..\Karte\Karte.h"
+#include <Punkt.h>
+#include <Rahmen.h>
+
+// Inhalt der Kamera Klasse aus Kamera.h
+// Konstruktor
+Kamera::Kamera()
+{
+	pos = Punkt( 0, 0 );
+	gr = Punkt( 0, 0 );
+	rGr =  Punkt( 0, 0 );
+	rahmen = new LRahmen();
+	rahmen->setFarbe( 0xFF505050 );
+	rahmen->setRamenBreite( 1 );
+	ref = 1;
+}
+
+// Destruktor
+Kamera::~Kamera()
+{
+	rahmen->release();
+}
+
+// nicht constant
+void Kamera::setPosition( int x, int y )
+{
+	pos.x = x;
+	pos.y = y;
+}
+
+void Kamera::addPosition( int x, int y, Karte *zMap )
+{
+	pos.x += x;
+	pos.y += y;
+	if( pos.x < 0 )
+		pos.x = 0;
+	if( pos.y < 0 )
+		pos.y = 0;
+	if( pos.x > zMap->getBreite() )
+		pos.x = zMap->getBreite();
+	if( pos.y > zMap->getHeight() )
+		pos.y = zMap->getHeight();
+}
+
+void Kamera::setSize( int br, int hö )
+{
+	gr.x = br;
+	gr.y = hö;
+}
+
+void Kamera::render( Bild &zRObj )
+{
+	rGr = zRObj.getSize();
+	rahmen->setPosition( getRX( getLinks() ), getRY( getOben() ) );
+	rahmen->setSize( gr );
+	rahmen->render( zRObj );
+}
+
+// constant
+int Kamera::getLinks() const
+{
+	return pos.x - (int)( gr.x / 2.0 + 0.5 );
+}
+
+int Kamera::getOben() const
+{
+	return pos.y - gr.y / 2;
+}
+
+int Kamera::getRechts() const
+{
+	return pos.x + gr.x / 2;
+}
+
+int Kamera::getUnten() const
+{
+	return pos.y + gr.y / 2;
+}
+
+bool Kamera::istSichtbar( int x, int y ) const
+{
+	return ( x >= getLinks() && x < getRechts() && y >= getOben() && y < getUnten() );
+}
+
+bool Kamera::istMausIn( int x, int y ) const
+{
+	return ( x >= ( rGr.x / 2 - gr.x / 2 ) && x < ( rGr.x / 2 + gr.x / 2 ) && y >= ( rGr.y / 2 - gr.y / 2 ) && y < ( rGr.y / 2 + gr.y / 2 ) );
+}
+
+int Kamera::getRX( int mapX ) const
+{
+	return rGr.x / 2 - ( pos.x - mapX );
+}
+
+int Kamera::getRY( int mapY ) const
+{
+	return rGr.y / 2 - ( pos.y - mapY );
+}
+
+int Kamera::getX() const
+{
+	return pos.x;
+}
+
+int Kamera::getY() const
+{
+	return pos.y;
+}
+
+// Reference Counting
+Kamera *Kamera::getThis()
+{
+	ref++;
+	return this;
+}
+
+Kamera *Kamera::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 45 - 0
Linie/Spiel/Kamera/Kamera.h

@@ -0,0 +1,45 @@
+#ifndef Kamera_H
+#define Kamera_H
+
+#include <Bild.h>
+
+using namespace Framework;
+
+class Karte;
+
+class Kamera
+{
+private:
+	Punkt pos;
+	Punkt gr;
+	Punkt rGr;
+	LRahmen *rahmen;
+	int ref;
+
+public:
+	// Konstruktor
+	Kamera();
+	// Destruktor
+	~Kamera();
+	// nicht constant
+	void setPosition( int x, int y );
+	void addPosition( int x, int y, Karte *zMap );
+	void setSize( int br, int hö );
+	void render( Bild &zRObj );
+	// constant
+	int getLinks() const;
+	int getOben() const;
+	int getRechts() const;
+	int getUnten() const;
+	bool istSichtbar( int x, int y ) const;
+	bool istMausIn( int x, int y ) const;
+	int getRX( int mapX ) const;
+	int getRY( int mapY ) const;
+	int getX() const;
+	int getY() const;
+	// Reference Counting
+	Kamera *release();
+	Kamera *getThis();
+};
+
+#endif

+ 78 - 0
Linie/Spiel/Karte/Karte.cpp

@@ -0,0 +1,78 @@
+#include "Karte.h"
+#include <Punkt.h>
+#include <Rahmen.h>
+#include "..\Kamera\Kamera.h"
+
+// Inhalt der Karte Klasse aus Karte.h
+// Konstruktor
+Karte::Karte()
+{
+	karteId = 0;
+	map = new Bild();
+	rahmen = new LRahmen();
+	rahmen->setFarbe( 0xFFFFFFFF );
+	rahmen->setRamenBreite( 2 );
+	ref = 1;
+}
+
+// Destruktor
+Karte::~Karte()
+{
+	map->release();
+	rahmen->release();
+}
+
+// nicht constant
+void Karte::setSize( int br, int hö )
+{
+	map->neuBild( br, hö, 0xFF000000 );
+	rahmen->setSize( br, hö );
+}
+
+void Karte::setId( int id )
+{
+	karteId = id;
+}
+
+void Karte::render( Kamera *zKam, Bild &zRObj )
+{
+	rahmen->setPosition( zKam->getRX( 0 ), zKam->getRY( 0 ) );
+	zRObj.drawBild( rahmen->getX(), rahmen->getY(), map->getBreite(), map->getHeight(), *map );
+	rahmen->render( zRObj );
+}
+
+// constant
+int Karte::getId() const
+{
+	return karteId;
+}
+
+int Karte::getBreite() const
+{
+	return map->getBreite();
+}
+
+int Karte::getHeight() const
+{
+	return map->getHeight();
+}
+
+Bild *Karte::zMap() const
+{
+	return ( map->getBreite() != 0 && map->getHeight() != 0 ) ? map : 0;
+}
+
+// Reference Counting
+Karte *Karte::getThis()
+{
+	ref++;
+	return this;
+}
+
+Karte *Karte::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 37 - 0
Linie/Spiel/Karte/Karte.h

@@ -0,0 +1,37 @@
+#ifndef Karte_H
+#define Karte_H
+
+#include <Bild.h>
+
+using namespace Framework;
+
+class Kamera;
+
+class Karte
+{
+private:
+	int karteId;
+	Bild *map;
+	LRahmen *rahmen;
+	int ref;
+
+public:
+	// Konstruktor
+	Karte();
+	// Destruktor
+	~Karte();
+	// nicht constant
+	void setSize( int br, int hö );
+	void setId( int id );
+	void render( Kamera *zKam, Bild &zRObj );
+	// constant
+	int getId() const;
+	int getBreite() const;
+	int getHeight() const;
+	Bild *zMap() const;
+	// Reference Counting
+	Karte *getThis();
+	Karte *release();
+};
+
+#endif

+ 820 - 0
Linie/Spiel/SpielKlasse.cpp

@@ -0,0 +1,820 @@
+#include "SpielKlasse.h"
+#include <time.h>
+#include <Schrift.h>
+#include <MausEreignis.h>
+#include <TastaturEreignis.h>
+
+// Inhalt der SpielKlasse Klasse aus SpielKlasse.h
+// Konstruktor
+SpielKlasse::SpielKlasse()
+{
+	spielZeit = 0;
+	rZeit = 0;
+	spielPause = 1;
+	rendern = 0;
+	stkn = new RCArray< STKNachricht >();
+	stkna = 0;
+	schrift = 0;
+	time_t t;
+	time( &t );
+	srand( (unsigned int)t );
+	infoKlient = 0;
+	spielKlient = 0;
+	spieler = new RCArray< Spieler >();
+	screen = 0;
+	kam = 0;
+	spielerAnzahl = 0;
+	karteId = 0;
+	spielerNummer = 0;
+	map = 0;
+	rEnd = 0;
+	end = 0;
+	chat = new SpielChat();
+	tasten = new char[ 256 ];
+	for( int i = 0; i < 256; i++ )
+		tasten[ i ] = 0;
+	mx = -1;
+	my = -1;
+	bestenliste = 0;
+	ref = 1;
+}
+
+// Destruktor
+SpielKlasse::~SpielKlasse()
+{
+	stkn->release();
+	if( schrift )
+		schrift->release();
+	if( infoKlient )
+		infoKlient->release();
+	if( spielKlient )
+		spielKlient->release();
+	if( kam )
+		kam->release();
+	if( map )
+		map->release();
+	if( rEnd )
+		rEnd->release();
+	if( end )
+		end->release();
+	if( bestenliste )
+		bestenliste->release();
+	chat->relese();
+	spieler->release();
+	if( screen )
+		screen->release();
+	delete[] tasten;
+}
+
+// privat
+bool SpielKlasse::istAmLeben() const
+{
+	for( int i = 0; i < spielerAnzahl; i++ )
+	{
+		if( spieler->z( i )->getSpielerNummer() == spielerNummer )
+			return spieler->z( i )->istAmLeben();
+	}
+	return 0;
+}
+
+// nicht constant
+void SpielKlasse::lock()
+{
+	if( screen )
+		screen->lock();
+}
+
+void SpielKlasse::unlock()
+{
+	if( screen )
+		screen->unlock();
+}
+
+void SpielKlasse::setSchrift( Schrift *schrift )
+{
+	if( this->schrift )
+		this->schrift->release();
+	this->schrift = schrift;
+	chat->setSchrift( schrift );
+	if( !bestenliste )
+		bestenliste = new Bestenliste( schrift->getThis() );
+	if( !rEnd )
+		rEnd = new RundenEnde( schrift );
+}
+
+void SpielKlasse::setBildschirm( Bildschirm *screen )
+{
+	this->screen = screen;
+}
+
+void SpielKlasse::nachricht( int län, char *bytes )
+{
+	if( !län )
+		return;
+	lock();
+	stkn->add( new STKNachricht( län, bytes ), stkna );
+	stkna++;
+	unlock();
+}
+
+void SpielKlasse::setKlients( InformationKlientV *infoKlient, SpielKlientV *spielKlient )
+{
+	if( this->infoKlient )
+		this->infoKlient->release();
+	this->infoKlient = infoKlient;
+	if( this->spielKlient )
+		this->spielKlient->release();
+	this->spielKlient = spielKlient;
+}
+
+void SpielKlasse::setKarteId( int karteId )
+{
+	this->karteId = karteId;
+}
+
+void SpielKlasse::ladeDaten()
+{
+	kam = new Kamera();
+	kam->setSize( 400, 400 );
+	map = new Karte();
+	map->setId( karteId );
+	for( int i = 1; i <= 100; i++ )
+	{
+		Sleep( 100 + ( rand() % 100 ) );
+		spielKlient->setLadenProzent( i );
+	}
+}
+
+void SpielKlasse::doMausEreignis( MausEreignis &me )
+{
+	if( end )
+	{
+		end->doMausEreignis( me );
+		return;
+	}
+	if( !istAmLeben() && kam->istMausIn( me.mx, me.my ) )
+	{
+		if( ( me.id == ME_RLinks || me.id == ME_RRechts ) && mx >= 0 )
+		{
+			mx = -1;
+			my = -1;
+		}
+		if( me.id == ME_Bewegung && mx >= 0 )
+		{
+			kam->addPosition( mx - me.mx, my - me.my, map );
+			mx = me.mx;
+			my = me.my;
+		}
+		if( ( me.id == ME_PLinks || me.id == ME_PRechts ) && mx < 0 )
+		{
+			mx = me.mx;
+			my = me.my;
+		}
+		me.verarbeitet = 1;
+	}
+	else
+	{
+		mx = -1;
+		my = -1;
+	}
+	chat->doMausEreignis( me );
+	if( bestenliste )
+		bestenliste->doMausEreignis( me );
+}
+
+void SpielKlasse::doTastaturEreignis( TastaturEreignis &te )
+{
+	if( end )
+		return;
+	if( istAmLeben() )
+	{
+		if( te.id == TE_Press )
+		{
+			switch( te.taste )
+			{
+			case T_Links:
+				if( !tasten[ T_Links ] )
+				{
+					tasten[ T_Links ] = 1;
+					char byte = 0;
+					spielKlient->spielNachricht( 1, &byte );
+					te.verarbeitet = 1;
+				}
+				break;
+			case T_Rechts:
+				if( !tasten[ T_Rechts ] )
+				{
+					tasten[ T_Rechts ] = 1;
+					char byte = 2;
+					spielKlient->spielNachricht( 1, &byte );
+					te.verarbeitet = 1;
+				}
+				break;
+			}
+		}
+		if( te.id == TE_Release )
+		{
+			switch( te.taste )
+			{
+			case T_Links:
+				if( tasten[ T_Links ] )
+				{
+					tasten[ T_Links ] = 0;
+					char byte = 1;
+					spielKlient->spielNachricht( 1, &byte );
+					te.verarbeitet = 1;
+				}
+				break;
+			case T_Rechts:
+				if( tasten[ T_Rechts ] )
+				{
+					tasten[ T_Rechts ] = 0;
+					char byte = 3;
+					spielKlient->spielNachricht( 1, &byte );
+					te.verarbeitet = 1;
+				}
+				break;
+			}
+		}
+	}
+	else
+	{
+		if( te.id == TE_Press )
+		{
+			switch( te.taste )
+			{
+			case T_Links:
+				kam->addPosition( -2, 0, map );
+				te.verarbeitet = 1;
+				break;
+			case T_Oben:
+				kam->addPosition( 0, -2, map );
+				te.verarbeitet = 1;
+				break;
+			case T_Rechts:
+				kam->addPosition( 2, 0, map );
+				te.verarbeitet = 1;
+				break;
+			case T_Unten:
+				kam->addPosition( 0, 2, map );
+				te.verarbeitet = 1;
+				break;
+			}
+		}
+	}
+	if( !te.verarbeitet )
+		chat->doTastaturEreignis( te, spielKlient );
+}
+
+void SpielKlasse::stknVerarbeitung()
+{
+	lock();
+	for( int i = 0; i < stkna; i++ )
+	{
+		STKNachricht *n = stkn->z( i );
+		double zeit = n->getSpielZeit();
+		if( zeit > spielZeit && ( !rEnd || !rEnd->istSichtbar() ) )
+			break;
+		int län = n->getLength();
+		char *bytes = n->getNachricht();
+		län--;
+		switch( bytes[ 0 ] )
+		{
+		case 0: // set Spieler Nummer
+			bytes++;
+			spielerNummer = *(int*)bytes;
+			län -= 4;
+			break;
+		case 1: // init Spieler
+			if( 1 )
+			{
+				bytes++;
+				spielerAnzahl = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				int maxTeam = 0;
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					Spieler *tmp = new Spieler( infoKlient );
+					int sNum = *(int*)bytes;
+					län -= 4;
+					bytes += 4;
+					tmp->setSpielerNummer( sNum );
+					int team = *(int*)bytes;
+					län -= 4;
+					bytes += 4;
+					maxTeam = maxTeam < team ? team : maxTeam;
+					tmp->setTeam( team );
+					int sFarbe = *(int*)bytes;
+					län -= 4;
+					bytes += 4;
+					tmp->setSpielerFarbe( sFarbe );
+					int tFarbe = *(int*)bytes;
+					län -= 4;
+					bytes += 4;
+					tmp->setTeamFarbe( tFarbe );
+					int accId = *(int*)bytes;
+					län -= 4;
+					bytes += 4;
+					tmp->setAccountId( accId );
+					bestenliste->addSpieler( tmp );
+					bestenliste->updateSpielerStatus( tmp );
+					spieler->set( tmp, i );
+				}
+				bestenliste->setTeamAnzahl( maxTeam + 1 );
+			}
+			break;
+		case 2: // setze Spieler Position
+			if( 1 )
+			{
+				bytes++;
+				int sNum = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				double posX = *(double*)bytes;
+				län -= 8;
+				bytes += 8;
+				double posY = *(double*)bytes;
+				län -= 8;
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					if( spieler->z( i )->getSpielerNummer() == sNum )
+						spieler->z( i )->setPos( posX, posY );
+				}
+				if( spielerNummer == sNum )
+					kam->setPosition( (int)posX, (int)posY );
+			}
+			break;
+		case 3: // setzt kammera größe
+			if( 1 )
+			{
+				bytes++;
+				int br = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				int hö = *(int*)bytes;
+				län -= 4;
+				kam->setSize( br, hö );
+			}
+			break;
+		case 4: // Zeit Beginn
+			spielPause = 0;
+			spielZeit = 0;
+			rZeit = 0;
+			rendern = 1;
+			break;
+		case 5: // spieler ist tod
+			if( 1 )
+			{
+				bytes++;
+				int sNum = *(int*)bytes;
+				län -= 4;
+				Text *zName = 0;
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					int team = spieler->z( i )->getTeam();
+					int player = spieler->z( i )->getSpielerNummer();
+					if( player == sNum )
+					{
+						spieler->z( i )->sterben( map->zMap(), zeit, spielZeit );
+						bestenliste->updateSpielerStatus( spieler->z( i ) );
+						zName = spieler->z( i )->zName();
+						bool teamLebt = 0;
+						for( int j = 0; j < spielerAnzahl; j++ )
+						{
+							if( spieler->z( j ) && spieler->z( j )->getTeam() == team )
+								teamLebt |= spieler->z( j )->istAmLeben();
+						}
+						if( !teamLebt )
+						{
+							for( int j = 0; j < bestenliste->getTeamAnzahl(); j++ )
+							{
+								if( bestenliste->teamExistiert( j ) )
+								{
+									bool amLeben = 0;
+									for( int k = 0; k < spielerAnzahl; k++ )
+									{
+										if( spieler->z( k ) && spieler->z( k )->getTeam() == j )
+											amLeben |= spieler->z( k )->istAmLeben();
+									}
+									if( amLeben )
+										bestenliste->addPunkt( j, 1 );
+									else
+										bestenliste->addPunkt( j, 0 );
+									if( bestenliste->getTeamPunkte( j ) <= 0 )
+										bestenliste->setTeamStatus( j, "tot", 0xFFFF0000 );
+								}
+							}
+						}
+					}
+					else
+					{
+						if( spieler->z( i )->istAmLeben() )
+							bestenliste->addPunkt( team, player, 1 );
+					}
+				}
+				if( sNum == spielerNummer )
+					chat->addNachricht( "Du bist gestorben.", 0xFFFFFF00 );
+				else if( zName )
+				{
+					Text *txt = new Text( zName->getText() );
+					txt->append( " ist gestorben." );
+					chat->addNachricht( txt->getText(), 0xFFFFFF00 );
+					txt->release();
+				}
+			}
+			break;
+		case 6: // spiel Ende
+			if( 1 )
+			{
+				bestenliste->updatePunkte();
+				bytes++;
+				char gewonnen = *bytes;
+				län--;
+				end = new Ende( schrift );
+				end->setGewonnen( gewonnen );
+			}
+			break;
+		case 7: // set Spieler Geschwindigkeit
+			if( 1 )
+			{
+				bytes++;
+				int sNum = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				double xSpeed = *(double*)bytes;
+				län -= 8;
+				bytes += 8;
+				double ySpeed = *(double*)bytes;
+				län -= 8;
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					if( spieler->z( i )->getSpielerNummer() == sNum )
+						spieler->z( i )->setSpeed( xSpeed, ySpeed );
+				}
+			}
+			break;
+		case 8: // set Spieler Wendigkeit
+			if( 1 )
+			{
+				bytes++;
+				int sNum = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				double kurve = *(double*)bytes;
+				län -= 8;
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					if( spieler->z( i )->getSpielerNummer() == sNum )
+						spieler->z( i )->setKurveSpeed( kurve );
+				}
+			}
+			break;
+		case 9: // set Spieler Kurve
+			if( 1 )
+			{
+				bytes++;
+				int sNum = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				char k = *bytes;
+				län--;
+				if( k == 0 )
+				{
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == sNum )
+						{
+							spieler->z( i )->setLinksKurve( map->zMap(), 0, zeit, spielZeit );
+							spieler->z( i )->setRechtsKurve( map->zMap(), 0, zeit, spielZeit );
+						}
+					}
+				}
+				else if( k == 1 )
+				{
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == sNum )
+							spieler->z( i )->setLinksKurve( map->zMap(), 1, zeit, spielZeit );
+					}
+				}
+				else if( k == 2 )
+				{
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == sNum )
+							spieler->z( i )->setLinksKurve( map->zMap(), 0, zeit, spielZeit );
+					}
+				}
+				else if( k == 3 )
+				{
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == sNum )
+							spieler->z( i )->setRechtsKurve( map->zMap(), 1, zeit, spielZeit );
+					}
+				}
+				else if( k == 4 )
+				{
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == sNum )
+							spieler->z( i )->setRechtsKurve( map->zMap(), 0, zeit, spielZeit );
+					}
+				}
+				else if( k == 5 )
+				{
+					for( int i = 0; i < spielerAnzahl; i++ )
+					{
+						if( spieler->z( i )->getSpielerNummer() == sNum )
+						{
+							spieler->z( i )->setLinksKurve( map->zMap(), 1, zeit, spielZeit );
+							spieler->z( i )->setRechtsKurve( map->zMap(), 1, zeit, spielZeit );
+						}
+					}
+				}
+			}
+			break;
+		case 0xA: // set Karte Größe
+			if( 1 )
+			{
+				bytes++;
+				int br = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				int hö = *(int*)bytes;
+				län -= 4;
+				map->setSize( br, hö );
+			}
+			break;
+		case 0xB: // chat Nachricht
+			if( 1 )
+			{
+				bytes++;
+				Text *txt = new Text( "" );
+				txt->append( bytes, län );
+				chat->addNachricht( txt->getText() );
+				txt->release();
+				län = 0;
+			}
+			break;
+		case 0xC: // Spieler Linien Unterbrechung
+			if( 1 )
+			{
+				bytes++;
+				int sNum = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				char unterbrechung = *bytes;
+				län--;
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					Spieler *tmp = spieler->z( i );
+					if( tmp && tmp->getSpielerNummer() == sNum )
+						tmp->setLinienUnterbrechung( map->zMap(), unterbrechung != 0, zeit, spielZeit );
+				}
+			}
+			break;
+		case 0xD: // Max Team Punkte 
+			if( 1 )
+			{
+				bytes++;
+				int team = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				int mP = *(int*)bytes;
+				län -= 4;
+				bestenliste->setTeamMaxPunkte( team, mP );
+			}
+			break;
+		case 0xE: // Team Punkte
+			if( 1 )
+			{
+				bytes++;
+				int team = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				int p = *(int*)bytes;
+				län -= 4;
+				bestenliste->setTeamPunkte( team, p );
+				if( !p )
+					bestenliste->setTeamStatus( team, "tot", 0xFFFF0000 );
+			}
+			break;
+		case 0xF: // Spieler Punkte
+			if( 1 )
+			{
+				bytes++;
+				int sNum = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				int p = *(int*)bytes;
+				län -= 4;
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					if( spieler->z( i ) && spieler->z( i )->getSpielerNummer() == sNum )
+					{
+						bestenliste->setSpielerPunkte( spieler->z( i )->getTeam(), sNum, p );
+						break;
+					}
+				}
+			}
+			break;
+		case 0x10: // Team Tod
+			if( 1 )
+			{
+				bytes++;
+				int team = *(int*)bytes;
+				län -= 4;
+				bestenliste->setTeamPunkte( team, 0 );
+				bestenliste->setTeamStatus( team, "tot", 0xFFFF0000 );
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					if( spieler->z( i ) && spieler->z( i )->getTeam() == team )
+					{
+						spieler->z( i )->sterben();
+						bestenliste->updateSpielerStatus( spieler->z( i ) );
+					}
+				}
+			}
+			break;
+		case 0x11: // Runden Ende
+			if( 1 )
+			{
+				spielPause = 1;
+				bytes++;
+				int team = *(int*)bytes;
+				län -= 4;
+				bool gewonnen = 0;
+				for( int i = 0; i < spielerAnzahl; i++ )
+				{
+					if( spieler->z( i )->getSpielerNummer() == spielerNummer )
+					{
+						gewonnen = spieler->z( i )->getTeam() == team;
+						break;
+					}
+				}
+				rEnd->setGewonnen( gewonnen );
+				bestenliste->updatePunkte();
+				rEnd->setSichtbar( 1 );
+			}
+			break;
+		case 0x12: // Verbleibende Zeit
+			if( 1 )
+			{
+				bytes++;
+				int sek = *(int*)bytes;
+				län -= 4;
+				rEnd->setZeit( sek );
+				if( !sek )
+				{
+					if( rEnd && rEnd->istSichtbar() )
+					{
+						rEnd->setSichtbar( 0 );
+						rEnd->setZeit( 6 );
+						for( int i = 0; i < spielerAnzahl; i++ )
+						{
+							if( spieler->z( i ) )
+							{
+								spieler->z( i )->neuRunde();
+								if( !bestenliste->getTeamPunkte( spieler->z( i )->getTeam() ) )
+									spieler->z( i )->sterben();
+								bestenliste->updateSpielerStatus( spieler->z( i ) );
+							}
+						}
+					}
+				}
+			}
+			break;
+		case 0x13: // Team Name
+			if( 1 )
+			{
+				bytes++;
+				int team = *(int*)bytes;
+				län -= 4;
+				bytes += 4;
+				char *n = new char[ län + 1 ];
+				n[ län ] = 0;
+				memcpy( n, bytes, län );
+				län -= län;
+				bestenliste->setTeamName( team, n );
+				delete[] n;
+			}
+			break;
+		default:
+			// Fehler beim verarbeiten
+			break;
+		}
+		if( län != 0 )
+		{
+			// Fehler beim verarbeiten
+			chat->addNachricht( "Es ist ein Fehler beim verarbeiten einer Nachricht aufgetreten.", 0xFFFF0000 );
+		}
+		n->setVerarbeitet();
+	}
+	for( int i = stkna; i > 0; i-- )
+	{
+		if( !stkn->z( 0 ) || !stkn->z( 0 )->istVerarbeitet() )
+			break;
+		stkna--;
+		stkn->remove( 0 );
+	}
+	unlock();
+}
+
+bool SpielKlasse::tick( double zeit )
+{
+	if( spielPause )
+	{
+		zeit = 0;
+		stknVerarbeitung();
+	}
+	rZeit += zeit;
+	while( spielZeit + TICK < rZeit )
+	{
+		spielZeit += TICK;
+		stknVerarbeitung();
+		if( end )
+			return 1;
+		if( !rEnd->istSichtbar() )
+		{
+			int x = 0;
+			int y = 0;
+			bool setKam = 0;
+			lock();
+			for( int i = 0; i < spielerAnzahl; i++ )
+			{
+				spieler->z( i )->tick( map->zMap(), TICK );
+				if( spielerNummer == spieler->z( i )->getSpielerNummer() )
+				{
+					x = (int)spieler->z( i )->getX();
+					y = (int)spieler->z( i )->getY();
+					setKam = spieler->z( i )->istAmLeben();
+				}
+			}
+			unlock();
+			if( setKam )
+			{
+				double px = ( ( x - kam->getX() ) / 100.0 ) * ( 50 * TICK );
+				double py = ( ( y - kam->getY() ) / 100.0 ) * ( 50 * TICK );
+				kam->addPosition( (int)px, (int)py, map );
+			}
+		}
+		chat->tick( !zeit ? 0.05 : zeit );
+	}
+	return 1;
+}
+
+void SpielKlasse::render( Bild &zRObj )
+{
+	if( !rendern )
+		return;
+	lock();
+	chat->render( zRObj );
+	if( bestenliste )
+		bestenliste->render( zRObj );
+	kam->render( zRObj );
+	int x = kam->getRX( kam->getLinks() ) + 1, y = kam->getRY( kam->getOben() ) + 1;
+	if( zRObj.setDrawOptions( x, y, kam->getRechts() - kam->getLinks() - 2, kam->getUnten() - kam->getOben() - 2 ) )
+	{
+		zRObj.addScrollOffset( x, y );
+		map->render( kam, zRObj );
+		for( int i = 0; i < spielerAnzahl; i++ )
+			spieler->z( i )->render( kam, zRObj );
+		zRObj.releaseDrawOptions();
+	}
+	if( rEnd )
+		rEnd->render( zRObj );
+	if( end )
+		end->render( zRObj );
+	unlock();
+}
+
+// constant
+int SpielKlasse::läuft() const
+{
+	if( !rendern )
+		return 3;
+	if( !end )
+		return 2;
+	if( end && !end->getWeiter() )
+		return 1;
+	if( end && end->getWeiter() )
+		return 0;
+	return 0;
+}
+
+// Reference Counting
+SpielV *SpielKlasse::getThis()
+{
+	ref++;
+	return this;
+}
+
+SpielV *SpielKlasse::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 69 - 0
Linie/Spiel/SpielKlasse.h

@@ -0,0 +1,69 @@
+#ifndef SpielKlasse_H
+#define SpielKlasse_H
+
+#include "SpielV.h"
+#include "Spieler\Spieler.h"
+#include "Karte\Karte.h"
+#include "Chat\Chat.h"
+#include "Ende\RundenEnde.h"
+#include "Ende\Ende.h"
+#include "Bestenliste\Bestenliste.h"
+#include "..\Netzwerk\STKNachricht.h"
+#include <Bildschirm.h>
+
+class SpielKlasse : public SpielV
+{
+private:
+	RCArray< STKNachricht > *stkn;
+	int stkna;
+	Bestenliste *bestenliste;
+	Schrift *schrift;
+	InformationKlientV *infoKlient;
+	SpielKlientV *spielKlient;
+	RCArray< Spieler > *spieler;
+	Bildschirm *screen;
+	Karte *map;
+	Kamera *kam;
+	SpielChat *chat;
+	RundenEnde *rEnd;
+	Ende *end;
+	bool rendern;
+	double spielZeit;
+	double rZeit;
+	bool spielPause;
+	int spielerAnzahl;
+	int karteId;
+	int spielerNummer;
+	char *tasten;
+	int mx;
+	int my;
+	int ref;
+	bool istAmLeben() const;
+
+public:
+	// Konstruktor
+	SpielKlasse();
+	// Destruktor
+	~SpielKlasse();
+	// nicht constant
+	void lock();
+	void unlock();
+	void setSchrift( Schrift *schrift ) override; // call 4
+	void setBildschirm( Bildschirm *screen ) override; // call 3
+	void nachricht( int län, char *bytes ) override;
+	void setKlients( InformationKlientV *infoKlient, SpielKlientV *spielKlient ) override; // call 2
+	void setKarteId( int karteId ) override; // call 1
+	void ladeDaten() override; // call 5
+	void doMausEreignis( MausEreignis &me ) override;
+	void doTastaturEreignis( TastaturEreignis &te ) override;
+	void stknVerarbeitung();
+	bool tick( double zeit ) override;
+	void render( Bild &zRObj ) override;
+	// constant
+	int läuft() const override;
+	// Reference Counting
+	SpielV *getThis() override;
+	SpielV *release() override;
+};
+
+#endif

+ 380 - 0
Linie/Spiel/Spieler/Spieler.cpp

@@ -0,0 +1,380 @@
+#include "Spieler.h"
+#include <Punkt.h>
+#include <math.h>
+#include <Rahmen.h>
+
+// Inhalt der Spieler Klasse aus Spieler.h
+// Konstruktor
+Spieler::Spieler( InformationKlientV *zInfoK )
+{
+	xPos = 0;
+	yPos = 0;
+	xSpeed = 0;
+	ySpeed = 0;
+	kurve = 0;
+	lKurve = 0;
+	rKurve = 0;
+	spielerNummer = 0;
+	team = 0;
+	radius = 1;
+	teamRahmen = new LRahmen();
+	teamRahmen->setRamenBreite( 1 );
+	spielerFarbe = 0;
+	teamFarbe = 0;
+	info = zInfoK->getThis();
+	name = 0;
+	accId = 0;
+	amLeben = 1;
+	linieUnterbrochen = 1;
+	ref = 1;
+}
+
+// Destruktor
+Spieler::~Spieler()
+{
+	teamRahmen->release();
+	info->release();
+	if( name )
+		name->release();
+}
+
+// nicht constant
+void Spieler::neuRunde()
+{
+	xPos = 0;
+	yPos = 0;
+	xSpeed = 0;
+	ySpeed = 0;
+	kurve = 0;
+	lKurve = 0;
+	rKurve = 0;
+	radius = 1;
+	amLeben = 1;
+	linieUnterbrochen = 1;
+}
+
+void Spieler::setAccountId( int accId )
+{
+	this->accId = accId;
+	name = info->getSpielerName( accId );
+}
+
+void Spieler::setSpielerNummer( int num )
+{
+	spielerNummer = num;
+}
+
+void Spieler::setTeam( int team )
+{
+	this->team = team;
+}
+
+void Spieler::setTeamFarbe( int fc )
+{
+	teamFarbe = fc;
+}
+
+void Spieler::setSpielerFarbe( int fc )
+{
+	spielerFarbe = fc;
+}
+
+void Spieler::setPos( double x, double y )
+{
+	xPos = x;
+	yPos = y;
+}
+
+void Spieler::setRadius( int r )
+{
+	radius = r;
+}
+
+void Spieler::setSpeed( double xSpeed, double ySpeed )
+{
+	this->xSpeed = xSpeed;
+	this->ySpeed = ySpeed;
+}
+
+void Spieler::setKurveSpeed( double kurve )
+{
+	this->kurve = kurve;
+}
+
+void Spieler::setLinksKurve( Bild *zMap, bool lKurve, double sendeZeit, double spielZeit )
+{
+	double sZ = -1;
+	if( sendeZeit < spielZeit )
+	{
+		sZ = spielZeit;
+		while( sendeZeit < spielZeit )
+		{
+			tick( zMap, -TICK );
+			spielZeit -= TICK;
+		}
+	}
+	this->lKurve = lKurve;
+	if( sZ >= 0 )
+	{
+		while( spielZeit < sZ )
+		{
+			tick( zMap, TICK );
+			spielZeit += TICK;
+		}
+	}
+}
+
+void Spieler::setRechtsKurve( Bild *zMap, bool rKurve, double sendeZeit, double spielZeit )
+{
+	double sZ = -1;
+	if( sendeZeit < spielZeit )
+	{
+		sZ = spielZeit;
+		while( sendeZeit < spielZeit )
+		{
+			tick( zMap, -TICK );
+			spielZeit -= TICK;
+		}
+	}
+	this->rKurve = rKurve;
+	if( sZ >= 0 )
+	{
+		while( spielZeit < sZ )
+		{
+			tick( zMap, TICK );
+			spielZeit += TICK;
+		}
+	}
+}
+
+void Spieler::sterben( Bild *zMap, double sendeZeit, double spielZeit )
+{
+	if( sendeZeit < spielZeit )
+	{
+		while( sendeZeit < spielZeit )
+		{
+			tick( zMap, -TICK );
+			spielZeit -= TICK;
+		}
+	}
+	amLeben = 0;
+}
+
+void Spieler::sterben()
+{
+	amLeben = 0;
+}
+
+void Spieler::setLinienUnterbrechung( Bild *zMap, bool unterbrechung, double sendeZeit, double spielZeit )
+{
+	double sZ = -1;
+	if( sendeZeit < spielZeit )
+	{
+		sZ = spielZeit;
+		while( sendeZeit < spielZeit )
+		{
+			tick( zMap, -TICK );
+			spielZeit -= TICK;
+		}
+	}
+	linieUnterbrochen = unterbrechung;
+	if( sZ >= 0 )
+	{
+		while( spielZeit < sZ )
+		{
+			tick( zMap, TICK );
+			spielZeit += TICK;
+		}
+	}
+}
+
+void Spieler::prozessKurve( double zeit )
+{
+	if( lKurve || rKurve )
+	{
+		double grad = kurve * zeit;
+		if( lKurve )
+			grad = -grad;
+		double cs = cos( grad );
+		double sn = sin( grad );
+		double tmpX = ( xSpeed * cs - ySpeed * sn );
+		double tmpY = ( xSpeed * sn + ySpeed * cs );
+		xSpeed = tmpX;
+		ySpeed = tmpY;
+	}
+}
+
+void Spieler::tick( Bild *zMap, double zeit )
+{
+	if( amLeben )
+	{
+		if( zeit > 0 )
+			prozessKurve( zeit );
+		int dpx = 0;
+		int dpy = 0;
+		int dgx = zMap->getBreite();
+		int dgy = zMap->getHeight();
+		int *buff = zMap->getBuffer();
+		if( zMap && !linieUnterbrochen )
+		{
+			int x1 = (int)( xPos + 0.5 );
+			int y1 = (int)( yPos + 0.5 );
+			int x2 = (int)( xPos + xSpeed * zeit + 0.5 );
+			int y2 = (int)( yPos + ySpeed * zeit + 0.5 );
+			int xlän = x2 - x1, axlän = abs( xlän );
+			int ylän = y2 - y1, aylän = abs( ylän );
+			double xf = (double)xlän / ( aylän ? aylän : 1 );
+			double yf = (double)ylän / ( axlän ? axlän : 1 );
+			if( axlän > aylän )
+				xf = xf < 0 ? -1 : 1;
+			else
+				yf = yf < 0 ? -1 : 1;
+			double x = (double)x1, y = (double)y1;
+			int maxP = (int)( sqrt( (double)( xlän * xlän + ylän * ylän ) ) + 0.5 );
+			int count = 0;
+			int lastX = (int)( x + 0.5 ), lastY = (int)( y + 0.5 );
+			if( zeit > 0 )
+			{
+				while( !( (int)( x + 0.5 ) == x2 && (int)( y + 0.5 ) == y2 ) && count < maxP )
+				{
+					if( (int)( x + 0.5 ) < dpx || (int)( x + 0.5 ) >= dgx || (int)( y + 0.5 ) < dpy || (int)( y + 0.5 ) >= dgy )
+					{
+						x += xf, y += yf;
+						lastX = (int)( x + 0.5 );
+						lastY = (int)( y + 0.5 );
+						count++;
+						continue;
+					}
+					buff[ (int)( x + 0.5 ) + (int)( y + 0.5 ) * zMap->getBreite() ] = spielerFarbe;
+					x += xf, y += yf;
+					if( lastX != (int)( x + 0.5 ) && lastY != (int)( yf + 0.5 ) )
+					{
+						if( (int)xf )
+						{
+							if( !( lastX < dpx || lastX >= dgx || (int)( y + 0.5 ) < dpy || (int)( y + 0.5 ) >= dgy ) )
+								buff[ lastX + (int)( y + 0.5 ) * zMap->getBreite() ] = spielerFarbe;
+						}
+						else
+						{
+							if( !( (int)( x + 0.5 ) < dpx || (int)( x + 0.5 ) >= dgx || lastY < dpy || lastY >= dgy ) )
+								buff[ (int)( x + 0.5 ) + lastY * zMap->getBreite() ] = spielerFarbe;
+						}
+					}
+					lastX = (int)( x + 0.5 );
+					lastY = (int)( y + 0.5 );
+					count++;
+				}
+			}
+			if( zeit < 0 )
+			{
+				while( !( (int)( x ) == x2 && (int)( y + 0.5 ) == y2 ) && count < maxP )
+				{
+					count++;
+					x += xf, y += yf;
+					if( lastX != (int)( x + 0.5 ) && lastY != (int)( yf + 0.5 ) )
+					{
+						if( (int)xf )
+						{
+							if( !( (int)( x + 0.5 ) < dpx || (int)( x + 0.5 ) >= dgx || lastY < dpy || lastY >= dgy ) )
+								buff[ (int)( x + 0.5 ) + lastY * zMap->getBreite() ] = 0;
+						}
+						else
+						{
+							if( !( lastX < dpx || lastX >= dgx || (int)( y + 0.5 ) < dpy || (int)( y + 0.5 ) >= dgy ) )
+								buff[ lastX + (int)( y + 0.5 ) * zMap->getBreite() ] = 0;
+						}
+					}
+					lastX = (int)( x + 0.5 );
+					lastY = (int)( y + 0.5 );
+					if( !( (int)( x + 0.5 ) < dpx || (int)( x + 0.5 ) >= dgx || (int)( y + 0.5 ) < dpy || (int)( y + 0.5 ) >= dgy ) )
+						buff[ (int)( x + 0.5 ) + (int)( y + 0.5 ) * zMap->getBreite() ] = 0;
+				}
+			}
+		}
+		xPos += xSpeed * zeit;
+		yPos += ySpeed * zeit;
+		if( zeit < 0 )
+			prozessKurve( zeit );
+	}
+}
+
+void Spieler::render( Kamera *zKam, Bild &zRObj )
+{
+	if( amLeben )
+	{
+		if( zKam->istSichtbar( (int)xPos, (int)yPos ) )
+		{
+			teamRahmen->setFarbe( teamFarbe );
+			teamRahmen->setSize( 5 * 2, 5 * 2 );
+			teamRahmen->setPosition( zKam->getRX( (int)xPos ) - 5, zKam->getRY( (int)yPos ) - 5 );
+			zRObj.fillRegion( teamRahmen->getX(), teamRahmen->getY(), 5 * 2, 5 * 2, spielerFarbe );
+			teamRahmen->render( zRObj );
+		}
+	}
+}
+
+// constant
+double Spieler::getX() const
+{
+	return xPos;
+}
+
+double Spieler::getY() const
+{
+	return yPos;
+}
+
+int Spieler::getTeam() const
+{
+	return team;
+}
+
+int Spieler::getTeamFarbe() const
+{
+	return teamFarbe;
+}
+
+int Spieler::getFarbe() const
+{
+	return spielerFarbe;
+}
+
+int Spieler::getSpielerNummer() const
+{
+	return spielerNummer;
+}
+
+bool Spieler::istAmLeben() const
+{
+	return amLeben;
+}
+
+int Spieler::getAccountId() const
+{
+	return accId;
+}
+
+Text *Spieler::getName() const
+{
+	return name ? name->getThis() : 0;
+}
+
+Text *Spieler::zName() const
+{
+	return name;
+}
+
+// Reference Counting
+Spieler *Spieler::getThis()
+{
+	ref++;
+	return this;
+}
+
+Spieler *Spieler::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 71 - 0
Linie/Spiel/Spieler/Spieler.h

@@ -0,0 +1,71 @@
+#ifndef Spieler_H
+#define Spieler_H
+
+#define TICK 0.03333333
+#include <KSGKlientV.h>
+#include "..\Kamera\Kamera.h"
+
+class Spieler
+{
+private:
+	double xPos;
+	double yPos;
+	double xSpeed;
+	double ySpeed;
+	double kurve;
+	bool lKurve;
+	bool rKurve;
+	int spielerNummer;
+	int team;
+	int radius;
+	bool amLeben;
+	bool linieUnterbrochen;
+	int accId;
+	InformationKlientV *info;
+	Text *name;
+	LRahmen *teamRahmen;
+	int spielerFarbe;
+	int teamFarbe;
+	int ref;
+
+public:
+	// Konstruktor
+	Spieler( InformationKlientV *zInfoK );
+	// Destruktor
+	~Spieler();
+	// nicht constant
+	void neuRunde();
+	void setAccountId( int accId );
+	void setSpielerNummer( int num );
+	void setTeam( int team );
+	void setTeamFarbe( int fc );
+	void setSpielerFarbe( int fc );
+	void setPos( double x, double y );
+	void setRadius( int r );
+	void setSpeed( double xSpeed, double ySpeed );
+	void setKurveSpeed( double kurve );
+	void setLinksKurve( Bild *zMap, bool lKurve, double sendeZeit, double spielZeit );
+	void setRechtsKurve( Bild *zMap, bool rKurve, double sendeZeit, double spielzeit );
+	void sterben( Bild *zMap, double sendeZeit, double spielZeit );
+	void sterben();
+	void setLinienUnterbrechung( Bild *zMap, bool unterbrechung, double sendeZeit, double spielZeit );
+	void prozessKurve( double zeit );
+	void tick( Bild *zMap, double zeit );
+	void render( Kamera *zKam, Bild &zRObj );
+	// constant
+	double getX() const;
+	double getY() const;
+	int getTeam() const;
+	int getTeamFarbe() const;
+	int getFarbe() const;
+	int getSpielerNummer() const;
+	bool istAmLeben() const;
+	int getAccountId() const;
+	Text *getName() const;
+	Text *zName() const;
+	// Reference Counting
+	Spieler *getThis();
+	Spieler *release();
+};
+
+#endif

+ 518 - 0
Linie/SpielStatistik/Chat/StatistikChat.cpp

@@ -0,0 +1,518 @@
+#include "StatistikChat.h"
+#include <Punkt.h>
+#include <DateiSystem.h>
+#include <MausEreignis.h>
+#include <AlphaFeld.h>
+#include <Scroll.h>
+#include <Rahmen.h>
+#include <TastaturEreignis.h>
+#include "../../Initialisierung/Initialisierung.h"
+
+// Inhalt der ChatListeSpieler Klasse aus StatistikChat.h
+// Konstruktor
+ChatListeSpieler::ChatListeSpieler( int accountId, int eigeneId, Schrift *zSchrift, BilderV *bilder, InformationKlientV *zInfoc,
+									bool istFreund, void( *addChatF )( void*, int ), void( *addFreundF )( void*, int ),
+									void( *accountAnsehenF )( void *, int ), void *param )
+: addChatF( addChatF ),
+  addFreundF( addFreundF ),
+  accountAnsehenF( accountAnsehenF ),
+  nachrichtParam( param ),
+  accountId( accountId ),
+  bg( new AlphaFeld() ),
+  name( initTextFeld( 0, 0, 133, 20, zSchrift, TextFeld::Style::Text | TextFeld::Style::Rahmen | TextFeld::Style::VCenter, "" ) ),
+  accountAnsehen( initKnopf( 133, 0, 20, 20, 0, 0, "" ) ),
+  nachrichtSenden( initKnopf( 153, 0, 20, 20, 0, 0, "" ) ),
+  freundesanfrageSenden( initKnopf( 173, 0, 20, 20, 0, 0, "" ) ),
+  pos( 0, 0 ),
+  gr( 133, 20 ),
+  online( 1 ),
+  minKnopfX( 113 - ( ( ( accountId != eigeneId ) + !istFreund ) * 20 ) ),
+  knopfX( 133 ),
+  mausIn( 0 ),
+  tickVal( 0 ),
+  rend( 0 ),
+  ref( 1 )
+{
+	Bild *ansehenBild = bilder->get( "chat.ltdb/ansehen.png" );
+	if( !ansehenBild )
+	{
+		LTDBDatei *datei = new LTDBDatei();
+		datei->setDatei( new Text( "data/client/bilder/chat.ltdb" ) );
+		datei->leseDaten( 0 );
+		ansehenBild = datei->laden( 0, new Text( "ansehen.png" ) );
+		datei->release();
+		bilder->add( "chat.ltdb/ansehen.png", ansehenBild->getThis() );
+	}
+	Bild *nachrichtBild = bilder->get( "chat.ltdb/nachricht.png" );
+	if( !nachrichtBild )
+	{
+		LTDBDatei *datei = new LTDBDatei();
+		datei->setDatei( new Text( "data/client/bilder/chat.ltdb" ) );
+		datei->leseDaten( 0 );
+		nachrichtBild = datei->laden( 0, new Text( "nachricht.png" ) );
+		datei->release();
+		bilder->add( "chat.ltdb/nachricht.png", nachrichtBild->getThis() );
+	}
+	Bild *einladungBild = bilder->get( "chat.ltdb/neuerfreund.png" );
+	if( !nachrichtBild )
+	{
+		LTDBDatei *datei = new LTDBDatei();
+		datei->setDatei( new Text( "data/client/bilder/chat.ltdb" ) );
+		datei->leseDaten( 0 );
+		einladungBild = datei->laden( 0, new Text( "neuerfreund.png" ) );
+		datei->release();
+		bilder->add( "chat.ltdb/neuerfreund.png", einladungBild->getThis() );
+	}
+	bg->setSize( gr );
+	bg->setFarbe( 0x0000FF00 );
+	bg->setStrength( -4 );
+	name->setText( zInfoc->getSpielerName( accountId ) );
+	accountAnsehen->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
+	accountAnsehen->setHintergrundBildZ( ansehenBild );
+	nachrichtSenden->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
+	nachrichtSenden->setHintergrundBildZ( nachrichtBild );
+	freundesanfrageSenden->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
+	freundesanfrageSenden->setHintergrundBildZ( einladungBild );
+}
+
+// Destruktor
+ChatListeSpieler::~ChatListeSpieler()
+{
+	bg->release();
+	name->release();
+	accountAnsehen->release();
+	nachrichtSenden->release();
+	freundesanfrageSenden->release();
+}
+
+// nicht constant
+void ChatListeSpieler::setOffline()
+{
+	online = 0;
+}
+
+void ChatListeSpieler::setPosition( int y )
+{
+	if( pos.y != y )
+		rend = 1;
+	pos.y = y;
+}
+
+void ChatListeSpieler::doMausEreignis( MausEreignis &me )
+{
+	int mx = me.mx;
+	int my = me.my;
+	me.mx -= pos.x;
+	me.my -= pos.y;
+	if( me.mx > 0 && me.mx < gr.x && me.my > 0 && me.my < gr.y )
+		mausIn = 1;
+	else
+		mausIn = 0;
+	me.mx += 133 - knopfX;
+	bool vera = me.verarbeitet;
+	accountAnsehen->doMausEreignis( me );
+	int aktion = ( me.verarbeitet && !vera ) ? 1 : 0;
+	nachrichtSenden->doMausEreignis( me );
+	aktion = ( me.verarbeitet && !vera && !aktion ) ? 2 : aktion;
+	freundesanfrageSenden->doMausEreignis( me );
+	aktion = ( me.verarbeitet && !vera && !aktion ) ? 3 : aktion;
+	me.mx -= 133 - knopfX;
+	if( me.id == ME_RLinks && mausIn )
+	{
+		switch( aktion )
+		{
+		case 1:
+			accountAnsehenF( nachrichtParam, accountId );
+			break;
+		case 2:
+			addChatF( nachrichtParam, accountId );
+			break;
+		case 3:
+			addFreundF( nachrichtParam, accountId );
+			break;
+		}
+	}
+	me.mx = mx;
+	me.my = my;
+}
+
+bool ChatListeSpieler::tick( double tickVal )
+{
+	rend |= name->tick( tickVal );
+	rend |= accountAnsehen->tick( tickVal );
+	rend |= nachrichtSenden->tick( tickVal );
+	rend |= freundesanfrageSenden->tick( tickVal );
+	this->tickVal += tickVal * 60;
+	int val = ( int )this->tickVal;
+	if( val )
+	{
+		this->tickVal -= val;
+		if( mausIn && knopfX != minKnopfX )
+		{
+			if( knopfX - val < minKnopfX )
+				knopfX = minKnopfX;
+			else
+				knopfX -= val;
+			rend = 1;
+		}
+		if( !mausIn && knopfX != gr.x )
+		{
+			if( knopfX + val > gr.x )
+				knopfX = gr.x;
+			else
+				knopfX += val;
+			rend = 1;
+		}
+		if( !online && bg->getFarbe() != 0x00FF0000 )
+		{
+			int g = ( bg->getFarbe() >> 8 ) & 0xFF;
+			if( g - val < 0 )
+				bg->setFarbe( 0x00FF0000 );
+			else
+			{
+				bg->setFarbe( ( ( ( g - val ) << 8 ) & 0xFF00 ) | ( bg->getFarbe() & 0xFFFF00FF ) );
+				bg->setFarbe( ( ( ( 255 - (g - val) ) << 16 ) & 0xFF0000 ) | ( bg->getFarbe() & 0xFF00FFFF ) );
+			}
+			rend = 1;
+		}
+	}
+	bool ret = rend;
+	rend = 0;
+	return ret;
+}
+
+void ChatListeSpieler::render( Bild &zRObj )
+{
+	if( !zRObj.setDrawOptions( pos, gr ) )
+		return;
+	bg->render( zRObj );
+	name->render( zRObj );
+	zRObj.addScrollOffset( 133 - knopfX, 0 );
+	accountAnsehen->render( zRObj );
+	nachrichtSenden->render( zRObj );
+	freundesanfrageSenden->render( zRObj );
+	zRObj.releaseDrawOptions();
+}
+
+// constant
+int ChatListeSpieler::getAccountId() const
+{
+	return accountId;
+}
+
+// Reference Counting
+ChatListeSpieler *ChatListeSpieler::getThis()
+{
+	ref++;
+	return this;
+}
+
+ChatListeSpieler *ChatListeSpieler::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der ChatListe Klasse aus StatistikChat.h
+// Konstruktor
+ChatListe::ChatListe( int eigeneId, InformationKlientV *infoc, Schrift *schrift, BilderV *bilder,
+					  void( *addChat )( void*, int ), void( *addFreund )( void*, int ),
+					  void( *accountAnsehen )( void *, int ), void *param )
+: addChat( addChat ),
+  addFreund( addFreund ),
+  accountAnsehen( accountAnsehen ),
+  nachrichtParam( nachrichtParam ),
+  eigeneId( eigeneId ),
+  spieler( new RCArray< ChatListeSpieler >() ),
+  vScroll( new VScrollBar() ),
+  pos( 420, 295 ),
+  gr( 150, 150 ),
+  infoc( infoc ),
+  schrift( schrift ),
+  bilder( bilder ),
+  ram( new LRahmen() ),
+  rend( 0 ),
+  ref( 1 )
+{
+	vScroll->setKlickScroll( 10 );
+	vScroll->update( 0, 148 );
+	ram->setFarbe( 0xFFFFFFFF );
+	ram->setSize( 150, 150 );
+}
+
+// Destruktor
+ChatListe::~ChatListe()
+{
+	spieler->release();
+	vScroll->release();
+	infoc->release();
+	schrift->release();
+	ram->release();
+}
+
+// nicht constant
+void ChatListe::addSpieler( int accountId, bool istFreund )
+{
+	int anz = spieler->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spieler->z( i ) && spieler->z( i )->getAccountId() == accountId )
+			return;
+	}
+	ChatListeSpieler *s = new ChatListeSpieler( accountId, eigeneId, schrift, bilder, infoc, istFreund, addChat, addFreund, accountAnsehen, nachrichtParam );
+	s->setPosition( anz * 20 );
+	spieler->add( s );
+	rend = 1;
+}
+
+void ChatListe::setOffline( int accountId )
+{
+	int anz = spieler->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spieler->z( i ) && spieler->z( i )->getAccountId() == accountId )
+		{
+			spieler->z( i )->setOffline();
+			return;
+		}
+	}
+}
+
+void ChatListe::doMausEreignis( MausEreignis &me )
+{
+	int mx = me.mx;
+	int my = me.my;
+	me.mx -= pos.x;
+	me.my -= pos.y - vScroll->getScroll();
+	vScroll->doMausMessage( 134, 1, 15, 148, me );
+	int anz = spieler->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spieler->z( i ) )
+			spieler->z( i )->doMausEreignis( me );
+	}
+	me.mx = mx;
+	me.my = my;
+}
+
+bool ChatListe::tick( double tickVal )
+{
+	rend |= vScroll->getRend();
+	int anz = spieler->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spieler->z( i ) )
+			rend |= spieler->z( i )->tick( tickVal );
+	}
+	bool ret = rend;
+	rend = 0;
+	return ret;
+}
+
+void ChatListe::render( Bild &zRObj )
+{
+	if( !zRObj.setDrawOptions( pos, gr ) )
+		return;
+	int anz = spieler->getEintragAnzahl();
+	zRObj.addScrollOffset( 0, vScroll->getScroll() );
+	for( int i = 0; i < anz; i++ )
+	{
+		if( spieler->z( i ) )
+			spieler->z( i )->render( zRObj );
+	}
+	zRObj.addScrollOffset( 0, -vScroll->getScroll() );
+	vScroll->render( 134, 1, 15, 148, zRObj );
+	ram->render( zRObj );
+	zRObj.releaseDrawOptions();
+}
+
+// constant
+
+// Reference Counting
+ChatListe *ChatListe::getThis()
+{
+	ref++;
+	return this;
+}
+
+ChatListe *ChatListe::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}
+
+
+// Inhalt der StatistikChat Klasse aus StatistikChat.h
+// Konstruktor
+StatistikChat::StatistikChat( int eigeneId, SpielKlientV *spielc, InformationKlientV *infoc, Schrift *schrift, BilderV *bilder,
+							  void( *addNachricht )( void *, Text *, Text *, Text *, Text *, char, void * ),
+							  void( *addChat )( void*, int ), void( *addFreund )( void*, int ),
+							  void( *accountAnsehen )( void *, int ), void *param )
+: addNachricht( addNachricht ),
+  nachrichtParam( nachrichtParam ),
+  spielc( spielc ),
+  infoc( infoc ),
+  verlauf( initTextFeld( 10, 295, 400, 150, schrift, TextFeld::Style::Sichtbar | TextFeld::Style::Rahmen | TextFeld::Style::VScroll | TextFeld::Style::Mehrzeilig, "" ) ),
+  nachricht( initTextFeld( 10, 450, 375, 20, schrift, TextFeld::Style::TextFeld, "" ) ),
+  senden( initKnopf( 390, 450, 20, 20, 0, 0, "" ) ),
+  verlassen( initKnopf( 430, 450, 130, 20, schrift, Knopf::Style::Sichtbar, "Verlassen" ) ),
+  spielerListe( new ChatListe( eigeneId, infoc->getThis(), schrift, bilder, addChat, addFreund, accountAnsehen, nachrichtParam ) ),
+  beenden( 0 ),
+  ref( 1 )
+{
+	Bild *sendenBild = bilder->get( "chat.ltdb/senden.png" );
+	if( !sendenBild )
+	{
+		LTDBDatei *datei = new LTDBDatei();
+		datei->setDatei( new Text( "data/client/bilder/chat.ltdb" ) );
+		datei->leseDaten( 0 );
+		sendenBild = datei->laden( 0, new Text( "senden.png" ) );
+		datei->release();
+		bilder->add( "chat.ltdb/senden.png", sendenBild->getThis() );
+	};
+	senden->setStyle( Knopf::Style::Sichtbar | Knopf::Style::Erlaubt | Knopf::Style::Hintergrund | Knopf::Style::HAlpha | Knopf::Style::HBild | Knopf::Style::KlickBuffer );
+	senden->setHintergrundBildZ( sendenBild );
+}
+
+// Destruktor
+StatistikChat::~StatistikChat()
+{
+	spielc->release();
+	infoc->release();
+	verlauf->release();
+	nachricht->release();
+	senden->release();
+	verlassen->release();
+	spielerListe->release();
+}
+
+// nicht constant
+void StatistikChat::addSpieler( int accountId, bool istFreund )
+{
+	spielerListe->addSpieler( accountId, istFreund );
+}
+
+void StatistikChat::spielerOffline( int accountId )
+{
+	spielerListe->setOffline( accountId );
+}
+
+void StatistikChat::addChatNachricht( int vonAccount, char *nachricht )
+{
+	Text *txt = vonAccount ? infoc->getSpielerName( vonAccount ) : 0;
+	if( !txt )
+		txt = new Text();
+	else
+		*txt += ": ";
+	*txt += nachricht;
+	*txt += "\n";
+	verlauf->zSchrift()->textFormatieren( txt, verlauf->getBreite() - 15, 12 );
+	verlauf->zText()->append( txt );
+	verlauf->updateVScroll();
+}
+
+void StatistikChat::doMausEreignis( MausEreignis &me )
+{
+	verlauf->doMausEreignis( me );
+	nachricht->doMausEreignis( me );
+	spielerListe->doMausEreignis( me );
+	bool vera = me.verarbeitet;
+	senden->doMausEreignis( me );
+	int aktion = ( me.verarbeitet && !vera ) ? 1 : 0;
+	verlassen->doMausEreignis( me );
+	aktion = ( me.verarbeitet && !vera && !aktion ) ? 2 : aktion;
+	if( me.id == ME_RLinks )
+	{
+		if( aktion == 1 )
+		{
+			if( nachricht->zText()->getLength() )
+			{
+				short län = 1 + nachricht->zText()->getLength();
+				char *bytes = new char[ län ];
+				bytes[ 0 ] = 2;
+				for( int i = 0; i < län - 1; i++ )
+					bytes[ i + 1 ] = nachricht->zText()->getText()[ i ];
+				if( !spielc->statistikNachricht( län, bytes ) )
+					addNachricht( nachrichtParam, new Text( "Fehler" ), new Text( "Die Nachricht konnte nicht gesendet werden." ), new Text( "Ok" ), 0, 0, 0 );
+				else
+				{
+					nachricht->setAuswahl( 0, 0 );
+					nachricht->setText( "" );
+				}
+				delete[] bytes;
+			}
+		}
+		if( aktion == 2 )
+			beenden = 1;
+	}
+}
+
+void StatistikChat::doTastaturEreignis( TastaturEreignis &te )
+{
+	bool vera = te.verarbeitet;
+	nachricht->doTastaturEreignis( te );
+	if( !vera && te.verarbeitet && te.id == TE_Release && te.taste == T_Enter )
+	{
+		if( nachricht->zText()->getLength() )
+		{
+			short län = 1 + nachricht->zText()->getLength();
+			char *bytes = new char[ län ];
+			bytes[ 0 ] = 2;
+			for( int i = 0; i < län - 1; i++ )
+				bytes[ i + 1 ] = nachricht->zText()->getText()[ i ];
+			if( !spielc->statistikNachricht( län, bytes ) )
+				addNachricht( nachrichtParam, new Text( "Fehler" ), new Text( "Die Nachricht konnte nicht gesendet werden." ), new Text( "Ok" ), 0, 0, 0 );
+			else
+			{
+				nachricht->setAuswahl( 0, 0 );
+				nachricht->setText( "" );
+			}
+			delete[] bytes;
+		}
+	}
+}
+
+bool StatistikChat::tick( double tickVal )
+{
+	bool rend = verlauf->tick( tickVal );
+	rend |= nachricht->tick( tickVal );
+	rend |= senden->tick( tickVal );
+	rend |= verlassen->tick( tickVal );
+	rend |= spielerListe->tick( tickVal );
+	return rend;
+}
+
+void StatistikChat::render( Bild &zRObj )
+{
+	verlauf->render( zRObj );
+	nachricht->render( zRObj );
+	senden->render( zRObj );
+	verlassen->render( zRObj );
+	spielerListe->render( zRObj );
+}
+
+// constant
+bool StatistikChat::hatVerlassen()
+{
+	return beenden;
+}
+
+// Reference Counting
+StatistikChat *StatistikChat::getThis()
+{
+	ref++;
+	return this;
+}
+
+StatistikChat *StatistikChat::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 131 - 0
Linie/SpielStatistik/Chat/StatistikChat.h

@@ -0,0 +1,131 @@
+#ifndef StatistikChat_H
+#define StatistikChat_H
+
+#include <Fenster.h>
+#include <Knopf.h>
+#include <KSGKlientV.h>
+#include <BilderV.h>
+
+using namespace Framework;
+
+class ChatListeSpieler
+{
+private:
+	void( *addChatF )( void *, int );
+	void( *addFreundF )( void *, int );
+	void( *accountAnsehenF )( void *, int );
+	void *nachrichtParam;
+	int accountId;
+	AlphaFeld *bg;
+	TextFeld *name;
+	Knopf *accountAnsehen;
+	Knopf *nachrichtSenden;
+	Knopf *freundesanfrageSenden;
+	Punkt pos;
+	Punkt gr;
+	bool online;
+	int minKnopfX;
+	int knopfX;
+	bool mausIn;
+	double tickVal;
+	bool rend;
+	int ref;
+
+public:
+	// Konstruktor
+	 ChatListeSpieler( int accountId, int eigeneId, Schrift *zSchrift, BilderV *bilder, InformationKlientV *zInfoc,
+											  bool istFreund, void( *addChatF )( void*, int ), void( *addFreundF )( void*, int ),
+											  void( *accountAnsehenF )( void *, int ), void *param );
+	// Destruktor
+	 ~ChatListeSpieler();
+	// nicht constant
+	 void setOffline();
+	 void setPosition( int y );
+	 void doMausEreignis( MausEreignis &me );
+	 bool tick( double tickVal );
+	 void render( Bild &zRObj );
+	// constant
+	 int getAccountId() const;
+	// Reference Counting
+	 ChatListeSpieler *getThis();
+	 ChatListeSpieler *release();
+};
+
+class ChatListe
+{
+private:
+	void( *addChat )( void *, int );
+	void( *addFreund )( void *, int );
+	void( *accountAnsehen )( void *, int );
+	void *nachrichtParam;
+	int eigeneId;
+	RCArray< ChatListeSpieler > *spieler;
+	VScrollBar *vScroll;
+	Punkt pos;
+	Punkt gr;
+	InformationKlientV *infoc;
+	Schrift *schrift;
+	BilderV *bilder;
+	LRahmen *ram;
+	bool rend;
+	int ref;
+
+public:
+	// Konstruktor
+	 ChatListe( int eigeneId, InformationKlientV *infoc, Schrift *schrift, BilderV *bilder,
+									   void( *addChat )( void*, int ), void( *addFreund )( void*, int ),
+									   void( *accountAnsehen )( void *, int ), void *param );
+	// Destruktor
+	 ~ChatListe();
+	// nicht constant
+	 void addSpieler( int accountId, bool istFreund );
+	 void setOffline( int accountId );
+	 void doMausEreignis( MausEreignis &me );
+	 bool tick( double tickVal );
+	 void render( Bild &zRObj );
+	// constant
+
+	// Reference Counting
+	 ChatListe *getThis();
+	 ChatListe *release();
+};
+
+class StatistikChat
+{
+private:
+	void( *addNachricht )( void *, Text *, Text *, Text *, Text *, char, void * );
+	void *nachrichtParam;
+	SpielKlientV *spielc;
+	InformationKlientV *infoc;
+	TextFeld *verlauf;
+	TextFeld *nachricht;
+	Knopf *senden;
+	Knopf *verlassen;
+	ChatListe *spielerListe;
+	bool beenden;
+	int ref;
+
+public:
+	// Konstruktor
+	StatistikChat( int eigeneId, SpielKlientV *spielc, InformationKlientV *infoc, Schrift *schrift, BilderV *bilder,
+										   void( *addNachricht )( void *, Text *, Text *, Text *, Text *, char, void * ),
+										   void( *addChat )( void*, int ), void( *addFreund )( void*, int ),
+										   void( *accountAnsehen )( void *, int ), void *param );
+	// Destruktor
+	~StatistikChat();
+	// nicht constant
+	void addSpieler( int accountId, bool istFreund );
+	void spielerOffline( int accountId );
+	void addChatNachricht( int vonAccount, char *nachricht );
+	void doMausEreignis( MausEreignis &me );
+	void doTastaturEreignis( TastaturEreignis &te );
+	bool tick( double tickVal );
+	void render( Bild &zRObj );
+	// constant
+	bool hatVerlassen();
+	// Reference Counting
+	StatistikChat *getThis();
+	StatistikChat *release();
+};
+
+#endif

+ 142 - 0
Linie/SpielStatistik/Runde/StatistikRunde.cpp

@@ -0,0 +1,142 @@
+#include "StatistikRunde.h"
+#include "../../Initialisierung/Initialisierung.h"
+#include <Punkt.h>
+
+// Inhalt der StatistikRunde Klasse aus StatistikRunde.h
+// Konstruktor
+StatistikRunde::StatistikRunde( Schrift *zSchrift, Array< SSDRunde* > *dat, bool historie )
+	: rundenBild( initBildZ( 525, 40, 245, 245, BildZ::Style::normal, 0 ) ),
+  rundenNummer( initTextFeld( 580, 295, 190, 20, zSchrift, TextFeld::Style::Text, "Runde: " ) ),
+  rundenDauer( initTextFeld( 580, 325, 190, 20, zSchrift, TextFeld::Style::Text, "Dauer: " ) ),
+  rundenSieger( initTextFeld( 580, 355, 190, 20, zSchrift, TextFeld::Style::Text, "Sieger: " ) ),
+  spielfeldNutzung( initTextFeld( 580, 385, 190, 20, zSchrift, TextFeld::Style::Text, "Spielfeldnutzung: " ) ),
+  verbleibend( initTextFeld( 580, 415, 190, 20, zSchrift, TextFeld::Style::Text, "Verbleibende Zeit: 300" ) ),
+  daten( dat ),
+  auswahl( -1 ),
+  verb( 300 ),
+  rend( 0 ),
+  ref( 1 )
+{
+	if( historie )
+	{
+		verbleibend->removeStyle( TextFeld::Style::Sichtbar );
+		rundenBild->setPosition( 520, 10 );
+		rundenBild->setSize( 250, 250 );
+		rundenNummer->setPosition( 520, 270 );
+		rundenDauer->setPosition( 520, 300 );
+		rundenSieger->setPosition( 520, 330 );
+		spielfeldNutzung->setPosition( 520, 360 );
+	}
+}
+
+// Destruktor 
+StatistikRunde::~StatistikRunde()
+{
+    rundenBild;
+	rundenNummer->release();
+	rundenDauer->release();
+	rundenSieger->release();
+	spielfeldNutzung->release();
+	verbleibend->release();
+	daten->release();
+}
+
+// nicht constant
+void StatistikRunde::setRunde( int nummer )
+{
+	if( nummer != auswahl )
+	{
+		Bild *b = new Bild();
+		b->neuBild( 1, 1, 0 );
+		rundenBild->setBildZ( b );
+		rundenNummer->setText( "Runde: " );
+		rundenDauer->setText( "Dauer: " );
+		rundenSieger->setText( "Sieger: " );
+		spielfeldNutzung->setText( "Spielfeldnutzung: " );
+		int anz = daten->getEintragAnzahl();
+		for( int i = 0; i < anz; i++ )
+		{
+			if( daten->hat( i ) && daten->get( i )->rundenNummer == nummer )
+			{
+				Bild *b = new Bild();
+				b->neuBild( daten->get( i )->rundenBild.getBreite(), daten->get( i )->rundenBild.getHeight(), 0 );
+				b->drawBild( 0, 0, b->getBreite(), b->getHeight(), daten->get( i )->rundenBild );
+				rundenBild->setBildZ( b );
+				*rundenNummer->zText() += nummer + 1;
+				*rundenDauer->zText() += daten->get( i )->rundenDauer / 60;
+				*rundenDauer->zText() += ":";
+				*rundenDauer->zText() += daten->get( i )->rundenDauer % 60;
+				int anz2 = daten->get( i )->teams.getEintragAnzahl();
+				for( int j = 0; j < anz; j++ )
+				{
+					if( daten->get( i )->teams.hat( j ) && daten->get( i )->teams.get( j )->teamNummer == daten->get( i )->rundenSieger )
+					{
+						*rundenSieger->zText() += daten->get( i )->teams.get( j )->teamName.getText();
+						break;
+					}
+				}
+				*spielfeldNutzung->zText() += daten->get( i )->spielfeldNutzung;
+				*spielfeldNutzung->zText() += "%";
+				auswahl = nummer;
+				rend = 1;
+				return;
+			}
+		}
+		auswahl = -1;
+		rend = 1;
+	}
+}
+
+void StatistikRunde::doMausEreignis( MausEreignis &me )
+{
+	rundenBild->doMausEreignis( me );
+}
+
+bool StatistikRunde::tick( double tickVal )
+{
+	int verbl = (int)verb;
+	verb -= tickVal;
+	if( verb < 0 )
+		verb = 0;
+	if( verbl != (int)verb )
+	{
+		verbleibend->setText( "Verbleibende Zeit: " );
+		*verbleibend->zText() += (int)verb;
+		rend = 1;
+	}
+	rend |= rundenBild->tick( tickVal );
+	bool ret = rend;
+	rend = 0;
+	return ret;
+}
+
+void StatistikRunde::render( Bild &zRObj )
+{
+	rundenBild->render( zRObj );
+	rundenNummer->render( zRObj );
+	rundenDauer->render( zRObj );
+	rundenSieger->render( zRObj );
+	spielfeldNutzung->render( zRObj );
+	verbleibend->render( zRObj );
+}
+
+// constant
+bool StatistikRunde::mussVerlassen() const
+{
+	return verb == 0;
+}
+
+// Reference Counting
+StatistikRunde *StatistikRunde::getThis()
+{
+	ref++;
+	return this;
+}
+
+StatistikRunde *StatistikRunde::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 42 - 0
Linie/SpielStatistik/Runde/StatistikRunde.h

@@ -0,0 +1,42 @@
+#ifndef StatistikRunde_H
+#define StatistikRunde_H
+
+#include <Bild.h>
+#include <TextFeld.h>
+#include "../SpielStatistikDaten.h"
+
+using namespace Framework;
+
+class StatistikRunde
+{
+private:
+	BildZ *rundenBild;
+	TextFeld *rundenNummer;
+	TextFeld *rundenDauer;
+	TextFeld *rundenSieger;
+	TextFeld *spielfeldNutzung;
+	TextFeld *verbleibend;
+	Array< SSDRunde* > *daten;
+	int auswahl;
+	double verb;
+	bool rend;
+	int ref;
+
+public:
+	// Konstruktor
+	StatistikRunde( Schrift *zSchrift, Array< SSDRunde* > *dat, bool historie = 0 );
+	// Destruktor
+	~StatistikRunde();
+	// nicht constant
+	void setRunde( int nummer );
+	void doMausEreignis( MausEreignis &me );
+	bool tick( double tickVal );
+	void render( Bild &zRObj );
+	// constant
+	bool mussVerlassen() const;
+	// Reference Counting
+	StatistikRunde *getThis();
+	StatistikRunde *release();
+};
+
+#endif

+ 564 - 0
Linie/SpielStatistik/SpielStatistik.cpp

@@ -0,0 +1,564 @@
+#include "SpielStatistik.h"
+#include "../Initialisierung/Initialisierung.h"
+#include <MausEreignis.h>
+#include <Punkt.h>
+
+// Inhalt der SpielStatistik Klasse aus SpielStatistik.h
+// Konstruktor
+SpielStatistik::SpielStatistik()
+{
+	InitializeCriticalSection( &cs );
+	addNachrichtF = 0;
+	addChatF = 0;
+	addFreundF = 0;
+	accountAnsehenF = 0;
+	istFreundF = 0;
+	nachrichtParam = 0;
+	bilder = 0;
+	schrift = 0;
+	screen = 0;
+	infoc = 0;
+	spielc = 0;
+	status = 0;
+	gss = new Array< SSDGesamtSpieler* >();
+	gts = new Array< SSDGesamtTeam* >();
+	rs = new Array< SSDRunde* >();
+	chat = 0;
+	runde = 0;
+	tabelle = 0;
+	accountId = 0;
+	rend = 0;
+	ref = 1;
+}
+
+// Destruktor
+SpielStatistik::~SpielStatistik()
+{
+	if( chat )
+		chat->release();
+	if( runde )
+		runde->release();
+	if( tabelle )
+		tabelle->release();
+	if( schrift )
+		schrift->release();
+	if( screen )
+		screen->release();
+	if( infoc )
+		infoc->release();
+	if( spielc )
+		spielc->release();
+	int anz = gss->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( gss->hat( i ) )
+			delete gss->get( i );
+	}
+	gss->release();
+	anz = gts->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( gts->hat( i ) )
+			delete gts->get( i );
+	}
+	gts->release();
+	anz = rs->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( rs->hat( i ) )
+		{
+			int anz2 = rs->get( i )->spieler.getEintragAnzahl();
+			for( int j = 0; j < anz2; j++ )
+			{
+				if( rs->get( i )->spieler.hat( j ) )
+					delete rs->get( i )->spieler.get( j );
+			}
+			anz2 = rs->get( i )->teams.getEintragAnzahl();
+			for( int j = 0; j < anz2; j++ )
+			{
+				if( rs->get( i )->teams.hat( j ) )
+					delete rs->get( i )->teams.get( j );
+			}
+			delete rs->get( i );
+		}
+	}
+	rs->release();
+	DeleteCriticalSection( &cs );
+}
+
+// nicht constant
+void SpielStatistik::lock()
+{
+	EnterCriticalSection( &cs );
+}
+
+void SpielStatistik::unlock()
+{
+	LeaveCriticalSection( &cs );
+}
+
+void SpielStatistik::bereit()
+{
+	char byte = 1;
+	spielc->statistikNachricht( 1, &byte );
+}
+
+void SpielStatistik::setBilder( BilderV *b )
+{
+	bilder = b;
+}
+
+void SpielStatistik::setAccountId( int id )
+{
+	accountId = id;
+}
+
+void SpielStatistik::setRückrufFunktionen( void( *addNachrichtF )( void *, Text *, Text *, Text *, Text *, char, void * ),
+										   void( *addChatF )( void *, int ), void( *addFreundF )( void *, int ),
+										   void( *accountAnsehenF )( void *, int ), bool( *istFreundF )( void *, int ), void *nachrichtParam )
+{
+	this->addNachrichtF = addNachrichtF;
+	this->addChatF = addChatF;
+	this->addFreundF = addFreundF;
+	this->accountAnsehenF = accountAnsehenF;
+	this->istFreundF = istFreundF;
+	this->nachrichtParam = nachrichtParam;
+}
+
+void SpielStatistik::setSchrift( Schrift *schrift )
+{
+	if( this->schrift )
+		this->schrift->release();
+	this->schrift = schrift;
+}
+
+void SpielStatistik::setBildschirm( Bildschirm *screen )
+{
+	if( this->screen )
+		this->screen->release();
+	this->screen = screen;
+}
+
+void SpielStatistik::setKlients( InformationKlientV *infoc, SpielKlientV *spielc )
+{
+	if( this->infoc )
+		this->infoc->release();
+	if( this->spielc )
+		this->spielc->release();
+	this->infoc = infoc;
+	this->spielc = spielc;
+}
+
+void SpielStatistik::nachricht( int län, char *bytes )
+{
+	lock();
+	char num = *bytes;
+	bytes++;
+	län--;
+	switch( num )
+	{
+	case 1: // Ladevorgang abgeschlossen
+		if( 1 )
+		{
+			chat = new StatistikChat( accountId, spielc->getThis(), infoc->getThis(), schrift->getThis(), bilder, addNachrichtF, addChatF, addFreundF, accountAnsehenF, nachrichtParam );
+			int anz = gss->getEintragAnzahl();
+			for( int i = 0; i < anz; i++ )
+			{
+				if( gss->hat( i ) )
+				{
+					int acc = infoc->getAccountId( gss->get( i )->spielerName );
+					if( acc )
+						chat->addSpieler( acc, istFreundF( nachrichtParam, acc ) || acc == accountId );
+				}
+			}
+			runde = new StatistikRunde( schrift, rs->getThis() );
+			tabelle = new StatistikTabelle( gss->getThis(), gts->getThis(), rs->getThis(), schrift, screen );
+			status = 1;
+		}
+		break;
+	case 2: // Gesammt Spieler Statistik
+		if( 1 )
+		{
+			SSDGesamtSpieler *ssdgs = new SSDGesamtSpieler();
+			ssdgs->spielerNummer = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			char snlän = *bytes;
+			län--;
+			bytes++;
+			char *txt = new char[ snlän + 1 ];
+			txt[ snlän ] = 0;
+			for( int i = 0; i < snlän; i++ )
+				txt[ i ] = bytes[ i ];
+			bytes += snlän;
+			län -= snlän;
+			ssdgs->spielerName = txt;
+			delete[] txt;
+			char tnlän = *bytes;
+			län--;
+			bytes++;
+			txt = new char[ tnlän + 1 ];
+			txt[ tnlän ] = 0;
+			for( int i = 0; i < tnlän; i++ )
+				txt[ i ] = bytes[ i ];
+			bytes += tnlän;
+			län -= tnlän;
+			ssdgs->teamName = txt;
+			delete[] txt;
+			ssdgs->spielerFarbe = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgs->teamFarbe = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgs->gewonneneRunden = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgs->punkte = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgs->linienLänge = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgs->zeitAmLeben = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgs->zeitTod = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgs->kills = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgs->tode = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			gss->add( ssdgs );
+		}
+		break;
+	case 3: // Gesammt Team Statistik
+		if( 1 )
+		{
+			SSDGesamtTeam *ssdgt = new SSDGesamtTeam();
+			ssdgt->teamNummer = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			char tnlän = *bytes;
+			län--;
+			bytes++;
+			char *txt = new char[ tnlän + 1 ];
+			txt[ tnlän ] = 0;
+			for( int i = 0; i < tnlän; i++ )
+				txt[ i ] = bytes[ i ];
+			bytes += tnlän;
+			län -= tnlän;
+			ssdgt->teamName = txt;
+			delete[] txt;
+			ssdgt->teamFarbe = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgt->gewonneneRunden = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgt->punkte = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgt->linienLänge = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgt->kills = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdgt->tode = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			gts->add( ssdgt );
+		}
+		break;
+	case 4: // Runde Statistik
+		if( 1 )
+		{
+			SSDRunde *ssdr = new SSDRunde();
+			ssdr->rundenNummer = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdr->rundenDauer = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdr->rundenSieger = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdr->spielfeldNutzung = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			int breite = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			int höhe = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			ssdr->rundenBild.neuBild( breite, höhe, 0 );
+			rs->add( ssdr );
+		}
+		break;
+	case 5: // Runde Bild
+		if( 1 )
+		{
+			int runde = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			int *buff = 0;
+			int max = 0;
+			int anz = rs->getEintragAnzahl();
+			for( int i = 0; i < anz; i++ )
+			{
+				if( rs->hat( i ) && rs->get( i )->rundenNummer == runde )
+				{
+					buff = rs->get( i )->rundenBild.getBuffer();
+					max = rs->get( i )->rundenBild.getBreite() * rs->get( i )->rundenBild.getHeight();
+					break;
+				}
+			}
+			if( !buff )
+				break;
+			int index = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			int plän = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			for( int i = 0; i < plän; i++ )
+			{
+				if( index + i >= max )
+					break;
+				buff[ index + i ] = *(int*)bytes;
+				bytes += 4;
+				län -= 4;
+			}
+		}
+		break;
+	case 6: // Runde Spieler Statistik
+		if( 1 )
+		{
+			int runde = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			int anz = rs->getEintragAnzahl();
+			for( int i = 0; i < anz; i++ )
+			{
+				if( rs->hat( i ) && rs->get( i )->rundenNummer == runde )
+				{
+					SSDRundeSpieler *ssdrs = new SSDRundeSpieler();
+					ssdrs->spielerNummer = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					char snlän = *bytes;
+					län--;
+					bytes++;
+					char *txt = new char[ snlän + 1 ];
+					txt[ snlän ] = 0;
+					for( int j = 0; j < snlän; j++ )
+						txt[ j ] = bytes[ j ];
+					bytes += snlän;
+					län -= snlän;
+					ssdrs->spielerName = txt;
+					delete[] txt;
+					char tnlän = *bytes;
+					län--;
+					bytes++;
+					txt = new char[ tnlän + 1 ];
+					txt[ tnlän ] = 0;
+					for( int j = 0; j < tnlän; j++ )
+						txt[ j ] = bytes[ j ];
+					bytes += tnlän;
+					län -= tnlän;
+					ssdrs->teamName = txt;
+					delete[] txt;
+					ssdrs->spielerFarbe = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					ssdrs->teamFarbe = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					ssdrs->linienLänge = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					ssdrs->kills = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					ssdrs->todesZeit = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					rs->get( i )->spieler.add( ssdrs );
+					break;
+				}
+			}
+		}
+		break;
+	case 7: // Runde Team Statistik
+		if( 1 )
+		{
+			int runde = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			int anz = rs->getEintragAnzahl();
+			for( int i = 0; i < anz; i++ )
+			{
+				if( rs->hat( i ) && rs->get( i )->rundenNummer == runde )
+				{
+					SSDRundeTeam *ssdrt = new SSDRundeTeam();
+					ssdrt->teamNummer = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					char tnlän = *bytes;
+					län--;
+					bytes++;
+					char *txt = new char[ tnlän + 1 ];
+					txt[ tnlän ] = 0;
+					for( int j = 0; j < tnlän; j++ )
+						txt[ j ] = bytes[ j ];
+					bytes += tnlän;
+					län -= tnlän;
+					ssdrt->teamName = txt;
+					delete[] txt;
+					ssdrt->teamFarbe = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					ssdrt->ergebnis = *bytes;
+					bytes++;
+					län--;
+					ssdrt->linienLänge = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					ssdrt->kills = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					ssdrt->tode = *(int*)bytes;
+					bytes += 4;
+					län -= 4;
+					rs->get( i )->teams.add( ssdrt );
+					break;
+				}
+			}
+		}
+		break;
+	case 8: // Chat Nachricht
+		if( 1 )
+		{
+			int vonAccount = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			char *txt = new char[ län + 1 ];
+			txt[ län ] = 0;
+			for( int i = 0; i < län; i++ )
+				txt[ i ] = bytes[ i ];
+			if( status == 1 )
+				chat->addChatNachricht( vonAccount, txt );
+			delete[] txt;
+		}
+		break;
+	case 9: // Spieler hat verlassen
+		if( 1 )
+		{
+			int acc = *(int*)bytes;
+			bytes += 4;
+			län -= 4;
+			if( status == 1 )
+				chat->spielerOffline( acc );
+		}
+		break;
+	default:
+		// Fehler
+		break;
+	}
+	if( län != 0 )
+	{
+		// Fehler
+	}
+	unlock();
+}
+
+void SpielStatistik::doMausEreignis( MausEreignis &me )
+{
+	if( !status )
+		return;
+	lock();
+	if( status == 1 )
+	{
+		tabelle->doMausEreignis( me );
+		runde->doMausEreignis( me );
+		chat->doMausEreignis( me );
+	}
+	unlock();
+}
+
+void SpielStatistik::doTastaturEreignis( TastaturEreignis &te )
+{
+	if( !status )
+		return;
+	lock();
+	if( status == 1 )
+		chat->doTastaturEreignis( te );
+	unlock();
+}
+
+bool SpielStatistik::tick( double zeit )
+{
+	if( !status )
+		return 0;
+	lock();
+	if( status == 1 )
+	{
+		rend |= chat->tick( zeit );
+		rend |= runde->tick( zeit );
+		rend |= tabelle->tick( zeit );
+		if( ( chat->hatVerlassen() || runde->mussVerlassen() ) && status == 1 )
+		{
+			spielc->trenne();
+			status = 2;
+		}
+		runde->setRunde( tabelle->getRunde() );
+	}
+	bool ret = rend;
+	rend = 0;
+	unlock();
+	return ret;
+}
+
+void SpielStatistik::render( Bild &zRObj )
+{
+	if( !status )
+		return;
+	lock();
+	chat->render( zRObj );
+	runde->render( zRObj );
+	tabelle->render( zRObj );
+	unlock();
+}
+
+void SpielStatistik::verlassen()
+{
+	if( spielc )
+	    spielc->trenne();
+	status = 2;
+}
+
+// constant
+int SpielStatistik::getStatus() const // 0 = laden, 1 = läuft, 2 = fortsetzen
+{
+	return status;
+}
+
+// Reference Counting
+SpielStatistikV *SpielStatistik::getThis()
+{
+	ref++;
+	return this;
+}
+
+SpielStatistikV *SpielStatistik::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 66 - 0
Linie/SpielStatistik/SpielStatistik.h

@@ -0,0 +1,66 @@
+#ifndef SpielStatistik_H
+#define SpielStatistik_H
+
+#include <SpielStatistikV.h>
+#include "SpielStatistikDaten.h"
+#include "Chat/StatistikChat.h"
+#include "Runde/StatistikRunde.h"
+#include "Tabelle/StatistikTabelle.h"
+
+class SpielStatistik : public SpielStatistikV
+{
+private:
+	void( *addNachrichtF )( void *, Text *, Text *, Text *, Text *, char, void * );
+	void( *addChatF )( void *, int );
+	void( *addFreundF )( void *, int );
+	void( *accountAnsehenF )( void *, int );
+	bool( *istFreundF )( void *, int );
+	void *nachrichtParam;
+	BilderV *bilder;
+	Schrift *schrift;
+	Bildschirm *screen;
+	InformationKlientV *infoc;
+	SpielKlientV *spielc;
+	CRITICAL_SECTION cs;
+	Array< SSDGesamtSpieler* > *gss;
+	Array< SSDGesamtTeam* > *gts;
+	Array< SSDRunde* > *rs;
+	StatistikChat *chat;
+	StatistikRunde *runde;
+	StatistikTabelle *tabelle;
+	int accountId;
+	bool rend;
+	int status;
+	int ref;
+
+public:
+	// Konstruktor
+	SpielStatistik();
+	// Destruktor
+	~SpielStatistik();
+	// nicht constant
+	void lock();
+	void unlock();
+	virtual void bereit();
+	virtual void setBilder( BilderV *b );
+	virtual void setAccountId( int id );
+	virtual void setRückrufFunktionen( void( *addNachrichtF )( void *, Text *, Text *, Text *, Text *, char, void * ),
+															   void( *addChatF )( void *, int ), void( *addFreundF )( void *, int ),
+															   void( *accountAnsehenF )( void *, int ), bool( *istFreundF )( void *, int ), void *nachrichtParam );
+	virtual void setSchrift( Schrift *schrift );
+	virtual void setBildschirm( Bildschirm *screen );
+	virtual void setKlients( InformationKlientV *infoc, SpielKlientV *spielc );
+	virtual void nachricht( int län, char *bytes );
+	virtual void doMausEreignis( MausEreignis &me );
+	virtual void doTastaturEreignis( TastaturEreignis &te );
+	virtual bool tick( double zeit );
+	virtual void render( Bild &zRObj );
+	virtual void verlassen();
+	// constant
+	virtual int getStatus() const; // 0 = laden, 1 = läuft, 2 = fortsetzen
+	// Reference Counting
+	virtual SpielStatistikV *getThis();
+	virtual SpielStatistikV *release();
+};
+
+#endif

+ 72 - 0
Linie/SpielStatistik/SpielStatistikDaten.h

@@ -0,0 +1,72 @@
+#ifndef SpielStatistikDaten_H
+#define SpielStatistikDaten_H
+
+#include <Text.h>
+#include <Bild.h>
+#include <Array.h>
+
+using namespace Framework;
+
+struct SSDGesamtSpieler
+{
+	int spielerNummer;
+	Text spielerName;
+	Text teamName;
+	int spielerFarbe;
+	int teamFarbe;
+	int gewonneneRunden;
+	int punkte;
+	int linienLänge;
+	int zeitAmLeben;
+	int zeitTod;
+	int kills;
+	int tode;
+};
+
+struct SSDGesamtTeam
+{
+	int teamNummer;
+	Text teamName;
+	int teamFarbe;
+	int gewonneneRunden;
+	int punkte;
+	int linienLänge;
+	int kills;
+	int tode;
+};
+
+struct SSDRundeSpieler
+{
+	int spielerNummer;
+	Text spielerName;
+	Text teamName;
+	int spielerFarbe;
+	int teamFarbe;
+	int linienLänge;
+	int kills;
+	int todesZeit;
+};
+
+struct SSDRundeTeam
+{
+	int teamNummer;
+	Text teamName;
+	int teamFarbe;
+	char ergebnis;
+	int linienLänge;
+	int kills;
+	int tode;
+};
+
+struct SSDRunde
+{
+	int rundenNummer;
+	int rundenDauer;
+	int rundenSieger;
+	int spielfeldNutzung;
+	Bild rundenBild;
+	Array< SSDRundeSpieler* > spieler;
+	Array< SSDRundeTeam* > teams;
+};
+
+#endif

+ 776 - 0
Linie/SpielStatistik/Tabelle/StatistikTabelle.cpp

@@ -0,0 +1,776 @@
+#include "StatistikTabelle.h"
+#include "../../Initialisierung/Initialisierung.h"
+
+#define ABSTYLE     AuswahlBox::Style::Sichtbar | AuswahlBox::Style::Erlaubt | AuswahlBox::Style::Rahmen | AuswahlBox::Style::AuswahlBuffer | AuswahlBox::Style::MausBuffer | AuswahlBox::Style::MaxHeight | AuswahlBox::Style::Hintergrund | AuswahlBox::Style::VScroll
+#define OTSTYLE     ObjTabelle::Style::Sichtbar | ObjTabelle::Style::Erlaubt | ObjTabelle::Style::Rahmen | ObjTabelle::Style::Raster | ObjTabelle::Style::scroll | ObjTabelle::Style::SpaltenBreiteMax | ObjTabelle::Style::SpaltenBreiteMin | ObjTabelle::Style::SpaltenBreiteChangeable | ObjTabelle::Style::SpaltenBeweglich
+
+// Inhalt der StatistikTabelle Klasse aus StatistikTabelle.h
+// Konstruktor
+StatistikTabelle::StatistikTabelle( Array< SSDGesamtSpieler* > *ssdgs, Array< SSDGesamtTeam* > *ssdgt,
+									Array< SSDRunde* > *ssdr, Schrift *zSchrift, Bildschirm *zScreen, bool historie )
+: schrift( zSchrift->getThis() ),
+  ssdgs( ssdgs ),
+  ssdgt( ssdgt ),
+  ssdr( ssdr ),
+  stAuswahl( initAuswahlBox( 10, 10, 120, 20, zSchrift, ABSTYLE, { "Spieler", "Teams" } ) ),
+  grAuswahl( initAuswahlBox( 140, 10, 120, 20, zSchrift, ABSTYLE, { "Gesamt" } ) ),
+  sortAuswahlGS( initAuswahlBox( 270, 10, 120, 20, zSchrift, ABSTYLE, { "Spielername", "Teamname", "Spielerfarbe", "Teamfarbe",
+																		"Gewonnene Runden", "Punkte", "Linienlänge", "Zeit am Leben",
+																		"Zeit tod", "Kills", "Tode" } ) ),
+  sortAuswahlGT( initAuswahlBox( 270, 10, 120, 20, zSchrift, ABSTYLE, { "Teamname", "Teamfarbe", "Gewonnene Runden", "Punkte",
+																		"Linienlänge", "Kills", "Tode" } ) ),
+  sortAuswahlRS( new RCArray< AuswahlBox >() ),
+  sortAuswahlRT( new RCArray< AuswahlBox >() ),
+  sortRichtungGS( initAuswahlBox( 400, 10, 120, 20, zSchrift, ABSTYLE, { "Aufwärts", "Abwärts" } ) ),
+  sortRichtungGT( initAuswahlBox( 400, 10, 120, 20, zSchrift, ABSTYLE, { "Aufwärts", "Abwärts" } ) ),
+  sortRichtungRS( new RCArray< AuswahlBox >() ),
+  sortRichtungRT( new RCArray< AuswahlBox >() ),
+  gesamtSpieler( initObjTabelle( 10, 40, 500, 245, zSchrift, OTSTYLE, { { "Spielername", 120, 20, 200 }, { "Teamname", 120, 20, 120 },
+  { "Spielerfarbe", 100, 20, 100 }, { "Teamfarbe", 100, 20, 100 }, { "Gewonnene Runden", 130, 20, 130 }, { "Punkte", 50, 20, 50 },
+  { "Linienlänge", 120, 20, 120 }, { "Zeit Am Leben", 120, 20, 120 }, { "Zeit tod", 60, 20, 60 }, { "Kills", 40, 20, 40 }, { "Tode", 40, 20, 40 } }, 20 ) ),
+  gesamtTeam( initObjTabelle( 10, 40, 500, 245, zSchrift, OTSTYLE, { { "Teamname", 120, 20, 120 }, { "Teamfarbe", 100, 20, 100 },
+  { "Gewonnene Runden", 130, 20, 130 }, { "Punkte", 50, 20, 50 }, { "Linienlänge", 120, 20, 120 }, { "Kills", 40, 20, 40 }, { "Tode", 40, 20, 40 } }, 20 ) ),
+  rundeSpieler( new RCArray< ObjTabelle >() ),
+  rundeTeam( new RCArray< ObjTabelle >() ),
+  teamS( 0 ),
+  rundeAusw( -1 ),
+  rend( 0 ),
+  ref( 1 )
+{
+	tabelleFüllen( gesamtSpieler );
+	tabelleFüllen( gesamtTeam );
+	int anz = ssdr->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+	{
+		if( !ssdr->hat( i ) )
+			continue;
+		Text rName( "Runde " );
+		rName += ssdr->get( i )->rundenNummer + 1;
+		grAuswahl->addEintrag( rName );
+		AuswahlBox *ab = initAuswahlBox( 270, 10, 120, 20, zSchrift, ABSTYLE, { "Spielername", "Teamname", "Spielerfarbe",
+										 "Teamfarbe", "Linienlänge", "Kills", "Todeszeit" } );
+		initToolTip( ab, "Spalte nach der sortiert werden soll.", schrift->getThis(), zScreen );
+		sortAuswahlRS->add( ab );
+		ab = initAuswahlBox( 270, 10, 120, 20, zSchrift, ABSTYLE, { "Teamname", "Teamfarbe", "Ergebnis",
+							 "Linienlänge", "Kills", "Tode" } );
+		initToolTip( ab, "Spalte nach der sortiert werden soll.", schrift->getThis(), zScreen );
+		sortAuswahlRT->add( ab );
+		ab = initAuswahlBox( 400, 10, 120, 20, zSchrift, ABSTYLE, { "Aufwärts", "Abwärts" } );
+		initToolTip( ab, "Richtung nach der sortiert werden soll.", schrift->getThis(), zScreen );
+		sortRichtungRS->add( ab );
+		ab = initAuswahlBox( 400, 10, 120, 20, zSchrift, ABSTYLE, { "Aufwärts", "Abwärts" } );
+		initToolTip( ab, "Richtung nach der sortiert werden soll.", schrift->getThis(), zScreen );
+		sortRichtungRT->add( ab );
+		rundeSpieler->add( initObjTabelle( 10, 40, 500, 245, zSchrift, OTSTYLE, { { "Spielername", 120, 20, 200 }, { "Teamname", 120, 20, 120 },
+		{ "Spielerfarbe", 100, 20, 100 }, { "Teamfarbe", 100, 20, 100 }, { "Linienlänge", 120, 20, 120 }, { "Kills", 40, 20, 40 }, { "Todeszeit", 80, 20, 80 } }, 20 ) );
+		rundeTeam->add( initObjTabelle( 10, 40, 500, 245, zSchrift, OTSTYLE, { { "Teamname", 120, 20, 120 }, { "Teamfarbe", 100, 20, 100 },
+		{ "Ergebnis", 80, 20, 80 }, { "Linienlänge", 120, 20, 120 }, { "Kills", 40, 20, 40 }, { "Tode", 40, 20, 40 } }, 20 ) );
+		tabelleFüllen( rundeSpieler->z( i ) );
+		tabelleFüllen( rundeTeam->z( i ) );
+	}
+	if( historie )
+	{
+		sortRichtungGS->setSize( 110, 20 );
+		sortRichtungGT->setSize( 110, 20 );
+		gesamtSpieler->setSize( 500, 380 );
+		gesamtTeam->setSize( 500, 380 );
+		for( int i = 0; i < anz; i++ )
+		{
+			rundeSpieler->z( i )->setSize( 500, 380 );
+			rundeTeam->z( i )->setSize( 500, 380 );
+			sortRichtungRS->z( i )->setSize( 110, 20 );
+			sortRichtungRT->z( i )->setSize( 110, 20 );
+		}
+	}
+}
+
+// Destruktor
+StatistikTabelle::~StatistikTabelle()
+{
+	tabelleLehren( gesamtSpieler, 1 );
+	tabelleLehren( gesamtTeam, 1 );
+	int anz = rundeSpieler->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+		tabelleLehren( rundeSpieler->z( i ), 1 );
+	anz = rundeTeam->getEintragAnzahl();
+	for( int i = 0; i < anz; i++ )
+		tabelleLehren( rundeTeam->z( i ), 1 );
+	schrift->release();
+	ssdgs->release();
+	ssdgt->release();
+	ssdr->release();
+	stAuswahl->release();
+	grAuswahl->release();
+	sortAuswahlGS->release();
+	sortAuswahlGT->release();
+	sortAuswahlRS->release();
+	sortAuswahlRT->release();
+	sortRichtungGS->release();
+	sortRichtungGT->release();
+	sortRichtungRS->release();
+	sortRichtungRT->release();
+	gesamtSpieler->release();
+	gesamtTeam->release();
+	rundeSpieler->release();
+	rundeTeam->release();
+}
+
+// privat
+void StatistikTabelle::tabelleLehren( ObjTabelle *zT, bool überschrift )
+{
+	int sAnz = zT->getSpaltenAnzahl();
+	int zAnz = zT->getZeilenAnzahl();
+	for( int i = !überschrift; i < zAnz; i++ )
+	{
+		for( int j = 0; j < sAnz; j++ )
+			( (TextFeld*)zT->zZeichnung( j, !überschrift ) )->release();
+		zT->removeZeile( !überschrift );
+	}
+}
+
+void StatistikTabelle::tabelleFüllen( ObjTabelle *zT )
+{
+	if( zT == gesamtSpieler )
+	{
+		if( !sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() ) )
+			return;
+		if( !sortRichtungGS->zEintragText( sortRichtungGS->getAuswahl() ) )
+			return;
+		Array< int > reihenfolge;
+		bool aufsteigend = sortRichtungGS->zEintragText( sortRichtungGS->getAuswahl() )->istGleich( "Aufwärts" );
+		int anz = ssdgs->getEintragAnzahl();
+		bool *fertig = new bool[ anz ];
+		ZeroMemory( fertig, anz );
+		bool spielername = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Spielername" );
+		bool teamname = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Teamname" );
+		bool spielerfarbe = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Spielerfarbe" );
+		bool teamfarbe = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Teamfarbe" );
+		bool gewonnenerunden = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Gewonnene Runden" );
+		bool punkte = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Punkte" );
+		bool linienlänge = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Linienlänge" );
+		bool zeitamleben = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Zeit am Leben" );
+		bool zeittod = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Zeit tod" );
+		bool kills = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Kills" );
+		bool tode = sortAuswahlGS->zEintragText( sortAuswahlGS->getAuswahl() )->istGleich( "Tode" );
+		for( int i = 0; i < anz; i++ )
+		{
+			Text minMaxT;
+			int minMax;
+			int pos = -1;
+			for( int j = 0; j < anz; j++ )
+			{
+				if( !ssdgs->hat( j ) || fertig[ j ] )
+					continue;
+				if( spielername && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->spielerName < minMaxT ) || ( !aufsteigend && ssdgs->get( j )->spielerName > minMaxT ) ) )
+				{ // Sortiert nach Spieler Name
+					minMaxT = ssdgs->get( j )->spielerName.getText();
+					pos = j;
+				}
+				if( teamname && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->teamName < minMaxT ) || ( !aufsteigend && ssdgs->get( j )->teamName > minMaxT ) ) )
+				{ // Sortiert nach Team Name
+					minMaxT = ssdgs->get( j )->teamName.getText();
+					pos = j;
+				}
+				if( spielerfarbe && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->spielerFarbe < minMax ) || ( !aufsteigend && ssdgs->get( j )->spielerFarbe > minMax ) ) )
+				{ // Sortiert nach Spieler Farbe
+					minMax = ssdgs->get( j )->spielerFarbe;
+					pos = j;
+				}
+				if( teamfarbe && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->teamFarbe < minMax ) || ( !aufsteigend && ssdgs->get( j )->teamFarbe > minMax ) ) )
+				{ // Sortiert nach Team Farbe
+					minMax = ssdgs->get( j )->teamFarbe;
+					pos = j;
+				}
+				if( gewonnenerunden && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->gewonneneRunden < minMax ) || ( !aufsteigend && ssdgs->get( j )->gewonneneRunden > minMax ) ) )
+				{ // Sortiert nach Gewonnenen Runden
+					minMax = ssdgs->get( j )->gewonneneRunden;
+					pos = j;
+				}
+				if( punkte && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->punkte < minMax ) || ( !aufsteigend && ssdgs->get( j )->punkte > minMax ) ) )
+				{ // Sortiert nach Punkten
+					minMax = ssdgs->get( j )->punkte;
+					pos = j;
+				}
+				if( linienlänge && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->linienLänge < minMax ) || ( !aufsteigend && ssdgs->get( j )->linienLänge > minMax ) ) )
+				{ // Sortiert nach Linienlängen
+					minMax = ssdgs->get( j )->linienLänge;
+					pos = j;
+				}
+				if( zeitamleben && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->zeitAmLeben < minMax ) || ( !aufsteigend && ssdgs->get( j )->zeitAmLeben > minMax ) ) )
+				{ // Sortiert nach Zeit Am Leben
+					minMax = ssdgs->get( j )->zeitAmLeben;
+					pos = j;
+				}
+				if( zeittod && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->zeitTod < minMax ) || ( !aufsteigend && ssdgs->get( j )->zeitTod > minMax ) ) )
+				{ // Sortiert nach Zeit Tod
+					minMax = ssdgs->get( j )->zeitTod;
+					pos = j;
+				}
+				if( kills && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->kills < minMax ) || ( !aufsteigend && ssdgs->get( j )->kills > minMax ) ) )
+				{ // Sortiert nach Kills
+					minMax = ssdgs->get( j )->kills;
+					pos = j;
+				}
+				if( tode && ( pos < 0 || ( aufsteigend && ssdgs->get( j )->tode < minMax ) || ( !aufsteigend && ssdgs->get( j )->tode > minMax ) ) )
+				{ // Sortiert nach Toden
+					minMax = ssdgs->get( j )->tode;
+					pos = j;
+				}
+			}
+			if( pos >= 0 )
+			{
+				reihenfolge.add( pos );
+				fertig[ pos ] = 1;
+			}
+			else
+				break;
+		}
+		delete[] fertig;
+		anz = reihenfolge.getEintragAnzahl();
+		for( int j = 0; j < anz; j++ )
+		{
+			int i = reihenfolge.get( j );
+			zT->addZeile( Text( "Spieler " ) += ssdgs->get( i )->spielerNummer );
+			int zNum = zT->getZeilenNummer( Text( "Spieler " ) += ssdgs->get( i )->spielerNummer );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Spielername" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdgs->get( i )->spielerName ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Teamname" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdgs->get( i )->teamName ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Spielerfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
+			( (TextFeld*)zT->zZeichnung( zT->getSpaltenNummer( "Spielerfarbe" ), zNum ) )->setHintergrundFarbe( ssdgs->get( i )->spielerFarbe );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Teamfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
+			( (TextFeld*)zT->zZeichnung( zT->getSpaltenNummer( "Teamfarbe" ), zNum ) )->setHintergrundFarbe( ssdgs->get( i )->teamFarbe );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Gewonnene Runden" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->gewonneneRunden ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Punkte" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->punkte ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Linienlänge" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->linienLänge ) );
+			Text zeitAmLeben;
+			zeitAmLeben += ssdgs->get( i )->zeitAmLeben / 60;
+			zeitAmLeben += ":";
+			zeitAmLeben += ssdgs->get( i )->zeitAmLeben % 60;
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Zeit Am Leben" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, zeitAmLeben ) );
+			Text zeitTod;
+			zeitTod += ssdgs->get( i )->zeitTod / 60;
+			zeitTod += ":";
+			zeitTod += ssdgs->get( i )->zeitTod % 60;
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Zeit tod" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, zeitTod ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Kills" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->kills ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Tode" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgs->get( i )->tode ) );
+		}
+		return;
+	}
+	if( zT == gesamtTeam )
+	{
+		if( !sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() ) )
+			return;
+		if( !sortRichtungGS->zEintragText( sortRichtungGS->getAuswahl() ) )
+			return;
+		Array< int > reihenfolge;
+		bool aufsteigend = sortRichtungGT->zEintragText( sortRichtungGT->getAuswahl() )->istGleich( "Aufwärts" );
+		int anz = ssdgt->getEintragAnzahl();
+		bool *fertig = new bool[ anz ];
+		ZeroMemory( fertig, anz );
+		bool teamname = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Teamname" );
+		bool teamfarbe = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Teamfarbe" );
+		bool gewonnenerunden = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Gewonnene Runden" );
+		bool punkte = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Punkte" );
+		bool linienlänge = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Linienlänge" );
+		bool kills = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Kills" );
+		bool tode = sortAuswahlGT->zEintragText( sortAuswahlGT->getAuswahl() )->istGleich( "Tode" );
+		for( int i = 0; i < anz; i++ )
+		{
+			Text minMaxT;
+			int minMax;
+			int pos = -1;
+			for( int j = 0; j < anz; j++ )
+			{
+				if( !ssdgt->hat( j ) || fertig[ j ] )
+					continue;
+				if( teamname && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->teamName < minMaxT ) || ( !aufsteigend && ssdgt->get( j )->teamName > minMaxT ) ) )
+				{ // Sortiert nach Team Name
+					minMaxT = ssdgt->get( j )->teamName.getText();
+					pos = j;
+				}
+				if( teamfarbe && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->teamFarbe < minMax ) || ( !aufsteigend && ssdgt->get( j )->teamFarbe > minMax ) ) )
+				{ // Sortiert nach Team Farbe
+					minMax = ssdgt->get( j )->teamFarbe;
+					pos = j;
+				}
+				if( gewonnenerunden && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->gewonneneRunden < minMax ) || ( !aufsteigend && ssdgt->get( j )->gewonneneRunden > minMax ) ) )
+				{ // Sortiert nach Gewonnenen Runden
+					minMax = ssdgt->get( j )->gewonneneRunden;
+					pos = j;
+				}
+				if( punkte && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->punkte < minMax ) || ( !aufsteigend && ssdgt->get( j )->punkte > minMax ) ) )
+				{ // Sortiert nach Punkten
+					minMax = ssdgt->get( j )->punkte;
+					pos = j;
+				}
+				if( linienlänge && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->linienLänge < minMax ) || ( !aufsteigend && ssdgt->get( j )->linienLänge > minMax ) ) )
+				{ // Sortiert nach Linienlängen
+					minMax = ssdgt->get( j )->linienLänge;
+					pos = j;
+				}
+				if( kills && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->kills < minMax ) || ( !aufsteigend && ssdgt->get( j )->kills > minMax ) ) )
+				{ // Sortiert nach Kills
+					minMax = ssdgt->get( j )->kills;
+					pos = j;
+				}
+				if( tode && ( pos < 0 || ( aufsteigend && ssdgt->get( j )->tode < minMax ) || ( !aufsteigend && ssdgt->get( j )->tode > minMax ) ) )
+				{ // Sortiert nach Toden
+					minMax = ssdgt->get( j )->tode;
+					pos = j;
+				}
+			}
+			if( pos >= 0 )
+			{
+				reihenfolge.add( pos );
+				fertig[ pos ] = 1;
+			}
+			else
+				break;
+		}
+		delete[] fertig;
+		anz = reihenfolge.getEintragAnzahl();
+		for( int j = 0; j < anz; j++ )
+		{
+			int i = reihenfolge.get( j );
+			zT->addZeile( Text( "Team " ) += ssdgt->get( i )->teamNummer );
+			int zNum = zT->getZeilenNummer( Text( "Team " ) += ssdgt->get( i )->teamNummer );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Teamname" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdgt->get( i )->teamName ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Teamfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
+			( (TextFeld*)zT->zZeichnung( zT->getSpaltenNummer( "Teamfarbe" ), zNum ) )->setHintergrundFarbe( ssdgt->get( i )->teamFarbe );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Gewonnene Runden" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->gewonneneRunden ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Punkte" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->punkte ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Linienlänge" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->linienLänge ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Kills" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->kills ) );
+			zT->setZeichnungZ( zT->getSpaltenNummer( "Tode" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdgt->get( i )->tode ) );
+		}
+		return;
+	}
+	int anz = rundeSpieler->getEintragAnzahl();
+	for( int h = 0; h < anz; h++ )
+	{
+		if( zT == rundeSpieler->z( h ) )
+		{
+			if( !ssdr->hat( h ) )
+				return;
+			Array< SSDRundeSpieler* > *ssdrs = &ssdr->get( h )->spieler;
+			AuswahlBox *sortAuswahl = sortAuswahlRS->z( h );
+			AuswahlBox *sortRichtung = sortRichtungRS->z( h );
+			if( !sortAuswahl || !sortAuswahl->zEintragText( sortAuswahl->getAuswahl() ) )
+				return;
+			if( !sortRichtung || !sortRichtung->zEintragText( sortRichtung->getAuswahl() ) )
+				return;
+			Array< int > reihenfolge;
+			bool aufsteigend = sortRichtung->zEintragText( sortRichtung->getAuswahl() )->istGleich( "Aufwärts" );
+			int anz = ssdrs->getEintragAnzahl();
+			bool *fertig = new bool[ anz ];
+			ZeroMemory( fertig, anz );
+			bool spielername = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Spielername" );
+			bool teamname = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Teamname" );
+			bool spielerfarbe = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Spielerfarbe" );
+			bool teamfarbe = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Teamfarbe" );
+			bool linienlänge = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Linienlänge" );
+			bool kills = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Kills" );
+			bool todeszeit = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Todeszeit" );
+			for( int i = 0; i < anz; i++ )
+			{
+				Text minMaxT;
+				int minMax;
+				int pos = -1;
+				for( int j = 0; j < anz; j++ )
+				{
+					if( !ssdrs->hat( j ) || fertig[ j ] )
+						continue;
+					if( spielername && ( pos < 0 || ( aufsteigend && ssdrs->get( j )->spielerName < minMaxT ) || ( !aufsteigend && ssdrs->get( j )->spielerName > minMaxT ) ) )
+					{ // Sortiert nach Spieler Name
+						minMaxT = ssdrs->get( j )->spielerName.getText();
+						pos = j;
+					}
+					if( teamname && ( pos < 0 || ( aufsteigend && ssdrs->get( j )->teamName < minMaxT ) || ( !aufsteigend && ssdrs->get( j )->teamName > minMaxT ) ) )
+					{ // Sortiert nach Team Name
+						minMaxT = ssdrs->get( j )->teamName.getText();
+						pos = j;
+					}
+					if( spielerfarbe && ( pos < 0 || ( aufsteigend && ssdrs->get( j )->spielerFarbe < minMax ) || ( !aufsteigend && ssdrs->get( j )->spielerFarbe > minMax ) ) )
+					{ // Sortiert nach Spieler Farbe
+						minMax = ssdrs->get( j )->spielerFarbe;
+						pos = j;
+					}
+					if( teamfarbe && ( pos < 0 || ( aufsteigend && ssdrs->get( j )->teamFarbe < minMax ) || ( !aufsteigend && ssdrs->get( j )->teamFarbe > minMax ) ) )
+					{ // Sortiert nach Team Farbe
+						minMax = ssdrs->get( j )->teamFarbe;
+						pos = j;
+					}
+					if( linienlänge && ( pos < 0 || ( aufsteigend && ssdrs->get( j )->linienLänge < minMax ) || ( !aufsteigend && ssdrs->get( j )->linienLänge > minMax ) ) )
+					{ // Sortiert nach Linienlängen
+						minMax = ssdrs->get( j )->linienLänge;
+						pos = j;
+					}
+					if( kills && ( pos < 0 || ( aufsteigend && ssdrs->get( j )->kills < minMax ) || ( !aufsteigend && ssdrs->get( j )->kills > minMax ) ) )
+					{ // Sortiert nach Kills
+						minMax = ssdrs->get( j )->kills;
+						pos = j;
+					}
+					if( todeszeit && ( pos < 0 || ( aufsteigend && ssdrs->get( j )->todesZeit < minMax ) || ( !aufsteigend && ssdrs->get( j )->todesZeit > minMax ) ) )
+					{ // Sortiert nach Todeszeitpunkten
+						minMax = ssdrs->get( j )->todesZeit;
+						pos = j;
+					}
+				}
+				if( pos >= 0 )
+				{
+					reihenfolge.add( pos );
+					fertig[ pos ] = 1;
+				}
+				else
+					break;
+			}
+			delete[] fertig;
+			anz = reihenfolge.getEintragAnzahl();
+			for( int j = 0; j < anz; j++ )
+			{
+				int i = reihenfolge.get( j );
+				zT->addZeile( Text( "Spieler " ) += ssdrs->get( i )->spielerNummer );
+				int zNum = zT->getZeilenNummer( Text( "Spieler " ) += ssdrs->get( i )->spielerNummer );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Spielername" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdrs->get( i )->spielerName ) );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Teamname" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdrs->get( i )->teamName ) );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Spielerfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
+				( (TextFeld*)zT->zZeichnung( zT->getSpaltenNummer( "Spielerfarbe" ), zNum ) )->setHintergrundFarbe( ssdrs->get( i )->spielerFarbe );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Teamfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
+				( (TextFeld*)zT->zZeichnung( zT->getSpaltenNummer( "Teamfarbe" ), zNum ) )->setHintergrundFarbe( ssdrs->get( i )->teamFarbe );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Linienlänge" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdrs->get( i )->linienLänge ) );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Kills" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdrs->get( i )->kills ) );
+				Text todesZeit;
+				todesZeit += ssdrs->get( i )->todesZeit / 60;
+				todesZeit += ":";
+				todesZeit += ssdrs->get( i )->todesZeit % 60;
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Todeszeit" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, todesZeit ) );
+			}
+			return;
+		}
+	}
+	anz = rundeTeam->getEintragAnzahl();
+	for( int h = 0; h < anz; h++ )
+	{
+		if( zT == rundeTeam->z( h ) )
+		{
+			if( !ssdr->hat( h ) )
+				return;
+			Array< SSDRundeTeam* > *ssdrt = &ssdr->get( h )->teams;
+			AuswahlBox *sortAuswahl = sortAuswahlRT->z( h );
+			AuswahlBox *sortRichtung = sortRichtungRT->z( h );
+			if( !sortAuswahl || !sortAuswahl->zEintragText( sortAuswahl->getAuswahl() ) )
+				return;
+			if( !sortRichtung || !sortRichtung->zEintragText( sortRichtung->getAuswahl() ) )
+				return;
+			Array< int > reihenfolge;
+			bool aufsteigend = sortRichtung->zEintragText( sortRichtung->getAuswahl() )->istGleich( "Aufwärts" );
+			int anz = ssdrt->getEintragAnzahl();
+			bool *fertig = new bool[ anz ];
+			ZeroMemory( fertig, anz );
+			bool teamname = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Teamname" );
+			bool teamfarbe = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Teamfarbe" );
+			bool ergebnis = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Ergebnis" );
+			bool linienlänge = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Linienlänge" );
+			bool kills = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Kills" );
+			bool tode = sortAuswahl->zEintragText( sortAuswahl->getAuswahl() )->istGleich( "Tode" );
+			for( int i = 0; i < anz; i++ )
+			{
+				Text minMaxT;
+				int minMax;
+				int pos = -1;
+				for( int j = 0; j < anz; j++ )
+				{
+					if( !ssdrt->hat( j ) || fertig[ j ] )
+						continue;
+					if( teamname && ( pos < 0 || ( aufsteigend && ssdrt->get( j )->teamName < minMaxT ) || ( !aufsteigend && ssdrt->get( j )->teamName > minMaxT ) ) )
+					{ // Sortiert nach Team Name
+						minMaxT = ssdrt->get( j )->teamName.getText();
+						pos = j;
+					}
+					if( teamfarbe && ( pos < 0 || ( aufsteigend && ssdrt->get( j )->teamFarbe < minMax ) || ( !aufsteigend && ssdrt->get( j )->teamFarbe > minMax ) ) )
+					{ // Sortiert nach Team Farbe
+						minMax = ssdrt->get( j )->teamFarbe;
+						pos = j;
+					}
+					if( ergebnis && ( pos < 0 || ( aufsteigend && ssdrt->get( j )->ergebnis < minMax ) || ( !aufsteigend && ssdrt->get( j )->ergebnis > minMax ) ) )
+					{ // Sortiert nach Ergebnis
+						minMax = ssdrt->get( j )->ergebnis;
+						pos = j;
+					}
+					if( linienlänge && ( pos < 0 || ( aufsteigend && ssdrt->get( j )->linienLänge < minMax ) || ( !aufsteigend && ssdrt->get( j )->linienLänge > minMax ) ) )
+					{ // Sortiert nach Linienlängen
+						minMax = ssdrt->get( j )->linienLänge;
+						pos = j;
+					}
+					if( kills && ( pos < 0 || ( aufsteigend && ssdrt->get( j )->kills < minMax ) || ( !aufsteigend && ssdrt->get( j )->kills > minMax ) ) )
+					{ // Sortiert nach Kills
+						minMax = ssdrt->get( j )->kills;
+						pos = j;
+					}
+					if( tode && ( pos < 0 || ( aufsteigend && ssdrt->get( j )->tode < minMax ) || ( !aufsteigend && ssdrt->get( j )->tode > minMax ) ) )
+					{ // Sortiert nach Todeszeitpunkten
+						minMax = ssdrt->get( j )->tode;
+						pos = j;
+					}
+				}
+				if( pos >= 0 )
+				{
+					reihenfolge.add( pos );
+					fertig[ pos ] = 1;
+				}
+				else
+					break;
+			}
+			delete[] fertig;
+			anz = reihenfolge.getEintragAnzahl();
+			for( int j = 0; j < anz; j++ )
+			{
+				int i = reihenfolge.get( j );
+				zT->addZeile( Text( "Team " ) += ssdrt->get( i )->teamNummer );
+				int zNum = zT->getZeilenNummer( Text( "Team " ) += ssdrt->get( i )->teamNummer );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Teamname" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ssdrt->get( i )->teamName ) );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Teamfarbe" ), zNum, initTextFeld( 0, 0, 0, 0, 0, TextFeld::Style::Sichtbar | TextFeld::Style::Hintergrund, 0 ) );
+				( (TextFeld*)zT->zZeichnung( zT->getSpaltenNummer( "Teamfarbe" ), zNum ) )->setHintergrundFarbe( ssdrt->get( i )->teamFarbe );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Ergebnis" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, ergebnis ? Text( "Gewonnen" ) : Text( "Verloren" ) ) );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Linienlänge" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdrt->get( i )->linienLänge ) );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Kills" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdrt->get( i )->kills ) );
+				zT->setZeichnungZ( zT->getSpaltenNummer( "Tode" ), zNum, initTextFeld( 0, 0, 0, 0, schrift, TextFeld::Style::Text, Text() += ssdrt->get( i )->tode ) );
+			}
+			return;
+		}
+	}
+}
+
+// nicht constant
+void StatistikTabelle::doMausEreignis( MausEreignis &me )
+{
+	// Auswahl Boxen
+	int ausw = stAuswahl->getAuswahl();
+	stAuswahl->doMausEreignis( me );
+	if( ausw != stAuswahl->getAuswahl() )
+	{
+		teamS = stAuswahl->zEintragText( stAuswahl->getAuswahl() )->istGleich( "Teams" );
+		stAuswahl->einklappen();
+	}
+	ausw = grAuswahl->getAuswahl();
+	grAuswahl->doMausEreignis( me );
+	if( ausw != grAuswahl->getAuswahl() )
+	{
+		if( grAuswahl->zEintragText( grAuswahl->getAuswahl() )->istGleich( "Gesamt" ) )
+			rundeAusw = -1;
+		Text *nummer = grAuswahl->zEintragText( grAuswahl->getAuswahl() )->getTeilText( 6 );
+		rundeAusw = (int)( *nummer ) - 1;
+		nummer->release();
+		grAuswahl->einklappen();
+	}
+	if( rundeAusw == -1 )
+	{ // Statistik vom gesamtem Spiel
+		if( teamS )
+		{ // Team Statistik
+			int ausw = sortAuswahlGT->getAuswahl();
+			sortAuswahlGT->doMausEreignis( me );
+			if( ausw != sortAuswahlGT->getAuswahl() )
+			{ // Sortierungs Spalte ändert sich
+				tabelleLehren( gesamtTeam, 0 );
+				tabelleFüllen( gesamtTeam );
+				sortAuswahlGT->einklappen();
+			}
+			ausw = sortRichtungGT->getAuswahl();
+			sortRichtungGT->doMausEreignis( me );
+			if( ausw != sortRichtungGT->getAuswahl() )
+			{ // Sortierungs Richtung ändert sich
+				tabelleLehren( gesamtTeam, 0 );
+				tabelleFüllen( gesamtTeam );
+				sortRichtungGT->einklappen();
+			}
+			gesamtTeam->doMausEreignis( me );
+		}
+		else
+		{ // Spieler Statistik
+			int ausw = sortAuswahlGS->getAuswahl();
+			sortAuswahlGS->doMausEreignis( me );
+			if( ausw != sortAuswahlGS->getAuswahl() )
+			{ // Sortierungs Spalte ändert sich
+				tabelleLehren( gesamtSpieler, 0 );
+				tabelleFüllen( gesamtSpieler );
+				sortAuswahlGS->einklappen();
+			}
+			ausw = sortRichtungGS->getAuswahl();
+			sortRichtungGS->doMausEreignis( me );
+			if( ausw != sortRichtungGS->getAuswahl() )
+			{ // Sortierungs Richtung ändert sich
+				tabelleLehren( gesamtSpieler, 0 );
+				tabelleFüllen( gesamtSpieler );
+				sortRichtungGS->einklappen();
+			}
+			gesamtSpieler->doMausEreignis( me );
+		}
+	}
+	else
+	{ // Statistik von einer Runde
+		if( teamS )
+		{ // Team Statistik
+			if( sortAuswahlRT->z( rundeAusw ) )
+			{
+				int ausw = sortAuswahlRT->z( rundeAusw )->getAuswahl();
+				sortAuswahlRT->z( rundeAusw )->doMausEreignis( me );
+				if( ausw != sortAuswahlRT->z( rundeAusw )->getAuswahl() && rundeTeam->z( rundeAusw ) )
+				{ // Sortierungs Spalte ändert sich
+					tabelleLehren( rundeTeam->z( rundeAusw ), 0 );
+					tabelleFüllen( rundeTeam->z( rundeAusw ) );
+					sortAuswahlRT->z( rundeAusw )->einklappen();
+				}
+			}
+			if( sortRichtungRT->z( rundeAusw ) )
+			{
+				int ausw = sortRichtungRT->z( rundeAusw )->getAuswahl();
+				sortRichtungRT->z( rundeAusw )->doMausEreignis( me );
+				if( ausw != sortRichtungRT->z( rundeAusw )->getAuswahl() && rundeTeam->z( rundeAusw ) )
+				{ // Sortierungs Richtung ändert sich
+					tabelleLehren( rundeTeam->z( rundeAusw ), 0 );
+					tabelleFüllen( rundeTeam->z( rundeAusw ) );
+					sortRichtungRT->z( rundeAusw )->einklappen();
+				}
+			}
+			if( rundeTeam->z( rundeAusw ) )
+				rundeTeam->z( rundeAusw )->doMausEreignis( me );
+		}
+		else
+		{ // Spieler Statistik
+			if( sortAuswahlRS->z( rundeAusw ) )
+			{
+				int ausw = sortAuswahlRS->z( rundeAusw )->getAuswahl();
+				sortAuswahlRS->z( rundeAusw )->doMausEreignis( me );
+				if( ausw != sortAuswahlRS->z( rundeAusw )->getAuswahl() && rundeSpieler->z( rundeAusw ) )
+				{ // Sortierungs Spalte ändert sich
+					tabelleLehren( rundeSpieler->z( rundeAusw ), 0 );
+					tabelleFüllen( rundeSpieler->z( rundeAusw ) );
+					sortAuswahlRS->z( rundeAusw )->einklappen();
+				}
+			}
+			if( sortRichtungRS->z( rundeAusw ) )
+			{
+				int ausw = sortRichtungRS->z( rundeAusw )->getAuswahl();
+				sortRichtungRS->z( rundeAusw )->doMausEreignis( me );
+				if( ausw != sortRichtungRS->z( rundeAusw )->getAuswahl() && rundeSpieler->z( rundeAusw ) )
+				{ // Sortierungs Richtung ändert sich
+					tabelleLehren( rundeSpieler->z( rundeAusw ), 0 );
+					tabelleFüllen( rundeSpieler->z( rundeAusw ) );
+					sortRichtungRS->z( rundeAusw )->einklappen();
+				}
+			}
+			if( rundeSpieler->z( rundeAusw ) )
+				rundeSpieler->z( rundeAusw )->doMausEreignis( me );
+		}
+	}
+}
+
+bool StatistikTabelle::tick( double tickVal )
+{
+	if( rundeAusw == -1 )
+	{ // Statistik vom gesamtem Spiel
+		if( teamS )
+		{ // Team Statistik
+			rend |= gesamtTeam->tick( tickVal );
+			rend |= sortAuswahlGT->tick( tickVal );
+			rend |= sortRichtungGT->tick( tickVal );
+		}
+		else
+		{ // Spieler Statistik
+			rend |= gesamtSpieler->tick( tickVal );
+			rend |= sortAuswahlGS->tick( tickVal );
+			rend |= sortRichtungGS->tick( tickVal );
+		}
+	}
+	else
+	{ // Statistik von einer Runde
+		if( teamS )
+		{ // Team Statistik
+			if( rundeTeam->z( rundeAusw ) )
+				rend |= rundeTeam->z( rundeAusw )->tick( tickVal );
+			if( sortAuswahlRT->z( rundeAusw ) )
+				rend |= sortAuswahlRT->z( rundeAusw )->tick( tickVal );
+			if( sortRichtungRT->z( rundeAusw ) )
+				rend |= sortRichtungRT->z( rundeAusw )->tick( tickVal );
+		}
+		else
+		{ // Spieler Statistik
+			if( rundeSpieler->z( rundeAusw ) )
+				rend |= rundeSpieler->z( rundeAusw )->tick( tickVal );
+			if( sortAuswahlRS->z( rundeAusw ) )
+				rend |= sortAuswahlRS->z( rundeAusw )->tick( tickVal );
+			if( sortRichtungRS->z( rundeAusw ) )
+				rend |= sortRichtungRS->z( rundeAusw )->tick( tickVal );
+		}
+	}
+	// Auswahl Boxen
+	rend |= stAuswahl->tick( tickVal );
+	rend |= grAuswahl->tick( tickVal );
+	bool ret = rend;
+	rend = 0;
+	return ret;
+}
+
+void StatistikTabelle::render( Bild &zRObj )
+{
+	if( rundeAusw == -1 )
+	{ // Statistik vom gesamtem Spiel
+		if( teamS )
+		{ // Team Statistik
+			gesamtTeam->render( zRObj );
+			sortAuswahlGT->render( zRObj );
+			sortRichtungGT->render( zRObj );
+		}
+		else
+		{ // Spieler Statistik
+			gesamtSpieler->render( zRObj );
+			sortAuswahlGS->render( zRObj );
+			sortRichtungGS->render( zRObj );
+		}
+	}
+	else
+	{ // Statistik von einer Runde
+		if( teamS )
+		{ // Team Statistik
+			if( rundeTeam->z( rundeAusw ) )
+				rundeTeam->z( rundeAusw )->render( zRObj );
+			if( sortAuswahlRT->z( rundeAusw ) )
+				sortAuswahlRT->z( rundeAusw )->render( zRObj );
+			if( sortRichtungRT->z( rundeAusw ) )
+				sortRichtungRT->z( rundeAusw )->render( zRObj );
+		}
+		else
+		{ // Spieler Statistik
+			if( rundeSpieler->z( rundeAusw ) )
+				rundeSpieler->z( rundeAusw )->render( zRObj );
+			if( sortAuswahlRS->z( rundeAusw ) )
+				sortAuswahlRS->z( rundeAusw )->render( zRObj );
+			if( sortRichtungRS->z( rundeAusw ) )
+				sortRichtungRS->z( rundeAusw )->render( zRObj );
+		}
+	}
+	// Auswahl Boxen
+	stAuswahl->render( zRObj );
+	grAuswahl->render( zRObj );
+}
+
+// constant
+int StatistikTabelle::getRunde() const
+{
+	return rundeAusw;
+}
+
+// Reference Counting
+StatistikTabelle *StatistikTabelle::getThis()
+{
+	ref++;
+	return this;
+}
+
+StatistikTabelle *StatistikTabelle::release()
+{
+	ref--;
+	if( !ref )
+		delete this;
+	return 0;
+}

+ 55 - 0
Linie/SpielStatistik/Tabelle/StatistikTabelle.h

@@ -0,0 +1,55 @@
+#ifndef StatistikTabelle_H
+#define StatistikTabelle_H
+
+#include <Tabelle.h>
+#include <AuswahlBox.h>
+#include "../SpielStatistikDaten.h"
+
+using namespace Framework;
+
+class StatistikTabelle
+{
+private:
+	Schrift *schrift;
+	Array< SSDGesamtSpieler* > *ssdgs;
+	Array< SSDGesamtTeam* > *ssdgt;
+	Array< SSDRunde* > *ssdr;
+	AuswahlBox *stAuswahl;
+	AuswahlBox *grAuswahl;
+	AuswahlBox *sortAuswahlGS;
+	AuswahlBox *sortAuswahlGT;
+	RCArray< AuswahlBox > *sortAuswahlRS;
+	RCArray< AuswahlBox > *sortAuswahlRT;
+	AuswahlBox *sortRichtungGS;
+	AuswahlBox *sortRichtungGT;
+	RCArray< AuswahlBox > *sortRichtungRS;
+	RCArray< AuswahlBox > *sortRichtungRT;
+	ObjTabelle *gesamtSpieler;
+	ObjTabelle *gesamtTeam;
+	RCArray< ObjTabelle > *rundeSpieler;
+	RCArray< ObjTabelle > *rundeTeam;
+	bool teamS;
+	int rundeAusw;
+	bool rend;
+	int ref;
+	// privat
+	void tabelleLehren( ObjTabelle *zT, bool überschrift );
+	void tabelleFüllen( ObjTabelle *zT );
+
+public:
+	// Konstruktor
+	StatistikTabelle( Array< SSDGesamtSpieler* > *ssdgs, Array< SSDGesamtTeam* > *ssdgt, Array< SSDRunde* > *ssdr, Schrift *zSchrift, Bildschirm *zScreen, bool historie = 0 );
+	// Destruktor
+	~StatistikTabelle();
+	// nicht constant
+	void doMausEreignis( MausEreignis &me );
+	bool tick( double tickVal );
+	void render( Bild &zRObj );
+	// constant
+	int getRunde() const;
+	// Reference Counting
+	StatistikTabelle *getThis();
+	StatistikTabelle *release();
+};
+
+#endif

+ 27 - 0
Linie/Start/DllStart.cpp

@@ -0,0 +1,27 @@
+#include "..\Spiel\SpielKlasse.h"
+#include "..\SpielStatistik\SpielStatistik.h"
+#include "..\HistorieStatistik\HistorieStatistik.h"
+#include "..\Aufzeichnung\Aufzeichnung.h"
+
+extern "C"
+{ // Dll Einstiegs Funktionen
+	__declspec( dllexport ) SpielV *getSpielKlasse()
+	{
+		return new SpielKlasse();
+	}
+
+	__declspec( dllexport ) SpielStatistikV *GetStatistikKlasse()
+	{
+		return new SpielStatistik();
+	}
+
+	__declspec( dllexport ) AccountHistorieStatistikV *GetAccountHistorieStatistik()
+	{
+		return new HistorieStatistik();
+	}
+
+	__declspec( dllexport ) AufzeichnungV *GetAufzeichnung()
+	{
+		return new Aufzeichnung();
+	}
+}

+ 3 - 0
build.bat

@@ -0,0 +1,3 @@
+"D:\Visual Studio 2017\MSBuild\15.0\Bin\MSBuild.exe" "Linie.sln" /p:configuration=release /p:platform=win32
+"D:\Visual Studio 2017\MSBuild\15.0\Bin\MSBuild.exe" "Linie.sln" /p:configuration=release /p:platform=x64
+"D:\Visual Studio 2017\MSBuild\15.0\Bin\MSBuild.exe" "Linie.sln" /p:configuration=debug /p:platform=x64