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

#define TICK 0.03333333

// Konstruktor
Spiel::Spiel()
{
    stkn = new RCArray< STKNachricht >();
    schrift = 0;
    infoKlient = 0;
    spielKlient = 0;
    zScreen = 0;
    chat = new SpielChat();
    end = 0;
    spielerGUI = 0;
    deads = new RCArray< DeadPlayer >();
    nextId = 0;
    rendern = 0;
    rZeit = 0;
    gameTicks = 0;
    spielerAnzahl = 0;
    karteId = 0;
    ladenProzent = 0;
    spielerNummer = 0;
    zWinner = 0;
    pause = 1;
    tasten = new char[ 256 ];
    for( int i = 0; i < 256; i++ )
        tasten[ i ] = 0;
    lastRunnedTrigger = 0;
    zuletztEingeschalteteBariere = 0;
    zuletztAusgeschalteteBariere = 0;
    zuletztBewegteBariere = 0;
    lastTeamChangedBase = 0;
    lastDropedDrop = 0;
    zuletztAufgehobenerGegenstand = KEIN_GEGENSTAND;
    zuletztBenutzterGegenstand = KEIN_GEGENSTAND;
    zuletztGedropterGegenstand = KEIN_GEGENSTAND;
    zuletztAbgefeuertesGeschoss = 0;
    zuletztUmgelenktesGeschoss = 0;
    zuletztBariereGetroffenesGeschoss = 0;
    zuletztTunnelBenutztesGeschoss = 0;
    zuletztGeschossGetroffenesGeschoss = 0;
    zuletztAktivierterSchalter = 0;
    zuletztSchadenGemachterSpieler = 0;
    zuletztSchadenGenommenerSpieler = 0;
    zuletztGeheilterSpieler = 0;
    zuletztLevelUpSpieler = 0;
    zuletztErfahrungBekommenerSpieler = 0;
    zuletztGegenstandAktivierterSpieler = 0;
    zuletztGegenstandAufgehobenerSpieler = 0;
    zuletztSchalterAktivierterSpieler = 0;
    zuletztTunnelBenutzterSpieler = 0;
    zuletztGestorbenerSpieler = 0;
    zuletztWiederbelebterSpieler = 0;
    zuletztGeschossenerSpieler = 0;
    zuletztAbgelaufenerTimer = 0;
    zuletztGestarteterTimer = 0;
    zuletztPausierterTimer = 0;
    zuletztFortgesetzterTimer = 0;
    zuletztBenutzterTunnel = 0;
    zuletztBenutzteUmlenkung = 0;
    resources = 0;
    ref = 1;
}

// Destruktor
Spiel::~Spiel()
{
    stkn->release();
    if( schrift )
        schrift->release();
    if( infoKlient )
        infoKlient->release();
    if( spielKlient )
        spielKlient->release();
    chat->relese();
    if( end )
        end->release();
    if( spielerGUI )
        spielerGUI->release();
    deads->release();
    if( lastRunnedTrigger )
        lastRunnedTrigger->release();
    if( zuletztEingeschalteteBariere )
        zuletztEingeschalteteBariere->release();
    if( zuletztAusgeschalteteBariere )
        zuletztAusgeschalteteBariere->release();
    if( zuletztBewegteBariere )
        zuletztBewegteBariere->release();
    if( lastTeamChangedBase )
        lastTeamChangedBase->release();
    if( lastDropedDrop )
        lastDropedDrop->release();
    if( zuletztAbgefeuertesGeschoss )
        zuletztAbgefeuertesGeschoss->release();
    if( zuletztUmgelenktesGeschoss )
        zuletztUmgelenktesGeschoss->release();
    if( zuletztBariereGetroffenesGeschoss )
        zuletztBariereGetroffenesGeschoss->release();
    if( zuletztTunnelBenutztesGeschoss )
        zuletztTunnelBenutztesGeschoss->release();
    if( zuletztGeschossGetroffenesGeschoss )
        zuletztGeschossGetroffenesGeschoss->release();
    if( zuletztAktivierterSchalter )
        zuletztAktivierterSchalter->release();
    if( zuletztSchadenGemachterSpieler )
        zuletztSchadenGemachterSpieler->release();
    if( zuletztSchadenGenommenerSpieler )
        zuletztSchadenGenommenerSpieler->release();
    if( zuletztGeheilterSpieler )
        zuletztGeheilterSpieler->release();
    if( zuletztLevelUpSpieler )
        zuletztLevelUpSpieler->release();
    if( zuletztErfahrungBekommenerSpieler )
        zuletztErfahrungBekommenerSpieler->release();
    if( zuletztGegenstandAktivierterSpieler )
        zuletztGegenstandAktivierterSpieler->release();
    if( zuletztGegenstandAufgehobenerSpieler )
        zuletztGegenstandAufgehobenerSpieler->release();
    if( zuletztSchalterAktivierterSpieler )
        zuletztSchalterAktivierterSpieler->release();
    if( zuletztTunnelBenutzterSpieler )
        zuletztTunnelBenutzterSpieler->release();
    if( zuletztGestorbenerSpieler )
        zuletztGestorbenerSpieler->release();
    if( zuletztWiederbelebterSpieler )
        zuletztWiederbelebterSpieler->release();
    if( zuletztGeschossenerSpieler )
        zuletztGeschossenerSpieler->release();
    if( zuletztAbgelaufenerTimer )
        zuletztAbgelaufenerTimer->release();
    if( zuletztGestarteterTimer )
        zuletztGestarteterTimer->release();
    if( zuletztPausierterTimer )
        zuletztPausierterTimer->release();
    if( zuletztFortgesetzterTimer )
        zuletztFortgesetzterTimer->release();
    if( zuletztBenutzterTunnel )
        zuletztBenutzterTunnel->release();
    if( zuletztBenutzteUmlenkung )
        zuletztBenutzteUmlenkung->release();
    if( resources )
        resources->release();
    delete[] tasten;
}

bool Spiel::istAmLeben() const
{
    for( int i = 0; i < spielerAnzahl; i++ )
    {
        if( spieler.z( i )->getId() == spielerNummer )
            return spieler.z( i )->istAmLeben();
    }
    return 0;
}

void Spiel::tick()
{
    rZeit -= TICK;// spieler bewegungen
    for( auto s = spieler.getIterator(); s; s++ )
    {
        s->move( TICK );
        if( s->getX() < 0 || s->getY() < 0 || s->getX() + s->getWidth() >= mapSize.x || s->getY() + s->getHeight() >= mapSize.y )
            s->move( -TICK );
        else
        {
            for( auto b = barieren.getIterator(); b; b++ )
            { // spieler - bariere intersection
                if( b->hatStyle( Bariere::Style::Aktiv ) && ( b->zTeam() != s->zTeam() ) && b->intersectsWith( s ) )
                    s->move( -TICK );
            }
        }
    }
    for( auto s = spieler.getIterator(); s; s++ )
        s->tick( TICK, this );
    // barieren bewegung
    for( auto b = barieren.getIterator(); b; b++ )
        b->tick( TICK, this );
    // geschoss bewegung
    for( int i = 0; i < shots.getEintragAnzahl(); i++ )
    {
        Geschoss *g = shots.z( i );
        g->tick( TICK );
        bool removed = 0;
        // geschoss - bariere intersection
        bool intersectsWithBariere = 0;
        for( auto b = barieren.getIterator(); b; b++ )
        {
            if( b->hatStyle( Bariere::Style::Aktiv ) && b->intersectsWith( g ) )
            {
                intersectsWithBariere = 1;
                break;
            }
        }
        if( intersectsWithBariere || g->getX() < 0 || g->getY() < 0 || g->getX() + g->getWidth() >= mapSize.x || g->getY() + g->getHeight() >= mapSize.y )
        {
            if( zuletztBariereGetroffenesGeschoss )
                zuletztBariereGetroffenesGeschoss->release();
            zuletztBariereGetroffenesGeschoss = (Geschoss *)g->getThis();
            g->tick( -TICK );
            switch( g->getTyp() )
            {
            case GESCHOSS_PFEIL:
                shots.remove( i );
                i--;
                removed = 1;
                break;
            case GESCHOSS_KUGEL:
            case GESCHOSS_DRACHENAUGE:
                g->invertDirection();
                break;
            case GESCHOSS_FEUERBALL:
                if( intersectsWithBariere )
                {
                    feuer.add( new FeuerballTreffer( resources, ++nextId, (int)g->getX() - 70, (int)g->getY() - 70, g->getBesitzer(), 10 ) );
                    shots.remove( i );
                    i--;
                    removed = 1;
                }
                else
                    g->invertDirection();
                break;
            case GESCHOSS_MINE:
                for( auto s = spieler.getIterator(); s; s++ )
                {
                    if( s->abstandZu( g ) < 50 )
                    {
                        s->nimmSchaden( 100 - s->abstandZu( g ), g->zBesitzer(), MITTE, this );
                        if( g->zBesitzer() )
                            g->zBesitzer()->addTreffer( this );
                        s->addGetroffen();
                    }
                }
                shots.remove( i );
                i--;
                removed = 1;
                break;
            }
        }
        if( !removed )
        { // geschoss - tunnel intersection
            for( auto t = tunnel.getIterator(); t; t++ )
            {
                if( t->istAktiv() && t->intersectsWith( g ) )
                {
                    g->setX( g->getX() + (float)t->getZielX() - t->getX() );
                    g->setY( g->getY() + (float)t->getZielY() - t->getY() );
                    g->addTunnel( this );
                    Ereignis *e = new Ereignis( TUNNEL_BENUTZT );
                    e->addParameter( "Betroffes Geschoss", g->getThis() );
                    e->addParameter( "Betroffer Tunnel", t->getThis() );
                    throwEvent( e );
                }
            }
            // geschoss - schalter intersection
            if( g->getTyp() == GESCHOSS_PFEIL )
            {
                for( auto s = schalter.getIterator(); s; s++ )
                {
                    if( s->isAktive() && s->intersectsWith( g ) )
                    {
                        shots.remove( i );
                        i--;
                        removed = 1;
                        g->addSchalter();
                        activateShalter( s->getId() );
                    }
                }
            }
            if( !removed )
            {
                // geschoss - umlenkung intersection
                if( g->getTyp() != GESCHOSS_PFEIL )
                {
                    for( auto u = umlenkungen.getIterator(); u; u++ )
                    {
                        if( u->isAktive() && !u->hatAbklingzeit() && g->getTyp() != GESCHOSS_PFEIL && u->intersectsWith( g ) )
                        {
                            g->setRichtung( u->getRichtung() );
                            g->addUmlenkung( this );
                            u->addBenutzt( this );
                            Ereignis *e = new Ereignis( UMLENKUNG_LENKT_UM );
                            e->addParameter( "Betroffes Geschoss", g->getThis() );
                            e->addParameter( "Betroffe Umlenkung", u->getThis() );
                            throwEvent( e );
                        }
                    }
                }
                // geschoss - geschoss intersection
                if( g->getTyp() == GESCHOSS_PFEIL )
                {
                    for( int j = 0; j < shots.getEintragAnzahl(); j++ )
                    {
                        if( i == j )
                            continue;
                        Geschoss *g2 = shots.z( j );
                        if( g2->intersectsWith( g ) )
                        {
                            if( g2->getTyp() == GESCHOSS_PFEIL )
                                removed = 1;
                            g->addGeschossTreffer( this );
                            if( j < i )
                                i--;
                            shots.remove( j );
                        }
                    }
                }
                if( !removed )
                {
                    // geschoss - spieler intersection
                    for( auto s = spieler.getIterator(); s; s++ )
                    {
                        if( s->istAmLeben() && s != g->zBesitzer() && g->intersectsWith( s ) )
                        {
                            switch( g->getTyp() )
                            {
                            case GESCHOSS_PFEIL:
                            {
                                s->nimmSchaden( PFEIL_DAMAGE, g->zBesitzer(), invert( g->getRichtung() ), this );
                                break;
                            }
                            case GESCHOSS_KUGEL:
                            {
                                s->nimmSchaden( KUGEL_DAMAGE, g->zBesitzer(), invert( g->getRichtung() ), this );
                                break;
                            }
                            case GESCHOSS_DRACHENAUGE:
                                s->addEffekt( new DrachenAugeEffect( g->zBesitzer(), s._ ) );
                                break;
                            case GESCHOSS_FEUERBALL:
                                feuer.add( new FeuerballTreffer( resources, ++nextId, (int)g->getX() - 70, (int)g->getY() - 70, g->getBesitzer(), 10 ) );
                                break;
                            case GESCHOSS_MINE:
                                for( auto s2 = spieler.getIterator(); s2; s2++ )
                                {
                                    if( s2->abstandZu( g ) < 50 )
                                    {
                                        s2->nimmSchaden( 100 - s->abstandZu( g ), g->zBesitzer(), MITTE, this );
                                        if( g->zBesitzer() )
                                            g->zBesitzer()->addTreffer( this );
                                        s->addGetroffen();
                                    }
                                }
                                break;
                            }
                            if( g->getTyp() != GESCHOSS_MINE )
                            {
                                if( g->zBesitzer() )
                                    g->zBesitzer()->addTreffer( this );
                                s->addGetroffen();
                            }
                            shots.remove( i );
                            i--;
                            removed = 1;
                        }
                    }
                }
            }
        }
    }
    // Feuer Ticks
    for( int i = 0; i < feuer.getEintragAnzahl(); i++ )
    {
        FeuerballTreffer *f = feuer.z( i );
        f->tick( TICK );
        if( f->isOver() )
        {
            feuer.remove( i );
            i--;
            continue;
        }
        if( f->makeDamage() )
        {
            for( auto s = spieler.getIterator(); s; s++ )
            {
                if( s->abstandZu( f ) < f->getWidth() / 2 )
                    s->addEffekt( new BrandEffekt( resources, f->zVerursacher(), s ) );
            }
        }
    }
    // Drop Ticks
    for( auto d = drops.getIterator(); d; d++ )
        d->tick( TICK, this );
    // Timer Ticks
    for( auto t = timer.getIterator(); t; t++ )
        t->tick( TICK, this );
    // Umlenkung Ticks
    for( auto u = umlenkungen.getIterator(); u; u++ )
        u->tick( TICK );
    // Base Ticks
    for( auto b = basen.getIterator(); b; b++ )
        b->tick( TICK, this );
    // aktive trigger Ticks
    for( int i = 0; i < triggerRuns.getEintragAnzahl(); i++ )
    {
        if( !triggerRuns.z( i )->runNext( TICK ) )
        {
            Ereignis *e = new Ereignis( AUSLOESER_RUNNED );
            e->addParameter( "Betroffener Ausl�ser", triggerRuns.z( i )->getTrigger() );
            throwEvent( e );
            triggerRuns.remove( i );
            i--;
        }
    }
}

// nicht constant
void Spiel::lock()
{
    c.lock();
}

void Spiel::unlock()
{
    c.unlock();
}

// call 4
void Spiel::setSchrift( Schrift *schrift )
{
    if( this->schrift )
        this->schrift->release();
    this->schrift = schrift;
    chat->setSchrift( schrift );
}

// call 3
void Spiel::setBildschirm( Bildschirm *zScreen )
{
    this->zScreen = zScreen;
}

void Spiel::nachricht( int l�n, char *bytes )
{
    lock();
    stkn->add( new STKNachricht( l�n, bytes ) );
    unlock();
}

// call 2
void Spiel::setKlients( KSGClient::InformationServerClient *infoKlient, KSGClient::SpielServerClient *spielKlient )
{
    if( this->infoKlient )
        this->infoKlient->release();
    this->infoKlient = infoKlient;
    if( this->spielKlient )
        this->spielKlient->release();
    this->spielKlient = spielKlient;
}

// call 1
void Spiel::setKarteId( int karteId )
{
    this->karteId = karteId;
}

// call 5
void Spiel::ladeDaten()
{
    Sleep( 1000 );
    Text *gamePath = infoKlient->getDateiGruppePfad( infoKlient->getDateiGruppeIdVonSpiel( infoKlient->getSpielId( karteId ) ) );
    Text mapPf = Text( "data/tmp/Karten/" ) + karteId + "/spiel/files";
    // loading resources
    if( resources )
        resources->release();
    resources = new ResourceRegistry( gamePath->getText(), mapPf );
    resources->zResource( R_BARIERE, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/bariere.png" );
    resources->zResource( R_BASE, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/base.png" );
    resources->zResource( R_PFEIL_GESCHOSS, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/pfeilg.png" );
    resources->zResource( R_PFEIL, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/pfeil.png" );
    resources->zResource( R_LEBEN, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/leben.png" );
    resources->zResource( R_SCHILD, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/schild.png" );
    resources->zResource( R_SCHUH, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/schuh.png" );
    resources->zResource( R_GEIST, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/geist.png" );
    resources->zResource( R_ROLLE, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/rolle.png" );
    resources->zResource( R_ROLLE_OBEN, 0, new ColorMode(), "spiel:/bilder/rolleoben.ltdb" );
    resources->zResource( R_ROLLE_LINKS, 0, new ColorMode(), "spiel:/bilder/rollelinks.ltdb" );
    resources->zResource( R_ROLLE_RECHTS, 0, new ColorMode(), "spiel:/bilder/rollerechts.ltdb" );
    resources->zResource( R_ROLLE_UNTEN, 0, new ColorMode(), "spiel:/bilder/rolleunten.ltdb" );
    resources->zResource( R_STURM, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/sturm.png" );
    resources->zResource( R_STURM_OBEN, 0, new ColorMode(), "spiel:/bilder/sturmoben.ltdb" );
    resources->zResource( R_STURM_LINKS, 0, new ColorMode(), "spiel:/bilder/sturmlinks.ltdb" );
    resources->zResource( R_STURM_RECHTS, 0, new ColorMode(), "spiel:/bilder/sturmrechts.ltdb" );
    resources->zResource( R_STURM_UNTEN, 0, new ColorMode(), "spiel:/bilder/sturmunten.ltdb" );
    resources->zResource( R_DRACHENAUGE, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/drachenauge.png" );
    resources->zResource( R_DRACHENAUGE_GESCHOSS, 0, new ColorMode(), "spiel:/bilder/drachenauge.ltdb" );
    resources->zResource( R_FEUERBALL, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/feuerball.png" );
    resources->zResource( R_FEUERBALL_GESCHOSS, 0, new ColorMode(), "spiel:/bilder/feuerball.ltdb" );
    resources->zResource( R_FEUERBALL_TREFFER, 0, new ColorMode(), "spiel:/bilder/feuerballtreffer.ltdb" );
    resources->zResource( R_ENTERHAKEN_SEIL, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/enterhakenseil." );
    resources->zResource( R_ENTERHAKEN_SPITZE, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/enterhakenspitz" );
    resources->zResource( R_ENTERHAKEN_ITEM, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/enterhaken.png" );
    resources->zResource( R_MINE, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/miene.png" );
    resources->zResource( R_MINE_GESCHOSS, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/mieneg.png" );
    resources->zResource( R_RWEISHEIT, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/rweisheit.png" );
    resources->zResource( R_RBOSHEIT, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/rbosheit.png" );
    resources->zResource( R_RLEBEN, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/rleben.png" );
    resources->zResource( R_RTEMPO, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/rtempo.png" );
    resources->zResource( R_RSTRENGTH, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/rstrength.png" );
    resources->zResource( R_SCHALTER, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/schalter.png" );
    resources->zResource( R_SCHIENE, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/schiene.png" );
    resources->zResource( R_SPIELER_STIRBT, 0, new ColorMode(), "spiel:/bilder/spielerstirbt.ltdb" );
    resources->zResource( R_SPIELER, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/spieler.png" );
    resources->zResource( R_SPIELER_RECHTS, 0, new ColorMode(), "spiel:/bilder/spielerrechts.ltdb" );
    resources->zResource( R_SPIELER_LINKS, 0, new ColorMode(), "spiel:/bilder/spielerlinks.ltdb" );
    resources->zResource( R_BRAND, 0, new ColorMode(), "spiel:/bilder/brand.ltdb" );
    resources->zResource( R_EXPLOSION, 0, new ColorMode(), "spiel:/bilder/explosion.ltdb" );
    resources->zResource( R_HEILUNG, 0, new ColorMode(), "spiel:/bilder/heilung.ltdb" );
    resources->zResource( R_SCHADEN, 0, new ColorMode(), "spiel:/bilder/schaden.ltdb" );
    resources->zResource( R_TUNNEL, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/tunnel.png" );
    resources->zResource( R_UMLENKUNG, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/umlenkung.png" );
    resources->zResource( R_RWEISHEIT_EFFECT, 0, new ColorMode(), "spiel:/bilder/rweisheit.ltdb" );
    resources->zResource( R_RBOSHEIT_EFFECT, 0, new ColorMode(), "spiel:/bilder/rbosheit.ltdb" );
    resources->zResource( R_RLEBEN_EFFECT, 0, new ColorMode(), "spiel:/bilder/rleben.ltdb" );
    resources->zResource( R_RTEMPO_EFFECT, 0, new ColorMode(), "spiel:/bilder/rtempo.ltdb" );
    resources->zResource( R_RSTRENGTH_EFFECT, 0, new ColorMode(), "spiel:/bilder/rstrength.ltdb" );
    resources->zResource( R_KUGEL_GESCHOSS, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/kugelg.png" );
    resources->zResource( R_KUGEL, 0, new ColorMode(), "spiel:/bilder/textures.ltdb/kugel.png" );
    resources->zResource( R_GUI_ERF, 0, new ColorMode(), "spiel:/bilder/gui.ltdb/erfleiste.png" );
    resources->zResource( R_GUI_ERF_RAND, 0, new ColorMode(), "spiel:/bilder/gui.ltdb/erfrand.png" );
    resources->zResource( R_GUI_INVENTAR_AUSWAHL, 0, new ColorMode(), "spiel:/bilder/gui.ltdb/invausw.png" );
    resources->zResource( R_GUI_INVENTAR_HINTERGRUND, 0, new ColorMode(), "spiel:/bilder/gui.ltdb/invbg.png" );
    resources->zResource( R_GUI_INVENTAR_HINTERGRUND_BENUTZT, 0, new ColorMode(), "spiel:/bilder/gui.ltdb/invbgdark.png" );
    resources->zResource( R_GUI_LEBEN_RAND, 0, new ColorMode(), "spiel:/bilder/gui.ltdb/lebenrand.png" );
    resources->zResource( R_GUI_LEVEL_RAND, 0, new ColorMode(), "spiel:/bilder/gui.ltdb/levelrand.png" );
    resources->zResource( R_GUI_SPIELER, 0, new ColorMode(), "spiel:/bilder/gui.ltdb/spieler.png" );
    spielKlient->setLadenProzent( 20 );

    MapReader *reader = new MapReader( karteId, Text( "data/tmp/Karten/" ) + karteId + "/spiel/data/" );
    // apply team color filters
    Array<int> *colors = reader->getTeamFarben();
    AlphaColorMode *alphaMode = new AlphaColorMode( 0x77 );
    for( auto c = colors->getIterator(); c; c++ )
    {
        resources->zResource( R_BARIERE, c._, alphaMode->getThis() );
        resources->zResource( R_BASE, c._, alphaMode->getThis() );
    }
    colors->release();
    alphaMode->release();
    spielKlient->setLadenProzent( 35 );
    // apply player color filters
    colors = reader->getSpielerFarben();
    MaskColorMode *maskMode = new MaskColorMode( 0xFFFFFF );
    for( auto c = colors->getIterator(); c; c++ )
    {
        resources->zResource( R_ROLLE_OBEN, c._, maskMode->getThis() );
        resources->zResource( R_ROLLE_LINKS, c._, maskMode->getThis() );
        resources->zResource( R_ROLLE_RECHTS, c._, maskMode->getThis() );
        resources->zResource( R_ROLLE_UNTEN, c._, maskMode->getThis() );
        resources->zResource( R_STURM_OBEN, c._, maskMode->getThis() );
        resources->zResource( R_STURM_LINKS, c._, maskMode->getThis() );
        resources->zResource( R_STURM_RECHTS, c._, maskMode->getThis() );
        resources->zResource( R_STURM_UNTEN, c._, maskMode->getThis() );
        resources->zResource( R_SPIELER_STIRBT, c._, maskMode->getThis() );
        resources->zResource( R_SPIELER, c._, maskMode->getThis() );
        resources->zResource( R_SPIELER_RECHTS, c._, maskMode->getThis() );
        resources->zResource( R_SPIELER_LINKS, c._, maskMode->getThis() );
    }
    colors->release();
    spielKlient->setLadenProzent( 50 );
    // loading map
    reader->ladeKarte( this );
    spielKlient->setLadenProzent( 99 );
    reader->release();

    resources->setSchrift( schrift->getThis() );
    spielerGUI = new SpielerGUI( resources );
    maskMode->release();
    spielKlient->setLadenProzent( 100 );
    gamePath->release();
}

void Spiel::doPublicMausEreignis( MausEreignis &me )
{
    if( me.verarbeitet )
        return;
    if( end )
    {
        end->doPublicMausEreignis( me );
        return;
    }
    chat->doPublicMausEreignis( me );
}

void Spiel::doTastaturEreignis( TastaturEreignis &te )
{
    if( te.verarbeitet )
        return;
    if( end )
    {
        end->doTastaturEreignis( te );
        return;
    }
    if( !chat->istAktiv() )
    {
        if( te.id == TE_Press && !tasten[ te.taste ] )
        {
            char buff[ 2 ] = { 0, (char)te.taste };
            spielKlient->spielNachricht( 2, buff );
            tasten[ te.taste ] = 1;
            te.verarbeitet = 1;
        }
        else if( te.id == TE_Release && tasten[ te.taste ] )
        {
            char buff[ 2 ] = { 1, (char)te.taste };
            spielKlient->spielNachricht( 2, buff );
            tasten[ te.taste ] = 0;
            te.verarbeitet = 1;
        }
    }
    if( !te.verarbeitet )
        chat->doTastaturEreignis( te, spielKlient );
}

void Spiel::stknVerarbeitung()
{
    lock();
    while( stkn->getEintragAnzahl() )
    {
        STKNachricht *n = stkn->z( 0 );
        char *msg = n->getNachricht();
        switch( *msg )
        {
        case 1: // initialisation
            spielerAnzahl = ( int ) * ( msg + 1 );
            for( int i = 0; i < spielerAnzahl; i++ )
            {
                int sId = *(int *)( msg + 2 + i * 8 );
                int aId = *(int *)( msg + 6 + i * 8 );
                for( auto s = spieler.getIterator(); s; s++ )
                {
                    if( s->getId() == sId )
                    {
                        s->setAccount( aId );
                        Text *t = infoKlient->getSpielerName( aId );
                        s->setName( t->getText() );
                        t->release();
                        break;
                    }
                }
            }
            n->setVerarbeitet();
            break;
        case 2: // spielernummer
            spielerNummer = *(int *)( msg + 1 );
            for( auto s = spieler.getIterator(); s; s++ )
            {
                if( s->getId() == spielerNummer )
                    spielerGUI->setSpieler( (Spieler *)s->getThis() );
            }
            n->setVerarbeitet();
            break;
        case 3: // spiel start
            pause = 0;
            rendern = 1;
            n->setVerarbeitet();
            break;
        case 4: // tasten stand
        {
            char taste = *(char *)( msg + 1 );
            char aktiv = *(char *)( msg + 2 );
            int sId = *(int *)( msg + 3 );
            for( auto s = spieler.getIterator(); s; s++ )
            {
                if( s->getId() == sId )
                {
                    s->setTastenStand( taste, aktiv );
                    break;
                }
            }
            n->setVerarbeitet();
            break;
        }
        case 5: // Spiel ende
            n->setVerarbeitet();
            break;
        case 6: //tick
            if( rZeit > 0.2 )
            {
                tick();
                n->setVerarbeitet();
            }
            break;
        case 7: // chat nachricht
        {
            unsigned char len = ( unsigned char ) * ( msg + 1 );
            char *buf = new char[ len + 1 ];
            memcpy( buf, msg + 2, len );
            buf[ len ] = 0;
            chat->addNachricht( buf );
            delete[] buf;
            n->setVerarbeitet();
            break;
        }
        }
        if( n->istVerarbeitet() )
            stkn->remove( 0 );
        else
            break;
    }
    unlock();
}

bool Spiel::tick( double zeit )
{
    if( !pause && !end )
        rZeit += zeit;
    stknVerarbeitung();
    int deadsCount = deads->getEintragAnzahl();
    for( int i = 0; i < deadsCount; i++ )
    {
        if( deads->z( i )->isFinished() )
        {
            deads->remove( i-- );
            deadsCount--;
        }
    }
    chat->tick( zeit );
    return 1;
}

void Spiel::render( Bild &zRObj )
{
    if( spielerGUI )
        spielerGUI->render( zRObj );
    Spieler *i = 0;
    for( auto s = spieler.getIterator(); s; s++ )
    {
        if( s->getId() == spielerNummer )
            i = s;
    }
    if( !i )
        return;
    if( zRObj.setDrawOptions( 300, 0, zRObj.getBreite() - 300, zRObj.getHeight() ) )
    {
        zRObj.addScrollOffset( (int)i->getX() - ( zRObj.getBreite() - 300 ) / 2, (int)i->getY() - zRObj.getHeight() / 2 );
        for( auto f = feuer.getIterator(); f; f++ )
            f->render( zRObj );
        for( auto s = schalter.getIterator(); s; s++ )
            s->render( zRObj );
        for( auto t = tunnel.getIterator(); t; t++ )
            t->render( zRObj );
        for( auto b = basen.getIterator(); b; b++ )
            b->render( zRObj );
        for( auto u = umlenkungen.getIterator(); u; u++ )
            u->render( zRObj );
        for( auto s = schienen.getIterator(); s; s++ )
            s->render( zRObj );
        for( auto i = items.getIterator(); i; i++ )
            i->render( zRObj );
        for( auto b = barieren.getIterator(); b; b++ )
            b->render( zRObj );
        // TODO: render deads
        for( auto s = spieler.getIterator(); s; s++ )
            s->render( zRObj );
        for( auto s = shots.getIterator(); s; s++ )
            s->render( zRObj );
        // TODO: render timer
        zRObj.releaseDrawOptions();
    }
    chat->render( zRObj );
    if( end )
        end->render( zRObj );
}

void Spiel::setMapSize( int width, int height )
{
    mapSize = Punkt( width, height );
}

void Spiel::setPausiert( bool pausiert )
{
    this->pause = pausiert;
}

void Spiel::addVariable( const char *name, Variable *var )
{
    bool found = 0;
    for( auto v = variablen.getIterator(); v; v++ )
    {
        if( v->getName().istGleich( name ) )
        {
            found = 1;
            break;
        }
    }
    if( !found )
        variablen.add( new VarPointer( name, var ) );
    else
        var->release();
}

void Spiel::setVariable( const char *name, Variable *var )
{
    bool found = 0;
    for( auto v = variablen.getIterator(); v; v++ )
    {
        if( v->getName().istGleich( name ) )
        {
            v->setVariable( var );
            break;
        }
    }
    if( !found )
        var->release();
}

void Spiel::addTeam( Team *team )
{
    teams.add( team );
}

void Spiel::addSpieler( Spieler *spieler )
{
    this->spieler.add( spieler );
}

void Spiel::addBariere( Bariere *bariere )
{
    barieren.add( bariere );
}

void Spiel::addBase( Base *base )
{
    basen.add( base );
}

void Spiel::addDrop( Drop *drop )
{
    drops.add( drop );
}

void Spiel::addGegenstand( Gegenstand *gegenstand )
{
    items.add( gegenstand );
    zuletztGedropterGegenstand = gegenstand->getTyp();
    Ereignis *e = new Ereignis( GEGENSTAND_DROPED );
    e->addParameter( "Betroffener Gegenstand", gegenstand->getThis() );
    throwEvent( e );
}

void Spiel::addGeschoss( Geschoss *geschoss )
{
    if( zuletztAbgefeuertesGeschoss )
        zuletztAbgefeuertesGeschoss->release();
    zuletztAbgefeuertesGeschoss = geschoss;
    shots.add( geschoss );
}

void Spiel::addSchalter( Schalter *schalter )
{
    this->schalter.add( schalter );
}

void Spiel::addSchiene( Schiene *schiene )
{
    schienen.add( schiene );
}

void Spiel::addTimer( Timer *timer )
{
    this->timer.add( timer );
}

void Spiel::addTunnel( Tunnel *tunnel )
{
    this->tunnel.add( tunnel );
}

void Spiel::addUmlenkung( Umlenkung *umlenkung )
{
    umlenkungen.add( umlenkung );
}

void Spiel::addTrigger( Trigger *trigger )
{
    this->trigger.add( trigger );
}

void Spiel::addTriggerRun( TriggerRun *tRun )
{
    if( tRun )
    {
        if( lastRunnedTrigger )
            lastRunnedTrigger->release();
        lastRunnedTrigger = tRun->getTrigger();
        triggerRuns.add( tRun );
    }
}

void Spiel::spielerActivate( Spieler *zSpieler )
{
    // spieler - item intersection
    for( int i = 0; i < items.getEintragAnzahl(); i++ )
    {
        if( items.z( i )->intersectsWith( zSpieler ) )
        {
            items.remove( i );
            zSpieler->addItem( items.z( i )->getTyp(), 1, this );
            i--;
        }
    }
    // Spieler - schalter intersection
    for( int i = 0; i < schalter.getEintragAnzahl(); i++ )
    {
        if( schalter.z( i )->intersectsWith( zSpieler ) )
        {
            zSpieler->addSchalterBenutzung( this );
            schalter.z( i )->press( this );
        }
    }
    // Spieler - tunnel intersection
    for( int i = 0; i < tunnel.getEintragAnzahl(); i++ )
    {
        if( tunnel.z( i )->intersectsWith( zSpieler ) )
        {
            zSpieler->addTunnelBenutzung( this );
            zSpieler->setX( (float)tunnel.z( i )->getZielX() - zSpieler->getWidth() / 2.f );
            zSpieler->setY( (float)tunnel.z( i )->getZielY() - zSpieler->getHeight() / 2.f );
            tunnel.z( i )->addBenutzung( this );
        }
    }
}

Team *Spiel::getTeam( int id ) const
{
    for( auto t = teams.getIterator(); t; t++ )
    {
        if( t->getTeamNummer() == id )
            return (Team *)t->getThis();
    }
    return 0;
}

Spieler *Spiel::getSpieler( int id ) const
{
    for( auto s = spieler.getIterator(); s; s++ )
    {
        if( s->getId() == id )
            return (Spieler *)s->getThis();
    }
    return 0;
}

Iterator<Spieler *> Spiel::getSpieler() const
{
    return spieler.getIterator();
}

Iterator<Bariere *> Spiel::getBarieren() const
{
    return barieren.getIterator();
}

Bariere *Spiel::getBariere( int id ) const
{
    for( auto b = barieren.getIterator(); b; b++ )
    {
        if( b->getId() == id )
            return (Bariere *)b->getThis();
    }
    return 0;
}

Base *Spiel::getBase( int id ) const
{
    for( auto b = basen.getIterator(); b; b++ )
    {
        if( b->getId() == id )
            return (Base *)b->getThis();
    }
    return 0;
}

Drop *Spiel::getDrop( int id ) const
{
    for( auto d = drops.getIterator(); d; d++ )
    {
        if( d->getId() == id )
            return (Drop *)d->getThis();
    }
    return 0;
}

Schalter *Spiel::getSchalter( int id ) const
{
    for( auto s = schalter.getIterator(); s; s++ )
    {
        if( s->getId() == id )
            return (Schalter *)s->getThis();
    }
    return 0;
}

Schiene *Spiel::getSchiene( int id ) const
{
    for( auto s = schienen.getIterator(); s; s++ )
    {
        if( s->getId() == id )
            return (Schiene *)s->getThis();
    }
    return 0;
}

Timer *Spiel::getTimer( int id ) const
{
    for( auto t = timer.getIterator(); t; t++ )
    {
        if( t->getId() == id )
            return (Timer *)t->getThis();
    }
    return 0;
}

Tunnel *Spiel::getTunnel( int id ) const
{
    for( auto t = tunnel.getIterator(); t; t++ )
    {
        if( t->getId() == id )
            return (Tunnel *)t->getThis();
    }
    return 0;
}

Umlenkung *Spiel::getUmlenkung( int id ) const
{
    for( auto u = umlenkungen.getIterator(); u; u++ )
    {
        if( u->getId() == id )
            return (Umlenkung *)u->getThis();
    }
    return 0;
}

Trigger *Spiel::getTrigger( int id ) const
{
    for( auto t = trigger.getIterator(); t; t++ )
    {
        if( t->getId() == id )
            return (Trigger *)t->getThis();
    }
    return 0;
}

Variable *Spiel::getVariable( const char *name ) const
{
    for( auto v = variablen.getIterator(); v; v++ )
    {
        if( v->getName().istGleich( name ) )
            return v->getVariable();
    }
    return 0;
}

Variable *Spiel::zVariable( const char *name ) const
{
    for( auto v = variablen.getIterator(); v; v++ )
    {
        if( v->getName().istGleich( name ) )
            return v->zVariable();
    }
    return 0;
}

bool Spiel::istPausiert() const
{
    return pause;
}

void Spiel::activateShalter( int id )
{
    for( auto s = schalter.getIterator(); s; s++ )
    {
        if( s->getId() == id )
            s->press( this );
    }
}

void Spiel::throwEvent( Ereignis *e )
{
    for( auto t = trigger.getIterator(); t; t++ )
    {
        if( t->hatEreignis( e->getTyp() ) )
        {
            TriggerRun *tr = t->runTrigger( e->getThis(), this );
            if( tr )
                triggerRuns.add( tr );
        }
    }
    e->release();
}

bool Spiel::needEvent( EreignisTyp typ ) const
{
    for( auto t = trigger.getIterator(); t; t++ )
    {
        if( t->hatEreignis( typ ) )
            return 1;
    }
    return 0;
}

int Spiel::getNextId()
{
    return ++nextId;
}

double Spiel::getRand()
{
    return randG.rand();
}

int Spiel::getTickCount() const
{
    return gameTicks;
}

void Spiel::setEnde( Team *zGewinner )
{
    zWinner = zGewinner;
    Spieler *i = 0;
    for( auto s = spieler.getIterator(); s; s++ )
    {
        if( s->getId() == spielerNummer )
            i = s;
    }
    end = new Ende( schrift );
    end->setGewonnen( ( zGewinner && i ) ? ( i->zTeam() == zGewinner ) : -1 );
}

Trigger *Spiel::getRandomTrigger()
{
    if( !trigger.getEintragAnzahl() )
        return 0;
    return trigger.get( (int)( randG.rand() * trigger.getEintragAnzahl() ) );
}

Trigger *Spiel::getLastRunnedTrigger() const
{
    return lastRunnedTrigger ? (Trigger *)lastRunnedTrigger->getThis() : 0;
}

Bariere *Spiel::getRandomBariere()
{
    return barieren.get( (int)( randG.rand() * barieren.getEintragAnzahl() ) );
}

void Spiel::setZuletztEingeschalteteBariere( Bariere *b )
{
    if( zuletztEingeschalteteBariere )
        zuletztEingeschalteteBariere->release();
    zuletztEingeschalteteBariere = b;
}

Bariere *Spiel::getZuletztEingeschalteteBariere() const
{
    return zuletztEingeschalteteBariere ? (Bariere *)zuletztEingeschalteteBariere->getThis() : 0;
}

void Spiel::setZuletztAusgeschalteteBariere( Bariere *b )
{
    if( zuletztAusgeschalteteBariere )
        zuletztAusgeschalteteBariere->release();
    zuletztAusgeschalteteBariere = b;
}

Bariere *Spiel::getZuletztAusgeschalteteBariere() const
{
    return zuletztAusgeschalteteBariere ? (Bariere *)zuletztAusgeschalteteBariere->getThis() : 0;
}

void Spiel::setZuletztBewegteBariere( Bariere *b )
{
    if( zuletztBewegteBariere )
        zuletztBewegteBariere->release();
    zuletztBewegteBariere = b;
}

Bariere *Spiel::getZuletztBewegteBariere() const
{
    return zuletztBewegteBariere ? (Bariere *)zuletztBewegteBariere->getThis() : 0;
}

Base *Spiel::getRandomBase()
{
    if( !basen.getEintragAnzahl() )
        return 0;
    return basen.get( (int)( randG.rand() * basen.getEintragAnzahl() ) );
}

void Spiel::setLastTeamChangedBase( Base *b )
{
    if( lastTeamChangedBase )
        lastTeamChangedBase->release();
    lastTeamChangedBase = b;
}

Base *Spiel::getLastTeamChangedBase() const
{
    return lastTeamChangedBase ? (Base *)lastTeamChangedBase->getThis() : 0;
}

Drop *Spiel::getRandomDrop()
{
    if( !drops.getEintragAnzahl() )
        return 0;
    return drops.get( (int)( randG.rand() * drops.getEintragAnzahl() ) );
}

void Spiel::setLastDrop( Drop *d )
{
    if( lastDropedDrop )
        lastDropedDrop->release();
    lastDropedDrop = d;
}

Drop *Spiel::getLastDrop() const
{
    return lastDropedDrop ? (Drop *)lastDropedDrop->getThis() : 0;
}

void Spiel::setItemZuletztAufgehoben( GegenstandTyp g )
{
    zuletztAufgehobenerGegenstand = g;
}

GegenstandTyp Spiel::getItemZuletztAufgehoben() const
{
    return zuletztAufgehobenerGegenstand;
}

void Spiel::setItemZuletztAktiviert( GegenstandTyp g )
{
    zuletztBenutzterGegenstand = g;
}

GegenstandTyp Spiel::getItemZuletztAktiviert() const
{
    return zuletztBenutzterGegenstand;
}

GegenstandTyp Spiel::getItemZuletztGedropt() const
{
    return zuletztGedropterGegenstand;
}

Geschoss *Spiel::getRandomGeschoss()
{
    if( !shots.getEintragAnzahl() )
        return 0;
    return shots.get( (int)( randG.rand() * shots.getEintragAnzahl() ) );
}

Geschoss *Spiel::getGeschossZuletztAbgefeuert() const
{
    return zuletztAbgefeuertesGeschoss ? (Geschoss *)zuletztAbgefeuertesGeschoss->getThis() : 0;
}

void Spiel::setGeschossZuletztUmgelenkt( Geschoss *g )
{
    if( zuletztUmgelenktesGeschoss )
        zuletztUmgelenktesGeschoss->release();
    zuletztUmgelenktesGeschoss = g;
}

Geschoss *Spiel::getGeschossZuletztUmgelenkt() const
{
    return zuletztUmgelenktesGeschoss ? (Geschoss *)zuletztUmgelenktesGeschoss->getThis() : 0;
}

Geschoss *Spiel::getGeschossZuletztBariereGetroffen() const
{
    return zuletztBariereGetroffenesGeschoss ? (Geschoss *)zuletztBariereGetroffenesGeschoss->getThis() : 0;
}

void Spiel::setGeschossZuletztTunnelBenutzt( Geschoss *g )
{
    if( zuletztTunnelBenutztesGeschoss )
        zuletztTunnelBenutztesGeschoss->release();
    zuletztTunnelBenutztesGeschoss = g;
}

Geschoss *Spiel::getGeschossZuletztTunnelBenutzt() const
{
    return zuletztTunnelBenutztesGeschoss ? (Geschoss *)zuletztTunnelBenutztesGeschoss->getThis() : 0;
}

void Spiel::setGeschossZuletztGeschossGetroffen( Geschoss *g )
{
    if( zuletztGeschossGetroffenesGeschoss )
        zuletztGeschossGetroffenesGeschoss->release();
    zuletztGeschossGetroffenesGeschoss = g;
}

Geschoss *Spiel::getGeschossZuletztGeschossGetroffen() const
{
    return zuletztGeschossGetroffenesGeschoss ? (Geschoss *)zuletztGeschossGetroffenesGeschoss->getThis() : 0;
}

Schalter *Spiel::getRandomSchalter()
{
    if( !schalter.getEintragAnzahl() )
        return 0;
    return schalter.get( (int)( randG.rand() * schalter.getEintragAnzahl() ) );
}

void Spiel::setSchalterZuletztAktiviert( Schalter *s )
{
    if( zuletztAktivierterSchalter )
        zuletztAktivierterSchalter->release();
    zuletztAktivierterSchalter = s;
}

Schalter *Spiel::getSchalterZuletztAktiviert() const
{
    return zuletztAktivierterSchalter ? (Schalter *)zuletztAktivierterSchalter->getThis() : 0;
}

Spieler *Spiel::getRandomSpieler()
{
    if( !spieler.getEintragAnzahl() )
        return 0;
    return spieler.get( (int)( randG.rand() * spieler.getEintragAnzahl() ) );
}

Spieler *Spiel::getRandomSpieler( Team *zTeam )
{
    if( !zTeam || !zTeam->getSpielerAnzahl() )
        return 0;
    int index = (int)( randG.rand() * zTeam->getSpielerAnzahl() );
    for( auto s = spieler.getIterator(); s; s++ )
    {
        if( s->zTeam() == zTeam )
        {
            if( index-- <= 0 )
                return (Spieler *)s->getThis();
        }
    }
    return 0;
}

void Spiel::setSpielerZuletztSchadenGemacht( Spieler *s )
{
    if( zuletztSchadenGemachterSpieler )
        zuletztSchadenGemachterSpieler->release();
    zuletztSchadenGemachterSpieler = s;
}

Spieler *Spiel::getSpielerZuletztSchadenGemacht() const
{
    return zuletztSchadenGemachterSpieler ? (Spieler *)zuletztSchadenGemachterSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztSchadenGenommen( Spieler *s )
{
    if( zuletztSchadenGenommenerSpieler )
        zuletztSchadenGenommenerSpieler->release();
    zuletztSchadenGenommenerSpieler = s;
}

Spieler *Spiel::getSpielerZuletztSchadenGenommen() const
{
    return zuletztSchadenGenommenerSpieler ? (Spieler *)zuletztSchadenGenommenerSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztGeheilt( Spieler *s )
{
    if( zuletztGeheilterSpieler )
        zuletztGeheilterSpieler->release();
    zuletztGeheilterSpieler = s;
}

Spieler *Spiel::getSpielerZuletztGeheilt() const
{
    return zuletztGeheilterSpieler ? (Spieler *)zuletztGeheilterSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztLevelUp( Spieler *s )
{
    if( zuletztLevelUpSpieler )
        zuletztLevelUpSpieler->release();
    zuletztLevelUpSpieler = s;
}

Spieler *Spiel::getSpielerZuletztLevelUp() const
{
    return zuletztLevelUpSpieler ? (Spieler *)zuletztLevelUpSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztErfahrungBekommen( Spieler *s )
{
    if( zuletztErfahrungBekommenerSpieler )
        zuletztErfahrungBekommenerSpieler->release();
    zuletztErfahrungBekommenerSpieler = s;
}

Spieler *Spiel::getSpielerZuletztErfahrungBekommen() const
{
    return zuletztErfahrungBekommenerSpieler ? (Spieler *)zuletztErfahrungBekommenerSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztGegenstandAktiviert( Spieler *s )
{
    if( zuletztGegenstandAktivierterSpieler )
        zuletztGegenstandAktivierterSpieler->release();
    zuletztGegenstandAktivierterSpieler = s;
}

Spieler *Spiel::getSpielerZuletztGegenstandAktiviert() const
{
    return zuletztGegenstandAktivierterSpieler ? (Spieler *)zuletztGegenstandAktivierterSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztGegenstandAufgehoben( Spieler *s )
{
    if( zuletztGegenstandAufgehobenerSpieler )
        zuletztGegenstandAufgehobenerSpieler->release();
    zuletztGegenstandAufgehobenerSpieler = s;
}

Spieler *Spiel::getSpielerZuletztGegenstandAufgehoben() const
{
    return zuletztGegenstandAufgehobenerSpieler ? (Spieler *)zuletztGegenstandAufgehobenerSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztSchalterAktiviert( Spieler *s )
{
    if( zuletztSchalterAktivierterSpieler )
        zuletztSchalterAktivierterSpieler->release();
    zuletztSchalterAktivierterSpieler = s;
}

Spieler *Spiel::getSpielerZuletztSchalterAktiviert() const
{
    return zuletztSchalterAktivierterSpieler ? (Spieler *)zuletztSchalterAktivierterSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztTunnelBenutzt( Spieler *s )
{
    if( zuletztTunnelBenutzterSpieler )
        zuletztTunnelBenutzterSpieler->release();
    zuletztTunnelBenutzterSpieler = s;
}

Spieler *Spiel::getSpielerZuletztTunnelBenutzt() const
{
    return zuletztTunnelBenutzterSpieler ? (Spieler *)zuletztTunnelBenutzterSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztGestorben( Spieler *s )
{
    if( zuletztGestorbenerSpieler )
        zuletztGestorbenerSpieler->release();
    zuletztGestorbenerSpieler = s;
}

Spieler *Spiel::getSpielerZuletztGestorben() const
{
    return zuletztGestorbenerSpieler ? (Spieler *)zuletztGestorbenerSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztWiederbelebt( Spieler *s )
{
    if( zuletztWiederbelebterSpieler )
        zuletztWiederbelebterSpieler->release();
    zuletztWiederbelebterSpieler = s;
}

Spieler *Spiel::getSpielerZuletztWiederbelebt() const
{
    return zuletztWiederbelebterSpieler ? (Spieler *)zuletztWiederbelebterSpieler->getThis() : 0;
}

void Spiel::setSpielerZuletztGeschossen( Spieler *s )
{
    if( zuletztGeschossenerSpieler )
        zuletztGeschossenerSpieler->release();
    zuletztGeschossenerSpieler = s;
}

Spieler *Spiel::getSpielerZuletztGeschossen() const
{
    return zuletztGeschossenerSpieler ? (Spieler *)zuletztGeschossenerSpieler->getThis() : 0;
}

Team *Spiel::getRandomTeam()
{
    if( !teams.getEintragAnzahl() )
        return 0;
    return teams.get( (int)( randG.rand() * teams.getEintragAnzahl() ) );
}

Timer *Spiel::getRandomTimer()
{
    if( !timer.getEintragAnzahl() )
        return 0;
    return timer.get( (int)( randG.rand() * timer.getEintragAnzahl() ) );
}

void Spiel::setTimerZuletztAbgelaufen( Timer *t )
{
    if( zuletztAbgelaufenerTimer )
        zuletztAbgelaufenerTimer->release();
    zuletztAbgelaufenerTimer = t;
}

Timer *Spiel::getTimerZuletztAbgelaufen() const
{
    return zuletztAbgelaufenerTimer ? (Timer *)zuletztAbgelaufenerTimer->getThis() : 0;
}

void Spiel::setTimerZuletztGestartet( Timer *t )
{
    if( zuletztGestarteterTimer )
        zuletztGestarteterTimer->release();
    zuletztGestarteterTimer = t;
}

Timer *Spiel::getTimerZuletztGestartet() const
{
    return zuletztGestarteterTimer ? (Timer *)zuletztGestarteterTimer->getThis() : 0;
}

void Spiel::setTimerZuletztPausiert( Timer *t )
{
    if( zuletztPausierterTimer )
        zuletztPausierterTimer->release();
    zuletztPausierterTimer = t;
}

Timer *Spiel::getTimerZuletztPausiert() const
{
    return zuletztPausierterTimer ? (Timer *)zuletztPausierterTimer->getThis() : 0;
}

void Spiel::setTimerZuletztFortgesetzt( Timer *t )
{
    if( zuletztFortgesetzterTimer )
        zuletztFortgesetzterTimer->release();
    zuletztFortgesetzterTimer = t;
}

Timer *Spiel::getTimerZuletztFortgesetzt() const
{
    return zuletztFortgesetzterTimer ? (Timer *)zuletztFortgesetzterTimer->getThis() : 0;
}

Tunnel *Spiel::getRandomTunnel()
{
    if( !tunnel.getEintragAnzahl() )
        return 0;
    return tunnel.get( (int)( randG.rand() * tunnel.getEintragAnzahl() ) );
}

void Spiel::setTunnelZuletztBenutzt( Tunnel *t )
{
    if( zuletztBenutzterTunnel )
        zuletztBenutzterTunnel->release();
    zuletztBenutzterTunnel = t;
}

Tunnel *Spiel::getTunnelZuletztBenutzt() const
{
    return zuletztBenutzterTunnel ? (Tunnel *)zuletztBenutzterTunnel->getThis() : 0;
}

Umlenkung *Spiel::getRandomUmlenkung()
{
    if( !umlenkungen.getEintragAnzahl() )
        return 0;
    return umlenkungen.get( (int)( randG.rand() * umlenkungen.getEintragAnzahl() ) );
}

void Spiel::setUmlenkungZuletztBenutzt( Umlenkung *t )
{
    if( zuletztBenutzteUmlenkung )
        zuletztBenutzteUmlenkung->release();
    zuletztBenutzteUmlenkung = t;
}

Umlenkung *Spiel::getUmlenkungZuletztBenutzt() const
{
    return zuletztBenutzteUmlenkung ? (Umlenkung *)zuletztBenutzteUmlenkung->getThis() : 0;
}

ResourceRegistry *Spiel::zResources() const
{
    return resources;
}

int Spiel::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 *Spiel::getThis()
{
    ref++;
    return this;
}

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