1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 //===================================================================
22 #include "nel/misc/debug.h"
24 #include "game_share/xml.h"
26 #include "ai_manager.h"
27 #include "ai_service.h"
30 //===================================================================
32 //---------------------------------------------------
33 // INSTANTIATED CLASS: Public methods
36 // a few read accessors (static properties)
38 // the manager id (0..255)
39 sint
CAIManager::id() const
41 return int(this-_managers
);
43 // the manager name .. ie the source file name minus extension
44 const std::string
&CAIManager::name() const
49 // the CPU load rating of the manager for auto-load ballancing purposes
50 uint
CAIManager::weightCPU() const
54 // the RAM load rating of the manager for auto-load ballancing purposes
55 uint
CAIManager::weightRAM() const
62 // a few read accessors (state of the files on disk)
64 // indicates whether newer source files than object files have been located
65 bool CAIManager::needCompile() const
69 // indicate whether an object file has been located in the object directory
70 bool CAIManager::objExists() const
77 // a few read accessors (relating to assignment to & execution by an ai service)
79 // has the manager been opened (it may still be waiting to be assigned)
80 bool CAIManager::isOpen() const
84 // has the manager been assigned to a service
85 bool CAIManager::isAssigned() const
89 // is the manager up and running on the assigned service
90 bool CAIManager::isUp() const
95 // the id of the service to which the manager is assigned
96 sint
CAIManager::serviceId() const
103 // a few basic actions (relating to disk files)
105 const std::string
&xmlDelimitedString(CxmlNode
*xmlNode
,const std::string
&delimiter
)
107 static const std::string emptyString
;
109 for (uint i
=0;i
<xmlNode
->childCount();++i
)
111 CxmlNode
*child
=xmlNode
->child(i
);
112 if (child
->type()==delimiter
)
113 if (child
->childCount()==1)
114 if (child
->child(0)->type()=="")
116 return child
->child(0)->txt();
123 const std::string
&getProp(CxmlNode
*xmlNode
,const std::string
&propertyName
)
125 static const std::string emptyString
;
127 for (uint i
=0;i
<xmlNode
->childCount();++i
)
129 CxmlNode
*child
=xmlNode
->child(i
);
130 if (child
->type()=="PROPERTY")
132 const std::string
&name
= xmlDelimitedString(child
,std::string("NAME"));
133 if (name
==propertyName
)
134 return xmlDelimitedString(child
,std::string("STRING"));
140 // compile the source files to generate new object files
141 void CAIManager::compile()
143 std::string srcFile
=CAIFiles::fullSrcFileName(id());
144 std::string objFile
=CAIFiles::fullObjFileName(id());
145 nlinfo("Compile %s => %s",srcFile
.c_str(),objFile
.c_str());
147 // open and parse the xml file
149 xmlfile
.read(srcFile
);
151 // locate the mgr node in the file
152 std::list
<CxmlNode
*> nodes
;
153 nodes
.push_back(&xmlfile
);
154 while (!nodes
.empty())
156 // pop the next node off the list
157 CxmlNode
*node
=*nodes
.begin();
160 // push our children so that they can be treated too
161 for (uint i
=0;i
<node
->childCount();++i
)
162 nodes
.push_back(node
->child(i
));
164 // if this is a child node then we're in business so dump a few infos to the screen
165 if (node
->type()=="CHILD" && !getProp(node
,std::string("AI_TYPE")).empty())
167 nlinfo("child: AI_TYPE: %s NAME: %s",getProp(node
,std::string("AI_TYPE")).c_str(),getProp(node
,std::string("Name")).c_str());
172 // delete the object files (but not the save files)
173 void CAIManager::clean()
175 CAIFiles::clean(id());
180 // a few basic actions (relating to assignment to & execution by an ai service)
182 // open the manager on an unspecified service
183 // (may be queued until a service is available)
184 void CAIManager::open()
186 CAIService::openMgr(id());
189 // assign manager to a specified service and begin execution
190 void CAIManager::assign(sint serviceId
)
192 // make sure that the manager isn't assigned to a service already
195 nlwarning("Cannot assign manager %04d (%s) to service %d as already assigned to %d",
196 id(), name(), serviceId
, _service
);
200 // flag me as assigned
204 // transfer control to the service's assignMgr() method
205 CAIService
*service
=CAIService::getServiceById(serviceId
);
207 service
->assignMgr(id());
210 // stop execution on the current service and assign to a new service
211 void CAIManager::reassign(sint serviceId
)
213 CAIService
*service
=CAIService::getServiceById(_service
);
215 service
->reassignMgr(id(),serviceId
);
218 // stop execution of a manager
219 void CAIManager::close()
221 // make sure that the manager isn't assigned to a service already
224 nlwarning("Cannot unassign manager %04d (%s) as it is already unassigned", id(), name());
228 // if the service is running then transfer control to the service singleton's closeMgr() method
231 CAIService::closeMgr(id());
235 // flag me as unassigned
243 // a few basic actions (miscelaneous)
245 // display information about the state of the manager
246 void CAIManager::display() const
249 nlinfo("AI Manager %04d: %s: %s ON SERVICE %d (%s)", id(), _name
.c_str(),
250 isUp()? "UP AND RUNNING":
251 /* else */ "ASSIGNED TO BUT NOT YET UP",
253 isOpen()? "auto-assigned":
254 /* else */ "manualy assigned"
257 nlinfo("AI Manager %04d: %s: %s", id(), _name
.c_str(),
258 isOpen()? "OPEN - AWAITING ASSIGNMENT":
259 !objExists()? "NOT OPEN - OBJECT FILE NOT FOUND":
260 needCompile()? "NOT OPEN - OBJECT FILE OLDER THAN SOURCE":
261 /* else */ "NOT OPEN - OBJECT FILE IS UP TO DATE"
267 // a few write accessors (miscelaneous)
269 // set the name assigned to manager
270 // if no name previously assigned then reset all manager properties
271 // if a name already exists and does not match new name then do nohing and return false
272 bool CAIManager::set(const std::string
&name
)
274 // if we already have a name associated with this slot then simply check that it matches the new name
276 return (_name
==name
);
282 // set the state of the needCompile flag
283 void CAIManager::setNeedCompile(bool val
)
288 // set the state of the objFileExists flag
289 void CAIManager::setObjFileExists(bool val
)
294 // set the state of the isUp flag
295 void CAIManager::setIsUp(bool val
)
300 // set the state of the isOpen flag
301 void CAIManager::setIsOpen(bool val
)
307 //---------------------------------------------------
308 // INSTANTIATED CLASS: Private methods
310 // default constructor - may only be instantiated by the singleton
311 CAIManager::CAIManager()
313 // manager id - make sure that the managers are all in the one static array
314 // note that id is calaulated from the array address and the addess of 'this'
315 nlassert(uint(id())<maxManagers());
316 // reset the rest of the properties
320 void CAIManager::_reset()
325 _needCompile
= false;
334 //===================================================================
335 // *** END OF THE INSTANTIATED CLASS *** START OF THE SINGLETON ***
336 //===================================================================
339 //---------------------------------------------------
342 class CAIManager
CAIManager::_managers
[RYAI_AI_MANAGER_MAX_MANAGERS
];
345 //---------------------------------------------------
346 // SINGLETON: Public methods
348 // get the number of allocated managers
349 uint
CAIManager::numManagers()
352 for (uint i
=0;i
<maxManagers();i
++)
353 if (!_managers
[i
]._name
.empty())
358 // get a pointer to the manager with given handle (0..maxManagers-1)
359 CAIManager
*CAIManager::getManagerById(sint id
)
361 if (uint(id
)>=maxManagers())
363 nlwarning("CAIManager::getManagerById(id): id %d not in range 0..%d",id
,maxManagers()-1);
366 return &(_managers
[id
]);
369 // get a pointer to the manager with given index (0..numManagers-1)
370 CAIManager
*CAIManager::getManagerByIdx(uint idx
)
373 for (uint i
=0;i
<maxManagers();i
++)
374 if (!_managers
[i
]._name
.empty())
377 return &(_managers
[i
]);
380 nlwarning("CAIManager::getManagerByIdx(idx): idx (%d)>=numManagers (%d)",idx
,count
);
384 // get the handle for the manager of given name and optionally create a new
385 // handle if none found - return -1 if none found or no free slots
386 int CAIManager::nameToId(std::string name
, bool assignNewIfNotFound
)
388 // see if the name is a numeric version of an id
389 uint val
=atoi(name
.c_str());
390 if (!name
.empty() && name
.size()<=4 &&
391 ( (val
>0 && val
<maxManagers()) ||
392 (val
==0 && name
==std::string("0000"+4-name
.size())) ) )
395 // see if the name is already assigned to one of the _managers
396 for (uint i
=0;i
<maxManagers();i
++)
397 if (_managers
[i
]._name
==name
)
400 // the name's not been found so if assignNewIfNotFound then look for a free slot
401 if (assignNewIfNotFound
)
403 for (uint i
=0;i
<maxManagers();i
++)
404 if (_managers
[i
]._name
.empty())
406 _managers
[i
].set(name
);
409 nlwarning("Failed to allocate a manager for name '%s' (all %d managers are already allocated)",name
.c_str(),maxManagers());
414 // clear file name assignments for managers that aren't currently running on
416 void CAIManager::liberateUnassignedManagers()
418 for (uint i
=0;i
<maxManagers();i
++)
419 if (!_managers
[i
]._isOpen
&& !_managers
[i
]._isAssigned
)
420 _managers
[i
]._reset();
424 //===================================================================