📄 aipemotion.h
字号:
//**********************************************************************
// aipEmotion.h - Emotion - a kind of running sum of goodness.
//
// Provides: aipEmotion aipFear aipGreed aipCuriosity aipHope
//
// This header file declares classes to implement the Emotion
// AI pattern.
//
// See www.aipatterns.org (or www.agt.net/public/bmarshal/aipatterns)
// for information on Emotion AI pattern.
//
// An emotion has a set of aspects.
//
// Copyright (c) 2005, 2008 Brian Marshall
//
// See the license at end of this file.
//
// Developers/Contributers:
// [BRM] Brian Marshall - Calgary - bmarshal@agt.net
//
// 08/06/16 [BRM] removed delete_aspect() and delete_emotion();
// small changes for portability
// 05/11/14 [BRM] simplified base class aipCompEmotion
// aipHope::weaken(), strengthen(), set_g()
// removed and default to those from aipCompEmotion
// aipHope::weaken_fear(), strengthen_greed(), etc.
// have been removed
// made const: aipHope::greed(), fear(), curiosity()
// 05/10/24 [BRM] made emotion slowly_degrade optional
// simplified set_g() and reset()
// added floor() and ceiling() functions
// removed public non-const access to hope components
// 05/08/17 [BRM] Development begins.
//
//----------------------------------------------------------------------
// Notes
//
// Calling a 'weaken' function on a (non-compound) emotion will
// never turn a value that is not aipNeutral to aipNeutral.
//
// If set_g(), weaken() or strengthen() are used with compound
// emotions, they have to be overriden. The best way to use
// compound-emotions, including aipHope, is to attach aspects
// to the emotion-aspects. For example, a subclass of aipAspect
// can be added to the fear in aipHope, with the code to affect
// that fear in the take_msg() function of the aspect.
//
//----------------------------------------------------------------------
#ifndef aipEmotion_h_guard
#define aipEmotion_h_guard
#include "aipPandemonium.h"
//----------------------------------------------------------------------
// Classes. Sub-classing is shown by indentation.
// class aipG is a typedef for aipGoodness
// class aipBase; ( in aipBase.h )
// class aipDemon; ( in aipPandemonium.h )
class aipAspect; // Aspect affecting an emotion
class aipEmotion; // Kind of running sum of goodness
class aipPosEmotion; // Positive emotion
class aipGreed; // Wanting a known good
class aipCuriosity; // Interested in potiential good
class aipNegEmotion; // Negative emotion
class aipFear; // Wanting to avoid a known bad
class aipCompEmotion; // Compound emotion
class aipHope; // Fear + Greed + Curiosity
// class aipDemonItr; ( in aipPandemonium.h )
class aipAspectItr; // Aspect Iterator
class aipEmotionItr; // Emotion Iterator
//----------------------------------------------------------------------
// Constants
// From aipBase.h -
// long Intensity Constants (for function arguments)...
// aipIntensity_None aipIntensity_Slightly
// aipIntensity_A_Little aipIntensity_Somewhat
// aipIntensity_A_Fair_Bit aipIntensity_Quite_A_Bit
// aipIntensity_A_Lot
//
//======================================================================
// aipAspect - an aspect that affects an emotion
class aipAspect : public aipDemon {
aipEmotion * m_owner_emotion;
public:
aipAspect () { m_owner_emotion = 0; }
virtual ~aipAspect () {}
void set_owner_emotion (aipEmotion *x) { m_owner_emotion = x; }
aipEmotion * emotion () const { return m_owner_emotion; }
virtual void take_msg (aipMsg *m) {}
};
//======================================================================
// aipEmotion - an abstract base class.
//
// The heart of an emotion is m_g, a goodness that changes as a
// result of calls to strengthen() or weaken(),
// or as a result of calls to take_msg(), which:
// - calls pre_msg_behavior()
// - calls take_msg() for each aspect of the emotion
// - calls post_msg_behavior()
//
// Subclasses can override pre_msg_behavior() and post_msg_behavior().
// Instances of subclasses can have aspects added to them.
// Subclasses should, in general, NOT override take_msg()
class aipEmotion : public aipAspect {
aipG m_g; // current emotion goodness
aipPandemonium * m_aspects; // aspects that affect m_g
aipG m_g_before_take_msg; // m_g before take_msg() is called.
aipG m_g_before_prev_msg; // m_g before take_msg() is called.
int m_should_slowly_degrade; // 0 = no
protected:
aipG g_before_take_msg () const { return m_g_before_take_msg; }
aipG g_before_prev_msg () const { return m_g_before_prev_msg; }
virtual void pre_msg_behavior (aipMsg *m =0) {}
virtual void slowly_degrade ();
virtual void post_msg_behavior (aipMsg *m =0) {
if (m_should_slowly_degrade) slowly_degrade();
}
aipPandemonium * aspect_pandemonium() const { // for iterators
return m_aspects;
}
public:
aipEmotion ();
virtual ~aipEmotion ();
void add_aspect (aipAspect *x);
void enable_slowly_degrade () { m_should_slowly_degrade = 1; }
void disable_slowly_degrade () { m_should_slowly_degrade = 0; }
virtual void dump_to_ptr (char *p) const; // used for debugging
aipAspectItr aspect_iterator() const;
virtual void set_g (aipG x);
virtual aipG g() const { return m_g; }
virtual void take_msg (aipMsg *m);
virtual void strengthen (long intensity_constant) =0;
virtual void weaken (long intensity_constant) =0;
void floor (aipG x);
void ceiling (aipG x);
virtual void reset (aipG x =aipNeutral);
};
//======================================================================
// Basic-classes: aipPosEmotion, aipNegEmotion, aipCompEmotion
//
// aipPosEmotion and aipNegEmotion are generally used as base-classes
// although they can be used as-is if desired.
//
// aipCompEmotion is generally a base class, and set_g()
// is generally be overridden.
//
//----------------------------------------------------------------------
// aipPosEmotion - emotion where goodness is Neutral or Positive
class aipPosEmotion : public aipEmotion {
public:
aipPosEmotion () {}
virtual ~aipPosEmotion () {}
virtual void set_g (aipG x);
virtual void strengthen (long intensity_constant);
virtual void weaken (long intensity_constant);
};
//----------------------------------------------------------------------
// aipNegEmotion - emotion where goodness is Neutral or Negative
class aipNegEmotion : public aipEmotion {
public:
aipNegEmotion () {}
virtual ~aipNegEmotion () {}
virtual void set_g (aipG x);
virtual void strengthen (long intensity_constant);
virtual void weaken (long intensity_constant);
};
//----------------------------------------------------------------------
// aipCompEmotion - compond emotion - aspects are emotions
//
// Emotions are composites (they descend from aipAspect).
// aipCompEmotion is used to create emotions where the aspects
// are other emotions. It provides these behaviors:
// - calc_compound() calculates the goodness - default is:
// the sum of the goodness of the aspect-emotions
// - set_g(aipNeutral) sets all aspect-emotions to aipNeutral
// by default, any other argument has no effect
//
// - post_msg_behavior(), called by take_msg(),
// calls calc_compound().
//
// set_g() must be overridden for any value except aipNeutral.
//
// weaken() and strengthen() must be overriden to do anything.
//
// set_g() and calc_compound() may be overriden to make them
// faster - knowing the components instead of the default
// implementation that uses iterators.
class aipCompEmotion : public aipEmotion {
protected:
void calc_compound();
virtual void post_msg_behavior (aipMsg *m =0);
public:
aipCompEmotion () {}
virtual ~aipCompEmotion () {}
void add_aspect (aipAspect *x) {} // use add_emotion
void add_emotion (aipEmotion *x);
aipEmotionItr emotion_iterator() const;
// any of the following functions that are used
// should be overriden (except set_g(aipNeutral) works)
virtual void set_g (aipG x); // probably override this
virtual void strengthen (long intensity_constant) {}
virtual void weaken (long intensity_constant) {}
};
//======================================================================
// aipFear, aipGreed, aipCuriosity, aipHope
//
//----------------------------------------------------------------------
// aipFear - how bad something might be.
class aipFear : public aipNegEmotion {
public:
aipFear () {}
virtual ~aipFear () {}
virtual void dump_to_ptr (char *p) const; // used for debugging
};
//----------------------------------------------------------------------
// aipGreed - how good something is known to be.
class aipGreed : public aipPosEmotion {
public:
aipGreed () {}
virtual ~aipGreed () {}
virtual void dump_to_ptr (char *p) const; // used for debugging
};
//----------------------------------------------------------------------
// aipCuriosity - how good something unknown might be.
class aipCuriosity : public aipPosEmotion {
public:
aipCuriosity () {}
virtual ~aipCuriosity () {}
virtual void dump_to_ptr (char *p) const; // used for debugging
};
//----------------------------------------------------------------------
// aipHope - Fear plus Greed plus Curiosity - the feeling about
// whether things are going to work out well.
//
// The behavior is simplistic in this class. Subclasses may
// define pre_msg_behavior() and post_msg_behavior() that considers
// application-specific aspects.
class aipHope : public aipCompEmotion {
aipFear * m_fear;
aipGreed * m_greed;
aipCuriosity * m_curiosity;
protected:
void calc_compound () {
if (m_fear && m_greed && m_curiosity) {
aipEmotion::set_g (
m_fear->g() + m_greed->g() + m_curiosity->g() );
}
}
virtual void post_msg_behavior (aipMsg *m =0);
public:
aipHope ();
virtual ~aipHope () {}
void enable_slowly_degrade ();
void disable_slowly_degrade ();
virtual void dump_to_ptr (char *p) const; // used for debugging
aipFear * fear () const { return m_fear; }
aipGreed * greed () const { return m_greed; }
aipCuriosity * curiosity () const { return m_curiosity; }
virtual void set_g (aipG x);
virtual void set_fear (aipG x);
virtual void set_greed (aipG x);
virtual void set_curiosity (aipG x);
};
//======================================================================
// Aspect Iterators
//
//----------------------------------------------------------------------
// aipAspectItr - Iterator for aspects in a pandemonium
class aipAspectItr : public aipDemonItr {
public:
aipAspectItr () {}
aipAspectItr (aipPandemonium *p) {
set_demon_itr (p,0);
}
aipAspectItr (const aipAspectItr& x) {
set_demon_itr (x.pandemonium(), x.current());
}
virtual ~aipAspectItr () {}
aipAspectItr& operator = (const aipAspectItr& x) {
set_demon_itr (x.pandemonium(), x.current());
return *this;
}
aipAspect * first() { return (aipAspect*)aipDemonItr::first(); }
aipAspect * next() { return (aipAspect*)aipDemonItr::next(); }
};
//----------------------------------------------------------------------
// aipEmotionItr - Iterator for emotion in a pandemonium
class aipEmotionItr : public aipDemonItr {
public:
aipEmotionItr () {}
aipEmotionItr (aipPandemonium *p) {
set_demon_itr(p,0);
}
aipEmotionItr (const aipEmotionItr& x) {
set_demon_itr (x.pandemonium(), x.current());
}
virtual ~aipEmotionItr () {}
aipEmotionItr& operator = (const aipEmotionItr& x) {
set_demon_itr (x.pandemonium(), x.current());
return *this;
}
aipEmotion * first() { return (aipEmotion*)aipDemonItr::first(); }
aipEmotion * next() { return (aipEmotion*)aipDemonItr::next(); }
};
//======================================================================
#endif
//======================================================================
// License
//
// Permission is hereby granted, free of charge, to any
// person obtaining a copy of this software and associated
// documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to
// whom the Software is furnished to do so, subject to the
// following conditions:
//
// The copyright notice and this license shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
//**********************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -