Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

191 lines
7.4 KiB

  1. // NextBotIntentionInterface.h
  2. // Interface for intentional thinking
  3. // Author: Michael Booth, April 2005
  4. // Copyright (c) 2005 Turtle Rock Studios, Inc. - All Rights Reserved
  5. #ifndef _NEXT_BOT_INTENTION_INTERFACE_H_
  6. #define _NEXT_BOT_INTENTION_INTERFACE_H_
  7. #include "NextBotComponentInterface.h"
  8. #include "NextBotContextualQueryInterface.h"
  9. class INextBot;
  10. //
  11. // Insert this macro in your INextBot-derived class declaration to
  12. // create a IIntention-derived class that handles the bookkeeping
  13. // of instantiating a Behavior with an initial Action and updating it.
  14. //
  15. #define DECLARE_INTENTION_INTERFACE( Actor ) \
  16. \
  17. class Actor##Intention : public IIntention \
  18. { \
  19. public: \
  20. Actor##Intention( Actor *me ); \
  21. virtual ~Actor##Intention(); \
  22. virtual void Reset( void ); \
  23. virtual void Update( void ); \
  24. virtual INextBotEventResponder *FirstContainedResponder( void ) const { return m_behavior; } \
  25. virtual INextBotEventResponder *NextContainedResponder( INextBotEventResponder *current ) const { return NULL; } \
  26. private: \
  27. Behavior< Actor > *m_behavior; \
  28. }; \
  29. \
  30. public: virtual IIntention *GetIntentionInterface( void ) const { return m_intention; } \
  31. private: Actor##Intention *m_intention; \
  32. public:
  33. //
  34. // Use this macro to create the implementation code for the IIntention-derived class
  35. // declared above. Since this requires InitialAction, it must occur after
  36. // that Action has been declared, so it can be new'd here.
  37. //
  38. #define IMPLEMENT_INTENTION_INTERFACE( Actor, InitialAction ) \
  39. Actor::Actor##Intention::Actor##Intention( Actor *me ) : IIntention( me ) { m_behavior = new Behavior< Actor >( new InitialAction ); } \
  40. Actor::Actor##Intention::~Actor##Intention() { delete m_behavior; } \
  41. void Actor::Actor##Intention::Reset( void ) { delete m_behavior; m_behavior = new Behavior< Actor >( new InitialAction ); } \
  42. void Actor::Actor##Intention::Update( void ) { m_behavior->Update( static_cast< Actor * >( GetBot() ), GetUpdateInterval() ); }
  43. //
  44. // Use this macro in the constructor of your bot to allocate the IIntention-derived class
  45. //
  46. #define ALLOCATE_INTENTION_INTERFACE( Actor ) { m_intention = new Actor##Intention( this ); }
  47. //
  48. // Use this macro in the destructor of your bot to deallocate the IIntention-derived class
  49. //
  50. #define DEALLOCATE_INTENTION_INTERFACE { if ( m_intention ) delete m_intention; }
  51. //----------------------------------------------------------------------------------------------------------------
  52. /**
  53. * The interface for intentional thinking.
  54. * The assumption is that this is a container for one or more concurrent Behaviors.
  55. * The "primary" Behavior is the FirstContainedResponder, and so on.
  56. * IContextualQuery requests are prioritized in contained responder order, such that the first responder
  57. * that returns a definitive answer is accepted. WITHIN a given responder (ie: a Behavior), the deepest child
  58. * Behavior in the active stack is asked first, then its parent, and so on, allowing the most specific active
  59. * Behavior to override the query responses of its more general parent Behaviors.
  60. */
  61. class IIntention : public INextBotComponent, public IContextualQuery
  62. {
  63. public:
  64. IIntention( INextBot *bot ) : INextBotComponent( bot ) { }
  65. virtual ~IIntention() { }
  66. virtual void Reset( void ) { INextBotComponent::Reset(); } // reset to initial state
  67. virtual void Update( void ) { } // update internal state
  68. // IContextualQuery propagation --------------------------------
  69. virtual QueryResultType ShouldPickUp( const INextBot *me, CBaseEntity *item ) const; // if the desired item was available right now, should we pick it up?
  70. virtual QueryResultType ShouldHurry( const INextBot *me ) const; // are we in a hurry?
  71. virtual QueryResultType ShouldRetreat( const INextBot *me ) const; // is it time to retreat?
  72. virtual QueryResultType IsHindrance( const INextBot *me, CBaseEntity *blocker ) const; // return true if we should wait for 'blocker' that is across our path somewhere up ahead.
  73. virtual Vector SelectTargetPoint( const INextBot *me, const CBaseCombatCharacter *subject ) const; // given a subject, return the world space position we should aim at
  74. virtual QueryResultType IsPositionAllowed( const INextBot *me, const Vector &pos ) const; // is the a place we can be?
  75. virtual const CKnownEntity * SelectMoreDangerousThreat( const INextBot *me,
  76. const CBaseCombatCharacter *subject, // the subject of the danger
  77. const CKnownEntity *threat1,
  78. const CKnownEntity *threat2 ) const; // return the more dangerous of the two threats, or NULL if we have no opinion
  79. // NOTE: As further queries are added, update the Behavior class to propagate them
  80. };
  81. inline QueryResultType IIntention::ShouldPickUp( const INextBot *me, CBaseEntity *item ) const
  82. {
  83. for ( INextBotEventResponder *sub = FirstContainedResponder(); sub; sub = NextContainedResponder( sub ) )
  84. {
  85. const IContextualQuery *query = dynamic_cast< const IContextualQuery * >( sub );
  86. if ( query )
  87. {
  88. // return the response of the first responder that gives a definitive answer
  89. QueryResultType result = query->ShouldPickUp( me, item );
  90. if ( result != ANSWER_UNDEFINED )
  91. {
  92. return result;
  93. }
  94. }
  95. }
  96. return ANSWER_UNDEFINED;
  97. }
  98. inline QueryResultType IIntention::ShouldHurry( const INextBot *me ) const
  99. {
  100. for ( INextBotEventResponder *sub = FirstContainedResponder(); sub; sub = NextContainedResponder( sub ) )
  101. {
  102. const IContextualQuery *query = dynamic_cast< const IContextualQuery * >( sub );
  103. if ( query )
  104. {
  105. // return the response of the first responder that gives a definitive answer
  106. QueryResultType result = query->ShouldHurry( me );
  107. if ( result != ANSWER_UNDEFINED )
  108. {
  109. return result;
  110. }
  111. }
  112. }
  113. return ANSWER_UNDEFINED;
  114. }
  115. inline QueryResultType IIntention::ShouldRetreat( const INextBot *me ) const
  116. {
  117. for ( INextBotEventResponder *sub = FirstContainedResponder(); sub; sub = NextContainedResponder( sub ) )
  118. {
  119. const IContextualQuery *query = dynamic_cast< const IContextualQuery * >( sub );
  120. if ( query )
  121. {
  122. // return the response of the first responder that gives a definitive answer
  123. QueryResultType result = query->ShouldRetreat( me );
  124. if ( result != ANSWER_UNDEFINED )
  125. {
  126. return result;
  127. }
  128. }
  129. }
  130. return ANSWER_UNDEFINED;
  131. }
  132. inline QueryResultType IIntention::IsHindrance( const INextBot *me, CBaseEntity *blocker ) const
  133. {
  134. for ( INextBotEventResponder *sub = FirstContainedResponder(); sub; sub = NextContainedResponder( sub ) )
  135. {
  136. const IContextualQuery *query = dynamic_cast< const IContextualQuery * >( sub );
  137. if ( query )
  138. {
  139. // return the response of the first responder that gives a definitive answer
  140. QueryResultType result = query->IsHindrance( me, blocker );
  141. if ( result != ANSWER_UNDEFINED )
  142. {
  143. return result;
  144. }
  145. }
  146. }
  147. return ANSWER_UNDEFINED;
  148. }
  149. inline QueryResultType IIntention::IsPositionAllowed( const INextBot *me, const Vector &pos ) const
  150. {
  151. for ( INextBotEventResponder *sub = FirstContainedResponder(); sub; sub = NextContainedResponder( sub ) )
  152. {
  153. const IContextualQuery *query = dynamic_cast< const IContextualQuery * >( sub );
  154. if ( query )
  155. {
  156. // return the response of the first responder that gives a definitive answer
  157. QueryResultType result = query->IsPositionAllowed( me, pos );
  158. if ( result != ANSWER_UNDEFINED )
  159. {
  160. return result;
  161. }
  162. }
  163. }
  164. return ANSWER_UNDEFINED;
  165. }
  166. #endif // _NEXT_BOT_INTENTION_INTERFACE_H_