JNR
aiAgent.cpp
1 /*
2 
3 Jump'n'Run Engine
4 http://www.atanaslaskov.com/jnr/
5 
6 BSD LICENSE
7 Copyright (c) 2007-2013, Atanas Laskov
8 All rights reserved.
9 
10 Redistribution and use in source and binary forms, with or without
11 modification, are permitted provided that the following conditions are met:
12 1. Redistributions of source code must retain the above copyright notice,
13 this list of conditions and the following disclaimer.
14 2. Redistributions in binary form must reproduce the above copyright notice,
15 this list of conditions and the following disclaimer in the documentation
16 and/or other materials provided with the distribution.
17 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 DISCLAIMED. IN NO EVENT SHALL ATANAS LASKOV BE LIABLE FOR ANY
21 DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 
28 */
29 
30 #include "stdafx.h"
31 #include "..\ai.h"
32 
33 
34 // Constructor
35 //
36 aiAgent::aiAgent()
37 {
38  // Object types this abstract factory can create
39  //
45 
47  REGISTER_CLASS( aiUpgradeTerminalState );
48 
50 
51  //
52  _bActive = M_FALSE;
53  _bInitialized = M_FALSE;
54 
55  _self = _player = NULL;
56  _perceptsGlobal = NULL;
57 
58  _strCurrentState = std::string("");
59  _pCurrentState = NULL; // Nil at first; Must be specified explicitly
60 }
61 
62 // Set controller objects
63 //
64 void aiAgent::controllers(aiController* pSelf, aiController *pPlayer, aiPercepts* pGlobalPercepts)
65 {
66  _self = pSelf;
67  _player = pPlayer;
68  _perceptsGlobal = pGlobalPercepts;
69 
70  //All states must be updated
71  //
72  std::map<std::string, aiAgentState*>::iterator i;
73 
74  for(i=_vStates.begin(); i!=_vStates.end(); i++)
75  {
76  i->second->_self = _self;
77  i->second->_player = _player;
78  }
79 }
80 
81 // State management
82 //
83 void aiAgent::add(std::string id, aiAgentState* pState) //Add state
84 {
85  //Ensure it's unique
86  ASSERT( _vStates.find(id)==_vStates.end(), "State ID already registered", id.c_str() );
87 
88  //Register state
89  _vStates[id] = pState;
90 
91  //Set internal pointers
92  _vStates[id]->_self = _self;
93  _vStates[id]->_player = _player;
94  _vStates[id]->_agent = this;
95 }
96 
97 void aiAgent::state(std::string id) // Set current state
98 {
99  //Ensure state exists
100  ASSERT( _vStates.find(id)!=_vStates.end(), "State ID is not registered", id.c_str() );
101 
102  //Sent activate/deactivate events
103  if( id != _strCurrentState )
104  {
105  _vStates[id]->perceive_active( _strCurrentState );
106  if(_pCurrentState) _pCurrentState->perceive_inactive( id );
107  }
108 
109  //Change state
110  _strCurrentState = id;
111  _pCurrentState = _vStates[_strCurrentState];
112 }
113 
114 // Load aiAgent form file
115 // The function reads up a list of aiAgentState identifiers,
116 // creates an appropriate aiAgent state object for each one
117 // and registers them with aiAgent::add()
118 //
119 void aiAgent::load(laFileParser *fp)
120 {
121  char strState_Name[128], strState_Class[128];
122  while(1)
123  {
124  fp->readSectionSeparator(strState_Name);
125 
126  if( strstr(strState_Name, "START") )
127  {
128  // Initial state
129  //
130  fp->readText(strState_Name);
131  ASSERT( _vStates.find(std::string(strState_Name))!=_vStates.end(),
132  "State ID=%s is not registered", strState_Name );
133 
134  _pCurrentState = _vStates[strState_Name];
135  _strCurrentState = std::string(strState_Name);
136  _bInitialized = M_FALSE;
137  //state(strState_Name);
138  return;
139  }
140  else
141  {
142  // Read state ID
143  fp->readText(strState_Class);
144 
145  //Instantiate
146  aiAgentState *pState = (aiAgentState*) instantiate(strState_Class);
147  fp->readObj(pState, M_FALSE);
148 
149  // Add state to the list
150  add(strState_Name, pState);
151  }
152 
153  }
154 }
155 
156 // Clear percepts
157 // NOTE: This call should be made after every simulation step,
158 // otherwise old percepts will accumulate
159 //
160 void aiAgent::perceptsClear()
161 {
162  _percepts.clear();
163 }
164 
165 // Set a new percept
166 //
167 void aiAgent::perceive(unsigned id, aiPerceptData data)
168 {
169  _percepts[id] = data;
170 }
171 
172 // Execute a discrete step of the AI agent,
173 // This function calls all the percept handlers
174 //
175 void aiAgent::execute(class laTimer *pt)
176 {
177  ERRORLEVEL_BEGIN;
178  ASSERT( _self && _player && _perceptsGlobal, "Controller objects are nil.");
179  ASSERT(_pCurrentState, "Current state is nil.");
180 
181  // initial state
182  if(!_bInitialized)
183  {
184  _pCurrentState->perceive_active( _strCurrentState );
185  _bInitialized = M_TRUE;
186  }
187 
188  // Dispatch local and global percepts to the active aiAgentState
189  _percepts.dispatch( _pCurrentState, M_FALSE );
190  _perceptsGlobal->dispatch( _pCurrentState, M_TRUE );
191 
192  ERRORLEVEL_END;
193 }
Single state of the AI-controlled creature.
Definition: aiAgentState.h:48
Flying creature behaviour.
laNamedClass * instantiate(std::string strClassName)
Instantiate class by name.
Crawling creature behaviour.
Ramble state.
Class aiController is an abstract class for behaviours which can be performed by objects.
Definition: aiController.h:41
Lava-jumper creature behaviour.
#define REGISTER_CLASS(class_name)
Handy macro for registering named class prototype.
Active (interactive) object.
File Parser.
Definition: laFileParser.h:41