/// @file behavior.hh /// @author Joshua Petitt /// @author Stefan Schmitt /// @version 1.0 /// @date 2003 /// /// Declares the abstract Behavior class. #ifndef BEHAVIOR_HH #define BEHAVIOR_HH #include "base/base.hh" #include "base/templates.hh" namespace EyeMind { class Behavior; //forward decl class State; //forward decl /// Connects Behaviors. /// /// A SignalLink connects two Behaviors and has an input Behavior and an output /// Behavior on its two terminals. SignalLinks come in two "flavors": generic /// and non-generic. Generic SignalLinks can be used to connect any Behaviors /// and carry signal data. Non-generic SignalLinks are /// subclasses of SignalLink and have to set the generic attribute to false in /// their constructor. These non-generic SignalLinks can carry any data, modify /// their data using functions, you name it. These non-generic SignalLinks /// cannot be connected to any Behavior, but only to certain Behaviors that can /// use these non-generic SignalLinks at their inputs resp. outputs. This /// non-generic SignalLink/Behavior relation is declared by the operator /// functions for << and >> (see example.hh). /// The data contained in the SignalLinks is buffered, i.e. the data is fed by /// the respective functions, then buffered and propagated by the Update() /// functions to the output and can then be read by the counterparts of theZZ /// feeding functions. The feeding functions are declared virtual to enable /// processing of this data (e.g. a step function) in derived classes. /// /// Note: The signal link only carries a single signal value, used for the /// excite signal, instead of two values, signal and excitation. JP Jul 12 2003 class SignalLink : public Updatable { // Connections to Behavior friend Behavior& SignalLinkOutputToBehavior(SignalLink& l, Behavior& o); friend Behavior& SignalLinkInputToBehavior(SignalLink& l, Behavior& i); friend SignalLink& BehaviorOutputToSignalLink(Behavior& n, SignalLink& o); friend SignalLink& BehaviorInputToSignalLink(Behavior& n, SignalLink& i); friend SignalLink* DisconnectBehaviors(Behavior& s, Behavior& t); // Connections to State friend State& SignalLinkOutputToState(SignalLink& l, State& o); friend State& SignalLinkInputToState(SignalLink& l, State& i); friend SignalLink& StateOutputToSignalLink(State& n, SignalLink& o); friend SignalLink& StateInputToSignalLink(State& n, SignalLink& i); private: int signal; ///< Current signal ( used by Excite() ). int next_signal; ///< Next signal value int Ks; ///< Signal gain int Bs; ///< Signal bias int decay; ///< Exponential decay term /// Should values only propagated by explicit Update() ? bool buffered; bool excite_on_update; ///< Excite out Behavior on Update? protected: Behavior *in; ///< Input Behavior of SignalLink. Behavior *out; ///< Output Behavior of SignalLink. bool updated; ///< Has new data been put into SignalLink? bool generic; ///< Is this a generic SignalLink? /// Reset in, out and internal data. void Null(); public: /// Default constructor; initalizes data members. SignalLink(); /// Virtual destructor. virtual ~SignalLink(); /// Propagates the data in the input buffers to the outputs. If a /// Behavior is attached at the out of the link, it is excited. If you /// want to call this function from the Update() function of derived /// classes, call it at the end of your function. virtual bool Update(); /// Reset the signal on the link back to zero void Reset(); /// Decay the signal on the link void Decay(); /// @name Data feeding functions; set update attribute to \c true //@{ virtual void Signal(int s); ///< Feeds a excitation signal. //@} /// @name Attribute manipulation functions //@{ Behavior* In(){ return in; } ///< Returns input Behavior. Behavior* Out(){ return out; } ///< Returns output Behavior. bool Updated(){ return updated; } ///< Has new data been fed? bool Generic(){ return generic; } ///< Is this Signal Link generic? int Signal(){ return signal+Bs; } ///< Returns current signal plus bias. void Invert(bool b){ Ks*=-1; } ///< Invert the signal void Gain(int k){ Ks = k; } ///< Set gain void Bias(int b){ Bs = b; } ///< Set bias void Decay(int d){ decay = d; } ///< Set decay //@} }; class Id; //forward declaration /// Number of input links in Behavior. const unsigned IN_SIGNAL_LIST_SIZE = 16; /// Number of output links in Behavior. const unsigned OUT_SIGNAL_LIST_SIZE = 16; /// Behavior abstract base class. Base class for deriving specific behavior /// objects. Each derived behavior must define its own virtual Execute() /// function and must be fully default-constructible. /// /// The behavior object is modeled like the Node class, which /// allows behaviors to be linked together in a list as well as have /// attached behaviors. The linked objects used for connecting behavior objects /// are of class SignalLink. These come in different "flavors" (see their /// declarations). Each behavior can use non-generic (i.e. specialized links /// carrying more data than excitation) as inputs and outputs, according to /// these rules: /// 1. Every Behavior must be able to do something with generic links /// 2. Only one type of non-generic link is allowed on either input or output /// /// The Behavior class Excite() function follows a simple set of rules: /// /// When the behavior is excited, the suppression value is subtracted /// from the excitation value. If the result is greater than the /// threshold value, then the Execute() function is executed. Each time the /// Execute() function is executed, the excitation value is decremented by /// an exaustion parameter and the suppression parameter is decreased by /// an emergence parameter. /// /// A Behavior also has an unsigned error flag and virtual OnError() /// procedure. By default the OnError() procedure clears the error flag. class Behavior : public Tagged { friend Behavior& SignalLinkOutputToBehavior(SignalLink& l, Behavior& o); friend Behavior& SignalLinkInputToBehavior(SignalLink& l, Behavior& i); friend SignalLink& BehaviorOutputToSignalLink(Behavior& n, SignalLink& o); friend SignalLink& BehaviorInputToSignalLink(Behavior& n, SignalLink& i); friend SignalLink* DisconnectBehaviors(Behavior& s, Behavior& t); friend Behavior& operator>>(Id& id, Behavior& b); private: bool active; ///< Denotes if the behavior is active. bool root; ///< Denotes if behavior is a 'root' behavior. bool excite_lock; ///< Locks Excite() function against recursion. int threshold; ///< Threshold value of the behavior. int feed_signal; ///< Signal to be fed to outlinks. float timebase;///< Timebase for exciting; 0 for explicit-only exciting. protected: /// List of attached incoming SignalLinks. Array inlinks; /// List of attached outgoing SignalLinks. Array outlinks; /// Error reference number. unsigned error; /// Function executed when behavior fires; returns an excitation /// signal value. virtual int Execute() = 0; /// Feed the SignalLink l with the appropriate data. To be called from /// the FeedAttached member function. Overload this function if you use /// non-generic links in your derived class and call this function as /// last instruction in the derived class's Feed function. virtual void Feed(SignalLink& l); /// Returns the sum of all the input signals int SumInputSignals(); /// Reset the incoming signal links void DecayInputSignals(); /// Returns the SignalLink with the highest excitation signal. SignalLink* FindMaxInputSignal(); /// Returns the SignalLink with the highest excitation signal among /// non-generic SignalLinks. SignalLink* FindMaxNonGenericInputSignal(); /// Classifies the excitation of the SignalLink. unsigned SignalRange(SignalLink& l); /// Is the excitation of the SignalLink in arbitrary range? bool InSignalRange(SignalLink& l, unsigned range); /// Reset the incoming signal links void ResetInputSignals(); /// Reset the outgoing signal links void ResetOutputSignals(); public: /// Default constructor; initializes data members. Behavior(); /// Virtual destructor. virtual ~Behavior(); /// Excite the behavior. Each time the behavior is excited it will add /// the excitation value to the current level of excitation.Then the /// suppression value is subtracted from the excitation value and if /// the total is greater than the threshold value, the behavior /// 'fires'. When firing the first thing that is done is execution of /// the Execute member function Then the excitation value is decreased /// by an exaustion parameter and the suppression is decreased by an /// emergence parameter. Finally the attached Behaviors on the /// excite_links list are excited and all the suppress_links are /// suppressed. /// /// @param signal Signal to be added to excitation. virtual void Excite(int signal); /// Loop through the outlinks and call Feed() for each. void FeedAttached(); /// @name Attribute manipulation functions /// For details on the parameters read and understand the Execite() /// functions's source. //@{ bool Active(){ return active; } ///< Is the behavior active? void Active(bool a){active = a; } ///< Activate/Deactivate behavior. /// Is the behavior attached directly to the Id? bool Root(){ return root; } /// Returns the execution treshold. int Threshold(){ return threshold; } /// Sets the execution treshold. void Threshold(int t){ threshold = t; } /// Return the excitation timebase. float Timebase(){ return timebase; } /// Sets the excitation timebase (call only once). void Timebase(float t); //@} int Error(){return error;} virtual void OnError(){error = 0;}; }; /// Connect SignalLink output with target Behavior. Behavior& operator>>(SignalLink& l, Behavior& o); /// Connect SignalLink input with source Behavior. Behavior& operator<<(SignalLink& l, Behavior& i); /// Add output SignalLink to Behavior. SignalLink& operator>>(Behavior& n, SignalLink& o); /// Add input SignalLink to Behavior. SignalLink& operator<<(Behavior& n, SignalLink& i); /// A synonym for DisconnectBehaviors(). SignalLink* operator|(Behavior& s, Behavior& t); /// Connect SignalLink output with target Behavior. /// @warning: Use this only if you exactly know what you are doing and for /// links that are already approved by some type-checking mechanism. Behavior& SignalLinkOutputToBehavior(SignalLink& l, Behavior& o); /// Connect SignalLink input with source Behavior. /// @warning: Use this only if you exactly know what you are doing and for /// links that are already approved by some type-checking mechanism. Behavior& SignalLinkInputToBehavior(SignalLink& l, Behavior& i); /// Add output SignalLink to Behavior. /// @warning: Use this only if you exactly know what you are doing and for /// links that are already approved by some type-checking mechanism. SignalLink& BehaviorOutputToSignalLink(Behavior& n, SignalLink& o); /// Add input SignalLink to Behavior. /// @warning: Use this only if you exactly know what you are doing and for /// links that are already approved by some type-checking mechanism. SignalLink& BehaviorInputToSignalLink(Behavior& n, SignalLink& i); /// Disconnect this Behavior from other Behavior. /// Note: The SignalLink object is not destroyed. /// @param s Source Behavior /// @param t Target Behavior to disconnect /// @returns Lingering SignalLink* on success, NULL else /// @warning Uses iteration, so not thread safe (see warning in templates.h) SignalLink* DisconnectBehaviors(Behavior& s, Behavior& t); /// @name Constants for excitation signal ranges //@{ const unsigned EXCITE_LOW_MIN = 1; const unsigned EXCITE_LOW_AVG = 4; const unsigned EXCITE_LOW_MAX = 16; const unsigned EXCITE_MED_MIN = 1001; const unsigned EXCITE_MED_AVG = 5000; const unsigned EXCITE_MED_MAX = 10000; const unsigned EXCITE_HI_MIN = 100001; const unsigned EXCITE_HI_AVG = 500000; const unsigned EXCITE_HI_MAX = 1000000; const unsigned EXCITE_NONE = 0; const unsigned EXCITE_IDLE = 1; const unsigned EXCITE_EXT = 1000000000; //@} /// @name Range classifiers for SignalRange() //@{ const unsigned EXCITE_RANGE_NONE = 0; const unsigned EXCITE_RANGE_LOW = 1; const unsigned EXCITE_RANGE_MED = 2; const unsigned EXCITE_RANGE_HI = 3; //@} /// Default Excite() signal for root behaviors, usually issued by Id. const int ROOT_DEFAULT_EXCITE = 1; }; // namespace EyeMind #endif // BEHAVIOR_HH