#include "Trigger.h" #include "Gegenstand.h" VarPointer::VarPointer( const char *name, Variable *var ) : ReferenceCounter() { this->name = name; this->var = var; } VarPointer::~VarPointer() { if( var ) var->release(); } Text VarPointer::getName() const { return name; } void VarPointer::setVariable( Variable *var ) { if( this->var ) this->var->release(); this->var = var; } Variable *VarPointer::getVariable() const { return var ? dynamic_cast( var->getThis() ) : 0; } Variable *VarPointer::zVariable() const { return var; } VarPointer::operator Variable *( ) const { return var; } LocalMemory::LocalMemory() : ReferenceCounter() {} LocalMemory::~LocalMemory() {} void LocalMemory::setVar( const char *name, Variable *var ) { for( auto v = vars.getIterator(); v; v++ ) { if( v->getName().istGleich( name ) ) { v->setVariable( var ); return; } } vars.add( new VarPointer( name, var ) ); } Variable *LocalMemory::getVariable( const char *name ) { for( auto v = vars.getIterator(); v; v++ ) { if( v->getName().istGleich( name ) ) return v->getVariable(); } return 0; } Variable *LocalMemory::zVariable( const char *name ) { for( auto v = vars.getIterator(); v; v++ ) { if( v->getName().istGleich( name ) ) return v->zVariable(); } return 0; } ProgramCounter::ProgramCounter() : ReferenceCounter() { current.add( 0 ); depth = 0; } ProgramCounter::~ProgramCounter() {} void ProgramCounter::stepIn() { depth++; if( current.getEintragAnzahl() <= depth ) current.add( 0 ); } void ProgramCounter::count() { current.set( current.get( depth ) + 1, depth ); while( depth + 1 < current.getEintragAnzahl() ) current.remove( depth + 1 ); } void ProgramCounter::stepOut() { depth--; } Text ProgramCounter::getUniqueString() const { Text ret = "__"; for( int i = 0; i < depth; i++ ) ret += Text( current.get( i ) ) + "__"; return ret; } int ProgramCounter::currentPosition() const { return current.get( depth ); } Bedingung::Bedingung( Aktion *expression ) : ReferenceCounter() { this->expression = expression; } Bedingung::~Bedingung() { if( expression ) expression->release(); } void Bedingung::setExpression( Aktion *expr ) { if( expression ) expression->release(); expression = expr; } bool Bedingung::check( Spiel *zSpiel, Ereignis *zEreignis ) { if( !expression ) return 1; double wait = 0; ProgramCounter c; LocalMemory m; while( !expression->runNext( zSpiel, zEreignis, &m, &c, wait ) ) wait = 0; Variable *var = m.zVariable( "__return__" ); return isTrue( var ); } Trigger::Trigger( int id, const char *name, int ereignisAnzahl, EreignisTyp *ereignisse, RCArray< Bedingung > *bedingungen, RCArray< Aktion > *aktionen ) : Variable( TRIGGER ) { this->id = id; this->name = name; this->ereignisAnzahl = ereignisAnzahl; this->ereignisse = ereignisse; this->bedingungen = bedingungen; this->aktionen = aktionen; aktiv = 1; runCount = 0; } Trigger::~Trigger() { delete[]ereignisse; bedingungen->release(); aktionen->release(); } void Trigger::setAktiv( bool aktiv ) { this->aktiv = aktiv; } bool Trigger::hatEreignis( EreignisTyp typ ) const { for( int i = 0; i < ereignisAnzahl; i++ ) { if( ereignisse[ i ] == typ ) return 1; } return 0; } int Trigger::getAktionAnzahl() const { return aktionen->getEintragAnzahl(); } Aktion *Trigger::zAktion( int index ) const { return aktionen->z( index ); } Aktion *Trigger::getAktion( int index ) const { return aktionen->get( index ); } // return: 0, falls die bedingungen nicht erfüllt sind TriggerRun *Trigger::runTrigger( Ereignis *e, Spiel *zSpiel ) { if( !aktiv ) { e->release(); return 0; } for( auto b = bedingungen->getIterator(); b; b++ ) { if( !b->check( zSpiel, e ) ) { e->release(); return 0; } } runCount++; return new TriggerRun( dynamic_cast( getThis() ), e, zSpiel ); } int Trigger::getId() const { return id; } int Trigger::getRuns() const { return runCount; } const char *Trigger::getName() const { return name.getText(); } bool Trigger::istAktiv() const { return aktiv; } TriggerRun::TriggerRun( Trigger *trig, Ereignis *e, Spiel *zSpiel ) : ReferenceCounter() { trigger = trig; ereignis = e; this->zSpiel = zSpiel; waitCount = 0; } TriggerRun::~TriggerRun() { trigger->release(); ereignis->release(); } // gibt 0 zurück, wenn der Auslöser vollständig durchgelaufen ist bool TriggerRun::runNext( double t ) { if( waitCount > 0 ) waitCount -= t; else { int current = counter.currentPosition(); if( current >= trigger->getAktionAnzahl() ) return 0; Aktion *ak = trigger->zAktion( current ); if( !ak || ak->runNext( zSpiel, ereignis, &localMem, &counter, waitCount ) ) counter.count(); if( counter.currentPosition() >= trigger->getAktionAnzahl() ) return 0; } return 1; } Trigger *TriggerRun::getTrigger() const { return dynamic_cast( trigger->getThis() ); }