#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 ) { 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 ) { if( v->getName().istGleich( name ) ) return v->getVariable(); } return 0; } Variable* LocalMemory::zVariable( const char* name ) { for( auto v : vars ) { 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 ); } Aktion* Bedingung::zExpression() const { return expression; } 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 ) { 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()); }