#include "Reader.h"
#include "Spiel.h"

struct SpielerTeamStruktur
{
    int spielerAnzahl;
    int teamAnzahl;
    Array< int > spielerFarbe;
    Array< int > teamFarbe;
    RCArray< Text > teamName;
    Array< int > teamSize;
};


// Konstruktor
MapReader::MapReader( int karteId, char *tmpPfad )
{
    this->karteId = karteId;
    pfad = new Text( tmpPfad );
    ref = 1;
}

// Destruktor
MapReader::~MapReader()
{
    if( pfad )
        pfad->release();
}

Array<int> *MapReader::getSpielerFarben()
{
    Text *pf = new Text( pfad->getText() );
    pf->append( "data.sts" );
    Datei *datei = new Datei();
    datei->setDatei( pf );
    if( !datei->existiert() || datei->istOrdner() )
    {
        datei->release();
        return 0;
    }
    int spielerAnzahl;
    int teamAnzahl;
    datei->open( Datei::Style::lesen );
    datei->lese( (char *)& spielerAnzahl, 4 );
    datei->lese( (char *)& teamAnzahl, 4 );
    Array< int > *result = new Array< int >();
    for( int i = 0; i < spielerAnzahl; i++ )
    {
        int f = 0;
        datei->lese( (char *)& f, 4 );
        result->add( f );
    }
    datei->close();
    datei->release();
    return result;
}

Array<int> *MapReader::getTeamFarben()
{
    Text *pf = new Text( pfad->getText() );
    pf->append( "data.sts" );
    Datei *datei = new Datei();
    datei->setDatei( pf );
    if( !datei->existiert() || datei->istOrdner() )
    {
        datei->release();
        return 0;
    }
    int spielerAnzahl;
    int teamAnzahl;
    datei->open( Datei::Style::lesen );
    datei->lese( (char *)& spielerAnzahl, 4 );
    datei->lese( (char *)& teamAnzahl, 4 );
    for( int i = 0; i < spielerAnzahl; i++ )
    {
        int f = 0;
        datei->lese( (char *)& f, 4 );
    }
    Array< int > *result = new Array< int >();
    for( int i = 0; i < teamAnzahl; i++ )
    {
        int f = 0;
        datei->lese( (char *)& f, 4 );
        result->add( f );
    }
    datei->close();
    datei->release();
    return result;
}

Aktion *MapReader::readAktion( Datei &dat )
{
    int id;
    dat.lese( (char *)& id, 4 );
    char pAnz = 0;
    dat.lese( &pAnz, 1 );
    RCArray< Aktion > *params = new RCArray< Aktion >();
    for( int i = 0; i < pAnz; i++ )
        params->add( readAktion( dat ) );
    switch( id )
    {
    case BARIERE_BEWEGUNG:
        return new BariereBewegung( params );
    case BARIERE_SET_EINGESCHALTET:
        return new BariereSetEingeschaltet( params );
    case GAME_OBJEKT_SET_POSITION:
        return new GameObjektSetPosition( params );
    case GAME_OBJEKT_SET_SIZE:
        return new GameObjektSetSize( params );
    case BARIERE_SET_TEAM:
        return new BariereSetTeam( params );
    case BARIERE_ZUFALL:
        params->release();
        return new BariereZufall();
    case BARIERE_ZULETZT_AUSGESCHALTET:
        params->release();
        return new BariereZuletztAusgeschaltet();
    case BARIERE_ZULETZT_BEWEGT:
        params->release();
        return new BariereZuletztBewegt();
    case BARIERE_ZULETZT_EINGESCHALTET:
        params->release();
        return new BariereZuletztEingeschaltet();
    case BASE_SET_TEAM:
        return new BaseSetTeam( params );
    case BASE_START_TEAM_CHANGE:
        return new BaseStartTeamChange( params );
    case BASE_ZUFALL:
        params->release();
        return new BaseZufall();
    case BASE_ZULETZT_BESITZER_GEWECHSELT:
        params->release();
        return new BaseZuletztBesitzerGewechselt();
    case BOOLEAN_AUS_TEXT:
        return new BooleanAusText( params );
    case BOOLEAN_BARIERE_BEWEGT_SICH:
        return new BooleanBariereBewegtSich( params );
    case BOOLEAN_BARIERE_IST_AKTIV:
        return new BooleanBariereIstAktiv( params );
    case BOOLEAN_BARIERE_IST_SCHALTEND:
        return new BooleanBariereIstSchaltend( params );
    case BOOLEAN_BASE_IST_NEUTRAL:
        return new BooleanBaseIstNeutral( params );
    case BOOLEAN_RECHNUNG:
    {
        char op;
        dat.lese( &op, 1 );
        return new BooleanRechnung( params, (Operator)op );
    }
    case BOOLEAN_SCHALTER_IST_AKTIV:
        return new BooleanSchalterIstAktiv( params );
    case BOOLEAN_SPIELER_AM_LEBEN:
        return new BooleanSpielerAmLeben( params );
    case BOOLEAN_SPIELER_HAT_GEGENSTAND:
        return new BooleanSpielerHatGegenstand( params );
    case BOOLEAN_SPIELER_IST_VERWUNDBAR:
        return new BooleanSpielerIstVerwundbar( params );
    case BOOLEAN_SPIELER_KANN_ITEM_BENUTZEN:
        return new BooleanSpielerKannItemBenutzen( params );
    case BOOLEAN_SPIEL_PAUSIERT:
        params->release();
        return new BooleanSpielPausiert();
    case BOOLEAN_TIMER_IS_RUNNING:
        return new BooleanTimerIsRunning( params );
    case BOOLEAN_TIMER_IST_SICHTBAR:
        return new BooleanTimerIstSichtbar( params );
    case BOOLEAN_TRIGGER_IST_AKTIV:
        return new BooleanTriggerIstAktiv( params );
    case BOOLEAN_TUNNEL_IST_AKTIV:
        return new BooleanTunnelIstAktiv( params );
    case BOOLEAN_UMLENKUNG_HAT_ABK:
        return new BooleanUmlenkungHatAbk( params );
    case BOOLEAN_UMLENKUNG_IST_DREHEND:
        return new BooleanUmlenkungIstDrehend( params );
    case BOOLEAN_ZUFALL:
        params->release();
        return new BooleanZufall();
    case DISPLAY_TEXT:
        return new DisplayText( params );
    case DROP_DO_DROP:
        return new DropDoDrop( params );
    case DROP_SET_AREA:
        return new DropSetArea( params );
    case DROP_SET_MAX_TIME:
        return new DropSetMaxTime( params );
    case DROP_SET_TIME:
        return new DropSetTime( params );
    case DROP_ZUFALL:
        params->release();
        return new DropZufall();
    case DROP_ZULETZT_GEDROPT:
        params->release();
        return new DropZuletztGedropt();
    case GESCHOSS_NEU:
        return new GeschossNeu( params );
    case GESCHOSS_SET_PLAYER:
        return new GeschossSetPlayer( params );
    case GESCHOSS_SET_RICHTUNG:
        return new GeschossSetRichtung( params );
    case GESCHOSS_SET_SPEED:
        return new GeschossSetSpeed( params );
    case GESCHOSS_SET_TYPE:
        return new GeschossSetType( params );
    case GESCHOSS_ZUFALL:
        params->release();
        return new GeschossZufall();
    case GESCHOSS_ZULETZT_ABGEFEUERT:
        params->release();
        return new GeschossZuletztAbgefeuert();
    case GESCHOSS_ZULETZT_BARIERE_GETROFFEN:
        params->release();
        return new GeschossZuletztBarjereGetroffen();
    case GESCHOSS_ZULETZT_GESCHOSS_GETROFFEN:
        params->release();
        return new GeschossZuletztGeschossGetroffen();
    case GESCHOSS_ZULETZT_TUNNEL_BENUTZT:
        params->release();
        return new GeschossZuletztTunnelBenutzt();
    case GESCHOSS_ZULETZT_UMGELENKT:
        params->release();
        return new GeschossZuletztUmgelenkt();
    case INTEGER_AUS_TEXT:
        return new IntegerAusText( params );
    case FLOAT_GAME_OBJEKT_BREITE:
        return new FloatGameObjektBreite( params );
    case FLOAT_GAME_OBJEKT_HEIGHT:
        return new FloatGameObjektHeight( params );
    case INTEGER_BARIERE_SCHALTUNGEN:
        return new IntegerBariereSchaltungen( params );
    case INTEGER_BARIERE_VERSCHIEBUNGEN:
        return new IntegerBariereVerschiebungen( params );
    case INTEGER_DROP_MAX_ZEIT:
        return new IntegerDropMaxZeit( params );
    case FLOAT_DROP_ZEIT:
        return new FloatDropZeit( params );
    case INTEGER_MAX_X_VON_DROP:
        return new IntegerMaxXVonDrop( params );
    case INTEGER_MAX_Y_VON_DROP:
        return new IntegerMaxYVonDrop( params );
    case INTEGER_MIN_X_VON_DROP:
        return new IntegerMinXVonDrop( params );
    case INTEGER_MIN_Y_VON_DROP:
        return new IntegerMinYVonDrop( params );
    case INTEGER_RECHNEN:
    {
        char op;
        dat.lese( &op, 1 );
        return new IntegerRechnen( params, (Operator)op );
    }
    case INTEGER_SCHALTER_AKTIVIERUNGEN:
        return new IntegerSchalterAktivierungen( params );
    case FLOAT_SPIELER_ABKLINGZEITVERRINGERUNG:
        return new FloatSpielerAbklingzeitVerringerung( params );
    case FLOAT_SPIELER_ARMOR:
        return new FloatSpielerArmor( params );
    case FLOAT_SPIELER_ERFAHRUNG:
        return new FloatSpielerErfahrung( params );
    case FLOAT_SPIELER_ERLITTENER_SCHADEN:
        return new FloatSpielerErlittenerSchaden( params );
    case FLOAT_SPIELER_GEHEILTES_LEBEN:
        return new FloatSpielerGeheiltesLeben( params );
    case INTEGER_SPIELER_GESCHOSSEN:
        return new IntegerSpielerGeschossen( params );
    case FLOAT_SPIELER_GESCHOSS_TEMPO:
        return new FloatSpielerGeschossTempo( params );
    case INTEGER_SPIELER_GETROFFEN:
        return new IntegerSpielerGetroffen( params );
    case INTEGER_SPIELER_ITEMS_AUFGEHOBEN:
        return new IntegerSpielerItemsAufgehoben( params );
    case INTEGER_SPIELER_ANZAHL_ITEMS_IN_INVENTAR:
        return new IntegerSpielerItemsInInventar( params );
    case INTEGER_SPIELER_ANZAHL_ITEMS_VON_TYP:
        return new IntegerSpielerItemsTypeInInventar( params );
    case INTEGER_SPIELER_ITEMS_VERWENDET:
        return new IntegerSpielerItemsVerwendet( params );
    case INTEGER_SPIELER_KILLS:
        return new IntegerSpielerKills( params );
    case FLOAT_SPIELER_LEBEN:
        return new FloatSpielerLeben( params );
    case FLOAT_SPIELER_LEBENSRAUB:
        return new FloatSpielerLebensraub( params );
    case FLOAT_SPIELER_LEBENSREGENERATION:
        return new FloatSpielerLebensregeneration( params );
    case INTEGER_SPIELER_LEVEL:
        return new IntegerSpielerLevel( params );
    case INTEGER_SPIELER_MAX_ERFAHRUNG:
        return new IntegerSpielerMaxErfahrung( params );
    case INTEGER_SPIELER_MAX_LEBEN:
        return new IntegerSpielerMaxLeben( params );
    case FLOAT_SPIELER_SCHADEN:
        return new FloatSpielerSchaden( params );
    case FLOAT_SPIELER_SCHADEN_BONUS:
        return new FloatSpielerSchadenBonus( params );
    case INTEGER_SPIELER_SCHALTER_AKTIVIERT:
        return new IntegerSpielerSchalterAktiviert( params );
    case FLOAT_SPIELER_TEMPO:
        return new FloatSpielerTempo( params );
    case INTEGER_SPIELER_TODE:
        return new IntegerSpielerTode( params );
    case INTEGER_SPIELER_TREFFER:
        return new IntegerSpielerTreffer( params );
    case INTEGER_SPIELER_TUNNEL_BENUTZT:
        return new IntegerSpielerTunnelBenutzt( params );
    case INTEGER_TEAM_KILLS:
        return new IntegerTeamKills( params );
    case INTEGER_TEAM_PUNKTE:
        return new IntegerTeamPunkte( params );
    case INTEGER_TEAM_SPIELERANZAHL:
        return new IntegerTeamSpieleranzahl( params );
    case INTEGER_TEAM_TODE:
        return new IntegerTeamTode( params );
    case FLOAT_TEAM_WIEDERBELEBUNGSZEIT:
        return new FloatTeamWiederbelegungszeit( params );
    case FLOAT_TIMER_AKTUELLE_ZEIT:
        return new FloatTimerAktuelleZeit( params );
    case INTEGER_TIMER_MAX_ZEIT:
        return new IntegerTimerMaxZeit( params );
    case INTEGER_TRIGGER_RUNNS:
        return new IntegerTriggerRunns( params );
    case INTEGER_TUNNEL_BENUTZUNGEN:
        return new IntegerTunnelBenutzungen( params );
    case INTEGER_UMLENKUNG_BENUTZUNGEN:
        return new IntegerUmlenkungBenutzungen( params );
    case FLOAT_X_VON_GAME_OBJEKT:
        return new FloatXVonGameObjekt( params );
    case FLOAT_Y_VON_GAME_OBJEKT:
        return new FloatYVonGameObjekt( params );
    case INTEGER_X_VON_TUNNEL_ZIEL:
        return new IntegerXVonTunnelZiel( params );
    case INTEGER_Y_VON_TUNNEL_ZIEL:
        return new IntegerYVonTunnelZiel( params );
    case INTEGER_ZUFALL:
        return new IntegerZufall( params );
    case ITEM_SPIELER_INVENTAR:
        return new ItemSpielerInventar( params );
    case ITEM_ZULETZT_AUFGEHOBEN:
        params->release();
        return new ItemZuletztAufgehoben();
    case ITEM_ZULETZT_AKTIVIERT:
        params->release();
        return new ItemZuletztAktiviert();
    case ITEM_ZULETZT_GEDROPT:
        params->release();
        return new ItemZuletztGedropt();
    case ITEM_ZUFALL:
        params->release();
        return new ItemZufall();
    case KONSTANT_BOOLEAN:
    {
        params->release();
        bool b;
        dat.lese( (char *)& b, 1 );
        return new KonstantBoolean( b );
    }
    case KONSTANT_FLOAT:
    {
        params->release();
        float f;
        dat.lese( (char *)& f, 4 );
        return new KonstantFloat( f );
    }
    case KONSTANT_INTEGER:
    {
        params->release();
        int i;
        dat.lese( (char *)& i, 4 );
        return new KonstantInteger( i );
    }
    case KONSTANT_NICHTS:
        params->release();
        return new KonstantNichts();
    case KONSTANT_STRING:
    {
        params->release();
        char len;
        dat.lese( &len, 1 );
        char *txt = new char[ len + 1 ];
        dat.lese( txt, len );
        txt[ (int)len ] = 0;
        Aktion *ret = new KonstantString( txt );
        delete[] txt;
        return ret;
    }
    case KONSTANT_VARIABLE:
    {
        params->release();
        char len;
        dat.lese( &len, 1 );
        char *txt = new char[ len + 1 ];
        dat.lese( txt, len );
        txt[ (int)len ] = 0;
        Aktion *ret = new KonstantVariable( txt );
        delete[] txt;
        return ret;
    }
    case RICHTUNG_VON_GESCHOSS:
        return new RichtungVonGeschoss( params );
    case RICHTUNG_VON_UMLENKUNG:
        return new RichtungVonUmlenkung( params );
    case RICHTUNG_ZUFALL:
        params->release();
        return new RichtungZufall();
    case SCHALTER_AKTIVIEREN:
        return new SchalterAktivieren( params );
    case SCHALTER_SET_ERLAUBT:
        return new SchalterSetErlaubt( params );
    case SCHALTER_ZUFALL:
        params->release();
        return new SchalterZufall();
    case SCHALTER_ZULETZT_AKTIVIERT:
        params->release();
        return new SchalterZuletztAktiviert();
    case SET_VARIABLE:
    {
        char len;
        dat.lese( &len, 1 );
        char *txt = new char[ len + 1 ];
        dat.lese( txt, len );
        txt[ (int)len ] = 0;
        Aktion *ret = new SetVariable( txt, params );
        delete[] txt;
        return ret;
    }
    case SPIEL_ENDE:
        return new SpielEnde( params );
    case SPIELER_GIVE_ITEM:
        return new SpielerGiveItem( params );
    case SPIELER_NACHRICHT:
        return new SpielerNachricht( params );
    case SPIELER_REMOVE_ITEM:
        return new SpielerRemoveItem( params );
    case SPIELER_SET_ABKLINGZEITVERRINGERUNG:
        return new SpielerSetAbklingzeitverringerung( params );
    case SPIELER_SET_ARMOR:
        return new SpielerSetArmor( params );
    case SPIELER_SET_ERFAHRUNG:
        return new SpielerSetErfahrung( params );
    case SPIELER_SET_LEBEN:
        return new SpielerSetLeben( params );
    case SPIELER_SET_LEBENSRAUB:
        return new SpielerSetLebensraub( params );
    case SPIELER_SET_LEBENSREGENERATION:
        return new SpielerSetLebensraub( params );
    case SPIELER_SET_LEVEL:
        return new SpielerSetLevel( params );
    case SPIELER_SET_MAX_ERFAHRUNG:
        return new SpielerSetMaxErfahrung( params );
    case SPIELER_SET_SCHADEN_BONUS:
        return new SpielerSetSchadenBonus( params );
    case SPIELER_SET_TEMPO:
        return new SpielerSetTempo( params );
    case SPIELER_SET_GESCHOSS_TEMPO:
        return new SpielerSetWaffenTempo( params );
    case SPIELER_ZUFALL:
        params->release();
        return new SpielerZufall();
    case SPIELER_ZUFALL_AUS_TEAM:
        return new SpielerZufallAusTeam( params );
    case SPIELER_ZULETZT_ERFAHRUNG_BEKOMMEN:
        return new SpielerZuletztErfahrungBekommen();
    case SPIELER_ZULETZT_GEGENSTAND_AKTIVIERT:
        params->release();
        return new SpielerZuletztGegenstandAktiviert();
    case SPIELER_ZULETZT_GEGENSTAND_AUFGEHOBEN:
        params->release();
        return new SpielerZuletztGegenstandAufgehoben();
    case SPIELER_ZULETZT_GEHEILT:
        params->release();
        return new SpielerZuletztGeheilt();
    case SPIELER_ZULETZT_GESCHOSSEN:
        params->release();
        return new SpielerZuletztGeschossGeschossen();
    case SPIELER_ZULETZT_GESTORBEN:
        params->release();
        return new SpielerZuletztGestorben();
    case SPIELER_ZULETZT_LEVEL_UP:
        params->release();
        return new SpielerZuletztLevelUp();
    case SPIELER_ZULETZT_SCHADEN_GEMACHT:
        params->release();
        return new SpielerZuletztSchadenGemacht();
    case SPIELER_ZULETZT_SCHADEN_GENOMMEN:
        params->release();
        return new SpielerZuletztSchadenGenommen();
    case SPIELER_ZULETZT_SCHALTER_AKTIVIERT:
        params->release();
        return new SpielerZuletztSchalterAktiviert();
    case SPIELER_ZULETZT_TUNNEL_BENUTZT:
        params->release();
        return new SpielerZuletztTunnelBenutzt();
    case SPIELER_ZULETZT_WIEDERBELEBT:
        params->release();
        return new SpielerZuletztWiederbelebent();
    case SPIEL_PAUSE:
        return new SpielPause( params );
    case TEAM_SET_PUNKTE:
        return new TeamSetPunkte( params );
    case TEAM_VON_BARIERE:
        return new TeamVonBariere( params );
    case TEAM_VON_SPIELER:
        return new TeamVonSpieler( params );
    case TEAM_ZUFALL:
        params->release();
        return new TeamZufall();
    case TEXT_AUS_BOOLEAN:
        return new TextAusBoolean( params );
    case TEXT_AUS_RICHTUNG:
        return new TextAusRichtung( params );
    case TEXT_AUS_INTEGER:
        return new TextAusInteger( params );
    case TEXT_CONCAT:
        return new TextConcat( params );
    case TEXT_ITEM_NAME:
        return new TextItemName( params );
    case TEXT_SPIELER_NAME:
        return new TextSpielerName( params );
    case TEXT_TEIL_VON_TEXT:
        return new TextTeilVonText( params );
    case TEXT_TRIGGER_NAME:
        return new TextTriggerName( params );
    case TIMER_SET_PAUSE:
        return new TimerSetPause( params );
    case TIMER_SET_SICHTBAR:
        return new TimerSetSichtbar( params );
    case TIMER_SET_ZEIT:
        return new TimerSetZeit( params );
    case TIMER_START:
        return new TimerStart( params );
    case TIMER_ZUFALL:
        params->release();
        return new TimerZufall();
    case TIMER_ZULETZT_ABGELAUFEN:
        params->release();
        return new TimerZuletztAbgelaufen();
    case TIMER_ZULETZT_FOTOGRAFIERT:
        params->release();
        return new TimerZuletztFortgesetzt();
    case TIMER_ZULETZT_GESTARTET:
        params->release();
        return new TimerZuletztGestartet();
    case TIMER_ZULETZT_PAUSIERT:
        params->release();
        return new TimerZuletztPausiert();
    case TRIGGER_AKTION:
        return new TriggerAktion( params );
    case TRIGGER_LAST_RUNNED:
        params->release();
        return new TriggerLastRunned();
    case TRIGGER_RUN_START:
        return new TriggerRunStart( params );
    case TRIGGER_SET_ENABLED:
        return new TriggerSetEnabled( params );
    case TRIGGER_ZUFALL:
        params->release();
        return new TriggerZufall();
    case TUNNEL_SET_ERLAUBT:
        return new TunnelSetErlaubt( params );
    case TUNNEL_SET_ZIEL_POSITION:
        return new TunnelSetZielPosition( params );
    case TUNNEL_ZUFALL:
        params->release();
        return new TunnelZufall();
    case TUNNEL_ZULETZT_BENUTZT:
        params->release();
        return new TunnelZuletztBenutzt();
    case UMLENKUNG_SET_ERLAUBT:
        return new UmlenkungSetEnabled( params );
    case UMLENKUNG_SET_MAX_ABK:
        return new UmlenkungSetMaxAbk( params );
    case UMLENKUNG_SET_RICHTUNG:
        return new UmlenkungSetRichtung( params );
    case UMLENKUNG_ZUFALL:
        params->release();
        return new UmlenkungZufall();
    case UMLENKUNG_ZULETZT_BENUTZT:
        params->release();
        return new UmlenkungZuletztBenutzt();
    case WARTEN:
        return new Warten( params );
    case WENN_DANN_SONST:
        return new WennDannSonst( params );
    case SEQUENZ:
        return new Sequenz( params );
    case FLOAT_RECHNUNG:
    {
        char op;
        dat.lese( &op, 1 );
        return new FloatRechnung( params, (Operator)op );
    }
    case FLOAT_AUS_INTEGER:
        return new FloatAusInteger( params );
    case FLOAT_AUS_TEXT:
        return new FloatAusText( params );
    case TEXT_AUS_FLOAT:
        return new TextAusFloat( params );
    case FLOAT_ZUFALL:
        return new FloatZufall( params );
    case INTEGER_AUS_FLOAT:
        return new IntegerAusFloat( params );
    }
    params->release();
    return new KonstantNichts();
}

// nicht constant
void MapReader::ladeKarte( Spiel *zSpiel )
{
    if( !pfad )
        return;
    SpielerTeamStruktur sts;
    Text *pf = new Text( pfad->getText() );
    pf->append( "data.sts" );
    Datei *datei = new Datei();
    datei->setDatei( pf );
    if( !datei->existiert() || datei->istOrdner() )
    {
        datei->release();
        return;
    }
    datei->open( Datei::Style::lesen );
    datei->lese( (char *)& sts.spielerAnzahl, 4 );
    datei->lese( (char *)& sts.teamAnzahl, 4 );
    for( int i = 0; i < sts.spielerAnzahl; i++ )
    {
        int farbe = 0;
        datei->lese( (char *)& farbe, 4 );
        sts.spielerFarbe.set( farbe, i );
    }
    for( int i = 0; i < sts.teamAnzahl; i++ )
    {
        int farbe = 0;
        datei->lese( (char *)& farbe, 4 );
        sts.teamFarbe.set( farbe, i );
    }
    for( int i = 0; i < sts.teamAnzahl; i++ )
    {
        char len = 0;
        datei->lese( &len, 1 );
        char *txt = new char[ len + 1 ];
        txt[ (int)len ] = 0;
        datei->lese( txt, len );
        Text *name = new Text( txt );
        delete[] txt;
        sts.teamName.set( name, i );
    }
    for( int i = 0; i < sts.teamAnzahl; i++ )
    {
        int size = 0;
        datei->lese( (char *)& size, 4 );
        sts.teamSize.set( size, i );
    }
    datei->close();
    datei->release();
    pf = new Text( pfad->getText() );
    pf->append( "data.map" );
    Datei mapFile;
    mapFile.setDatei( pf );
    if( !mapFile.existiert() || mapFile.istOrdner() )
        return;
    mapFile.open( Datei::Style::lesen );
    // map Size
    int width;
    int height;
    mapFile.lese( (char *)& width, 4 );
    mapFile.lese( (char *)& height, 4 );
    zSpiel->setMapSize( width, height );
    // teams
    for( int i = 0; i < sts.teamAnzahl; i++ )
    {
        int maxWbZeit;
        int punkte;
        mapFile.lese( (char *)& maxWbZeit, 4 );
        mapFile.lese( (char *)& punkte, 4 );
        zSpiel->addTeam( new Team( i, sts.teamSize.get( i ), punkte, maxWbZeit, sts.teamFarbe.get( i ), sts.teamName.z( i )->getText() ) );
    }
    // spieler
    int team = 0;
    int maxT = sts.teamSize.get( team );
    for( int i = 0; i < sts.spielerAnzahl; i++ )
    {
        int spawnX;
        int spawnY;
        mapFile.lese( (char *)& spawnX, 4 );
        mapFile.lese( (char *)& spawnY, 4 );
        if( i >= maxT )
        {
            team++;
            if( sts.teamSize.hat( team ) )
                maxT += sts.teamSize.get( team );
        }
        zSpiel->addSpieler( new Spieler( zSpiel->zResources(), i, zSpiel->getTeam( team ), spawnX, spawnY, sts.spielerFarbe.get( i ) ) );
    }
    // Barieren
    int anz = 0;
    mapFile.lese( (char *)& anz, 4 );
    for( int i = 0; i < anz; i++ )
    {
        int x;
        int y;
        int breite;
        int height;
        int style;
        int verschiebungWeite;
        int autoSchaltungMaxTime;
        int team;
        mapFile.lese( (char *)& x, 4 );
        mapFile.lese( (char *)& y, 4 );
        mapFile.lese( (char *)& breite, 4 );
        mapFile.lese( (char *)& height, 4 );
        mapFile.lese( (char *)& style, 4 );
        mapFile.lese( (char *)& verschiebungWeite, 4 );
        mapFile.lese( (char *)& autoSchaltungMaxTime, 4 );
        mapFile.lese( (char *)& team, 4 );
        zSpiel->addBariere( new Bariere( zSpiel->zResources(), zSpiel->getNextId(), x, y, breite, height, style, verschiebungWeite, autoSchaltungMaxTime, zSpiel->getTeam( team ) ) );
    }
    // Basen
    mapFile.lese( (char *)& anz, 4 );
    for( int i = 0; i < anz; i++ )
    {
        int x;
        int y;
        int breite;
        int height;
        int maxTime;
        int team;
        mapFile.lese( (char *)& x, 4 );
        mapFile.lese( (char *)& y, 4 );
        mapFile.lese( (char *)& breite, 4 );
        mapFile.lese( (char *)& height, 4 );
        mapFile.lese( (char *)& maxTime, 4 );
        mapFile.lese( (char *)& team, 4 );
        zSpiel->addBase( new Base( zSpiel->zResources(), zSpiel->getNextId(), x, y, breite, height, maxTime, zSpiel->getTeam( team ) ) );
    }
    // Drops
    mapFile.lese( (char *)& anz, 4 );
    for( int i = 0; i < anz; i++ )
    {
        int minX;
        int minY;
        int maxX;
        int maxY;
        int maxTime;
        int numDrops;
        float wahrscheinlichkeit[ ITEMANZAHL ];
        mapFile.lese( (char *)& minX, 4 );
        mapFile.lese( (char *)& minY, 4 );
        mapFile.lese( (char *)& maxX, 4 );
        mapFile.lese( (char *)& maxY, 4 );
        mapFile.lese( (char *)& maxTime, 4 );
        mapFile.lese( (char *)& numDrops, 4 );
        for( int j = KEIN_GEGENSTAND; j < ITEMANZAHL; j++ )
            mapFile.lese( (char *)& wahrscheinlichkeit[ j ], 4 );
        char len;
        mapFile.lese( (char *)& len, 1 );
        char *name = new char[ (int)len + 1 ];
        mapFile.lese( name, len );
        name[ (int)len ] = 0;
        zSpiel->addDrop( new Drop( zSpiel->getNextId(), minX, maxX, minY, maxY, maxTime, numDrops, name, wahrscheinlichkeit ) );
        delete[] name;
    }
    // Schalter
    mapFile.lese( (char *)& anz, 4 );
    for( int i = 0; i < anz; i++ )
    {
        int x;
        int y;
        int breite;
        int height;
        bool aktive;
        mapFile.lese( (char *)& x, 4 );
        mapFile.lese( (char *)& y, 4 );
        mapFile.lese( (char *)& breite, 4 );
        mapFile.lese( (char *)& height, 4 );
        mapFile.lese( (char *)& aktive, 1 );
        zSpiel->addSchalter( new Schalter( zSpiel->zResources(), zSpiel->getNextId(), x, y, breite, height, aktive ) );
    }
    // Schiene
    mapFile.lese( (char *)& anz, 4 );
    for( int i = 0; i < anz; i++ )
    {
        int x;
        int y;
        int breite;
        int height;
        mapFile.lese( (char *)& x, 4 );
        mapFile.lese( (char *)& y, 4 );
        mapFile.lese( (char *)& breite, 4 );
        mapFile.lese( (char *)& height, 4 );
        zSpiel->addSchiene( new Schiene( zSpiel->zResources(), zSpiel->getNextId(), x, y, breite, height ) );
    }
    // Timer
    mapFile.lese( (char *)& anz, 4 );
    for( int i = 0; i < anz; i++ )
    {
        int x;
        int y;
        int maxZeit;
        bool sichtbar;
        bool autoWiederhohlung;
        bool runns;
        int farbe;
        mapFile.lese( (char *)& x, 4 );
        mapFile.lese( (char *)& y, 4 );
        mapFile.lese( (char *)& maxZeit, 4 );
        mapFile.lese( (char *)& sichtbar, 1 );
        mapFile.lese( (char *)& autoWiederhohlung, 1 );
        mapFile.lese( (char *)& runns, 1 );
        mapFile.lese( (char *)& farbe, 4 );
        char len;
        mapFile.lese( (char *)& len, 1 );
        char *name = new char[ (int)len + 1 ];
        mapFile.lese( name, len );
        name[ (int)len ] = 0;
        zSpiel->addTimer( new Timer( zSpiel->getNextId(), name, maxZeit, x, y, sichtbar, autoWiederhohlung, runns, farbe ) );
        delete[] name;
    }
    // Tunnel
    mapFile.lese( (char *)& anz, 4 );
    for( int i = 0; i < anz; i++ )
    {
        int x;
        int y;
        int breite;
        int height;
        int zielX;
        int zielY;
        bool aktiv;
        mapFile.lese( (char *)& x, 4 );
        mapFile.lese( (char *)& y, 4 );
        mapFile.lese( (char *)& breite, 4 );
        mapFile.lese( (char *)& height, 4 );
        mapFile.lese( (char *)& zielX, 4 );
        mapFile.lese( (char *)& zielY, 4 );
        mapFile.lese( (char *)& aktiv, 1 );
        zSpiel->addTunnel( new Tunnel( zSpiel->zResources(), zSpiel->getNextId(), x, y, breite, height, zielX, zielY, aktiv ) );
    }
    // Umlenkungen
    mapFile.lese( (char *)& anz, 4 );
    for( int i = 0; i < anz; i++ )
    {
        int x;
        int y;
        int breite;
        int height;
        char richtung;
        int maxAbklingzeit;
        bool drehend;
        bool aktiv;
        mapFile.lese( (char *)& x, 4 );
        mapFile.lese( (char *)& y, 4 );
        mapFile.lese( (char *)& breite, 4 );
        mapFile.lese( (char *)& height, 4 );
        mapFile.lese( (char *)& richtung, 1 );
        mapFile.lese( (char *)& maxAbklingzeit, 4 );
        mapFile.lese( (char *)& drehend, 1 );
        mapFile.lese( (char *)& aktiv, 1 );
        zSpiel->addUmlenkung( new Umlenkung( zSpiel->zResources(), zSpiel->getNextId(), x, y, breite, height, (Richtung)richtung, maxAbklingzeit, drehend, aktiv ) );
    }
    // Trigger
    mapFile.lese( (char *)& anz, 4 );
    for( int i = 0; i < anz; i++ )
    {
        char len;
        mapFile.lese( (char *)& len, 1 );
        char *name = new char[ (int)len + 1 ];
        mapFile.lese( name, len );
        name[ (int)len ] = 0;
        int ereignisAnzahl;
        int bedingungAnzahl;
        int aktionAnzahl;
        mapFile.lese( (char *)& ereignisAnzahl, 4 );
        mapFile.lese( (char *)& bedingungAnzahl, 4 );
        mapFile.lese( (char *)& aktionAnzahl, 4 );
        EreignisTyp *ereignisse = new EreignisTyp[ ereignisAnzahl ];
        for( int j = 0; j < ereignisAnzahl; j++ )
            mapFile.lese( (char *)& ereignisse[ j ], 4 );
        RCArray< Bedingung > *bedingungen = new RCArray< Bedingung >();
        for( int j = 0; j < bedingungAnzahl; j++ )
            bedingungen->add( new Bedingung( readAktion( mapFile ) ) );
        RCArray< Aktion > *aktionen = new RCArray< Aktion >();
        for( int j = 0; j < aktionAnzahl; j++ )
            aktionen->add( readAktion( mapFile ) );
        zSpiel->addTrigger( new Trigger( zSpiel->getNextId(), name, ereignisAnzahl, ereignisse, bedingungen, aktionen ) );
        delete[] name;
    }
    // Variablen
    mapFile.lese( (char *)& anz, 4 );
    for( int i = 0; i < anz; i++ )
    {
        char len;
        mapFile.lese( (char *)& len, 1 );
        char *name = new char[ (int)len + 1 ];
        mapFile.lese( name, len );
        name[ (int)len ] = 0;
        char typ;
        mapFile.lese( &typ, 1 );
        Variable *var = 0;
        switch( typ )
        {
        case NICHTS:
            var = new Variable( NICHTS );
            break;
        case INTEGER:
        {
            int val;
            mapFile.lese( (char *)& val, 4 );
            var = new Integer( val );
            break;
        }
        case BOOLEAN:
        {
            bool val;
            mapFile.lese( (char *)& val, 1 );
            var = new Boolean( val );
            break;
        }
        case STRING:
        {
            char len;
            mapFile.lese( (char *)& len, 1 );
            char *value = new char[ (int)len + 1 ];
            mapFile.lese( value, len );
            value[ (int)len ] = 0;
            var = new String( value );
            delete[] value;
            break;
        }
        case RICHTUNG:
        {
            char len;
            mapFile.lese( (char *)& len, 1 );
            char *value = new char[ (int)len + 1 ];
            mapFile.lese( value, len );
            value[ (int)len ] = 0;
            var = new String( getRichtungFromString( Text( value ) ) );
            delete[] value;
            break;
        }
        case FLOAT:
        {
            float val;
            mapFile.lese( (char *)& val, 4 );
            var = new Float( val );
            break;
        }
        case TASTE:
        {
            char val;
            mapFile.lese( &val, 1 );
            var = new Integer( val, 1 );
            break;
        }
        case SPIELER:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = zSpiel->getSpieler( id );
            break;
        }
        case TIMER:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = zSpiel->getTimer( id );
            break;
        }
        case TEAM:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = zSpiel->getTeam( id );
            break;
        }
        case BARIERE:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = zSpiel->getBariere( id );
            break;
        }
        case SCHALTER:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = zSpiel->getSchalter( id );
            break;
        }
        case BASE:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = zSpiel->getBase( id );
            break;
        }
        case GEGENSTAND:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = new GegenstandTypVar( (GegenstandTyp)id );
            break;
        }
        case SCHIENE:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = zSpiel->getSchiene( id );
            break;
        }
        case TUNNEL:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = zSpiel->getTunnel( id );
            break;
        }
        case UMLENKUNG:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = zSpiel->getUmlenkung( id );
            break;
        }
        case TRIGGER:
        {
            int id;
            mapFile.lese( (char *)& id, 4 );
            var = zSpiel->getTrigger( id );
            break;
        }
        }
        zSpiel->addVariable( name, var );
        delete[] name;
    }
    mapFile.close();
}

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

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