Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / nel / src / logic / logic_condition.cpp
blobab6b22822a9b0e3a9f643e7569f0308758726445
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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.
8 //
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/>.
18 #include "stdlogic.h"
19 #include "nel/logic/logic_condition.h"
21 #include "nel/logic/logic_variable.h"
22 #include "nel/logic/logic_state_machine.h"
24 #include "nel/misc/o_xml.h"
26 using namespace NLMISC;
27 using namespace std;
29 namespace NLLOGIC
32 //-------------------------------------------------
33 // setLogicStateMachine :
35 //-------------------------------------------------
36 void CLogicComparisonBlock::setLogicStateMachine( CLogicStateMachine * logicStateMachine )
38 if( logicStateMachine == 0 )
40 nlwarning("(LOGIC)<CLogicComparisonBlock::setLogicStateMachine> The state machine is null");
42 else
44 _LogicStateMachine = logicStateMachine;
47 } // setLogicStateMachine //
50 //-------------------------------------------------
51 // testLogic :
53 //-------------------------------------------------
54 bool CLogicComparisonBlock::testLogic()
56 CLogicVariable var;
57 if( _LogicStateMachine->getVariable( VariableName, var ) == false )
59 nlwarning("(LOGIC)<CLogicComparisonBlock::testLogic> The variable %s is unknown in the state machine",VariableName.c_str());
60 return false;
63 if( Operator == "<" ) return ( var.getValue() < Comparand );
64 if( Operator == "<=" ) return ( var.getValue() <= Comparand );
65 if( Operator == ">" ) return ( var.getValue() > Comparand );
66 if( Operator == ">=" ) return ( var.getValue() >= Comparand );
67 if( Operator == "==" ) return ( var.getValue() == Comparand );
68 if( Operator == "!=" ) return ( var.getValue() != Comparand );
70 nlwarning("(LOGIC)<CLogicComparisonBlock::testLogic> The comparison block operator %s is unknown",Operator.c_str());
71 return false;
73 } // testLogic //
76 //-------------------------------------------------
77 // serial :
79 //-------------------------------------------------
80 /*void CLogicComparisonBlock::serial( IStream &f )
82 f.xmlPush("COMPARISON_BLOCK");
84 f.serial( VariableName );
85 f.serial( Operator );
86 f.serial( Comparand );
88 f.xmlPop();
90 } // serial //*/
92 void CLogicComparisonBlock::write (xmlNodePtr node) const
94 xmlNodePtr elmPtr = xmlNewChild ( node, NULL, (const xmlChar*)"COMPARISON_BLOCK", NULL);
95 xmlSetProp (elmPtr, (const xmlChar*)"VariableName", (const xmlChar*)VariableName.c_str());
96 xmlSetProp (elmPtr, (const xmlChar*)"Operator", (const xmlChar*)Operator.c_str());
97 xmlSetProp (elmPtr, (const xmlChar*)"Comparand", (const xmlChar*)toString(Comparand).c_str());
100 void CLogicComparisonBlock::read (xmlNodePtr node)
102 xmlCheckNodeName (node, "COMPARISON_BLOCK");
104 VariableName = getXMLProp (node, "VariableName");
105 Operator = getXMLProp (node, "Operator");
106 Comparand = atoiInt64(getXMLProp (node, "Comparand").c_str());
115 //-------------------------------------------------
116 // setLogicStateMachine :
118 //-------------------------------------------------
119 void CLogicConditionLogicBlock::setLogicStateMachine( CLogicStateMachine * logicStateMachine )
121 if( logicStateMachine == 0 )
123 nlwarning("(LOGIC)<CCLogicConditionLogicBlock::setLogicStateMachine> The state machine is null");
125 else
127 // set the state machine of this node
128 _LogicStateMachine = logicStateMachine;
130 // set the state machine of the logic block
131 ComparisonBlock.setLogicStateMachine( logicStateMachine );
134 } // setLogicStateMachine //
137 //-------------------------------------------------
138 // testLogic :
140 //-------------------------------------------------
141 bool CLogicConditionLogicBlock::testLogic()
143 switch( Type )
145 case NOT :
147 return true;
149 break;
151 case COMPARISON :
153 return ComparisonBlock.testLogic();
155 break;
157 case SUB_CONDITION :
159 CLogicCondition condition;
160 if( _LogicStateMachine->getCondition(SubCondition,condition) )
162 return condition.testLogic();
164 else
166 nlwarning("(LOGIC)<CLogicConditionLogicBlock::testLogic> The subcondition \"%s\" is unknown in the state machine \"%s\"",
167 SubCondition.c_str(),_LogicStateMachine->getName().c_str());
172 default :
173 nlerror("(LOGIC)<CLogicConditionLogicBlock::testLogic> logic block type %d is unknown",Type);
176 return false;
178 } // testLogic //
182 //-------------------------------------------------
183 // fillVarSet :
185 //-------------------------------------------------
186 void CLogicConditionLogicBlock::fillVarSet( set<string>& condVars )
188 if( Type == COMPARISON )
190 condVars.insert( ComparisonBlock.VariableName );
192 else
194 if( Type == SUB_CONDITION )
196 CLogicCondition condition;
197 if( _LogicStateMachine->getCondition(SubCondition,condition) )
199 condition.fillVarSet( condVars );
204 } // fillVarSet //
207 //-------------------------------------------------
208 // serial :
210 //-------------------------------------------------
211 /*void CLogicConditionLogicBlock::serial( IStream &f )
213 f.xmlPush("CONDITION_LOGIC_BLOCK");
215 f.serialEnum( Type );
216 switch( Type )
218 case NOT : break;
220 case COMPARISON :
222 f.serial( ComparisonBlock );
224 break;
226 case SUB_CONDITION :
228 f.serial( SubCondition );
230 break;
233 f.xmlPop();
234 };*/
236 void CLogicConditionLogicBlock::write (xmlNodePtr node) const
238 xmlNodePtr elmPtr = xmlNewChild ( node, NULL, (const xmlChar*)"CONDITION_LOGIC_NODE", NULL);
239 xmlSetProp (elmPtr, (const xmlChar*)"Type", (const xmlChar*)toString((uint32)Type).c_str());
240 switch( Type )
242 case NOT : break;
244 case COMPARISON :
246 ComparisonBlock.write(elmPtr);
248 break;
250 case SUB_CONDITION :
252 xmlSetProp (elmPtr, (const xmlChar*)"SubCondition", (const xmlChar*)SubCondition.c_str());
254 break;
258 void CLogicConditionLogicBlock::read (xmlNodePtr node)
260 xmlCheckNodeName (node, "CONDITION_LOGIC_NODE");
261 uint32 uType;
262 NLMISC::fromString(getXMLProp(node, "Type"), uType);
263 Type = (TLogicConditionLogicBlockType)uType;
264 switch( Type )
266 case NOT : break;
268 case COMPARISON :
270 ComparisonBlock.read (node);
272 break;
274 case SUB_CONDITION :
276 SubCondition = getXMLProp (node, "SubCondition");
278 break;
282 //-----------------------------------------
286 //-------------------------------------------------
287 // setLogicStateMachine :
289 //-------------------------------------------------
290 void CLogicConditionNode::setLogicStateMachine( CLogicStateMachine * logicStateMachine )
292 if( logicStateMachine == 0 )
294 nlwarning("(LOGIC)<CLogicConditionNode::setLogicStateMachine> The state machine is null");
296 else
298 // set the state machine of this node
299 _LogicStateMachine = logicStateMachine;
301 // set the state machine of the logic block
302 LogicBlock.setLogicStateMachine( logicStateMachine );
304 // set the state machine for the sub nodes
305 vector<CLogicConditionNode *>::iterator itNodes;
306 for( itNodes = _Nodes.begin(); itNodes != _Nodes.end(); ++itNodes )
308 (*itNodes)->setLogicStateMachine( logicStateMachine );
312 } // setLogicStateMachine //
315 //-------------------------------------------------
316 // addNode :
318 //-------------------------------------------------
319 void CLogicConditionNode::addNode( CLogicConditionNode * node )
321 node->setLogicStateMachine( _LogicStateMachine );
322 _Nodes.push_back( node );
324 } // addToSubNodes //
327 //-------------------------------------------------
328 // testLogic :
330 //-------------------------------------------------
331 bool CLogicConditionNode::testLogic()
333 // test the logic block
334 if( LogicBlock.testLogic() == false )
336 return false;
339 // if there's no subtree we assess the subtree is true
340 if( _Nodes.empty() )
342 return true;
345 // test the subtree
346 if( LogicBlock.isNotBlock() )
348 // the subtree is false if at least one node is true
349 vector<CLogicConditionNode *>::iterator itNodes;
350 for( itNodes = _Nodes.begin(); itNodes != _Nodes.end(); ++itNodes )
352 if( (*itNodes)->testLogic() == true )
354 return false;
358 return true;
360 else
362 // the subtree is true if at least one node is true
363 vector<CLogicConditionNode *>::iterator itNodes;
364 for( itNodes = _Nodes.begin(); itNodes != _Nodes.end(); ++itNodes )
366 if( (*itNodes)->testLogic() == true )
368 return true;
372 return false;
375 } // testLogic //
378 //-------------------------------------------------
379 // fillVarSet :
381 //-------------------------------------------------
382 void CLogicConditionNode::fillVarSet( set<string>& condVars )
384 if( Type == LOGIC_NODE )
386 LogicBlock.fillVarSet( condVars );
389 vector<CLogicConditionNode *>::iterator itNode;
390 for( itNode = _Nodes.begin(); itNode != _Nodes.end(); ++itNode )
392 (*itNode)->fillVarSet( condVars );
395 } // fillVarSet //
398 //-------------------------------------------------
399 // serial :
401 //-------------------------------------------------
402 /*void CLogicConditionNode::serial( IStream &f )
404 f.xmlPush("CONDITION_NODE");
406 f.serialEnum( Type );
407 switch( Type )
409 case TERMINATOR : break;
410 case LOGIC_NODE :
412 f.serial( LogicBlock );
413 if( f.isReading() )
415 uint32 sz;
416 f.serial( sz );
417 uint i;
418 for( i = 0; i < sz; i++ )
420 CLogicConditionNode * node = new CLogicConditionNode();
421 f.serial( *node );
422 _Nodes.push_back( node );
425 else
427 uint32 sz = _Nodes.size();
428 f.serial( sz );
429 vector<CLogicConditionNode *>::iterator itNode;
430 for( itNode = _Nodes.begin(); itNode != _Nodes.end(); ++itNode )
432 f.serial( **itNode );
436 break;
439 f.xmlPop();
441 } // serial //*/
443 void CLogicConditionNode::write (xmlNodePtr node) const
445 xmlNodePtr elmPtr = xmlNewChild ( node, NULL, (const xmlChar*)"CONDITION_NODE", NULL);
446 xmlSetProp (elmPtr, (const xmlChar*)"Type", (const xmlChar*)toString((uint32)Type).c_str());
448 switch( Type )
450 case TERMINATOR : break;
451 case LOGIC_NODE :
453 LogicBlock.write(elmPtr);
454 vector<CLogicConditionNode *>::const_iterator itNode = _Nodes.begin();
455 for( ; itNode != _Nodes.end(); ++itNode )
457 (*itNode)->write(elmPtr);
460 break;
464 void CLogicConditionNode::read (xmlNodePtr node)
466 xmlCheckNodeName (node, "CONDITION_NODE");
467 uint32 uType;
468 NLMISC::fromString(getXMLProp(node, "Type"), uType);
469 Type = (TConditionNodeType )uType;
470 switch( Type )
472 case TERMINATOR : break;
473 case LOGIC_NODE :
475 LogicBlock.read (node);
478 // Count the parent
479 uint nb = CIXml::countChildren (node, "CONDITION_NODE");
480 uint i = 0;
481 xmlNodePtr parent = CIXml::getFirstChildNode (node, "CONDITION_NODE");
482 while (i<nb)
484 CLogicConditionNode *v = new CLogicConditionNode();
485 v->read(parent);
486 _Nodes.push_back (v);
488 // Next parent
489 parent = CIXml::getNextChildNode (parent, "CONDITION_NODE");
490 i++;
494 break;
498 //-------------------------------------------------
499 // ~CLogicConditionNode :
501 //-------------------------------------------------
502 CLogicConditionNode::~CLogicConditionNode()
504 vector<CLogicConditionNode *>::iterator itNodes;
505 for( itNodes = _Nodes.begin(); itNodes != _Nodes.end(); ++itNodes )
507 delete (*itNodes);
510 } // ~CLogicConditionNode //
518 //-------------------------------------------------
519 // setLogicStateMachine :
521 //-------------------------------------------------
522 void CLogicCondition::setLogicStateMachine( CLogicStateMachine * logicStateMachine )
524 if( logicStateMachine == 0 )
526 nlwarning("(LOGIC)<CLogicCondition::setLogicStateMachine> The state machine is null");
528 else
530 // init the logic state machine for each node
531 vector<CLogicConditionNode>::iterator itNodes;
532 for( itNodes = Nodes.begin(); itNodes != Nodes.end(); ++itNodes )
534 (*itNodes).setLogicStateMachine( logicStateMachine );
538 } // setLogicStateMachine //
541 //-------------------------------------------------
542 // testLogic :
544 //-------------------------------------------------
545 bool CLogicCondition::testLogic()
547 vector<CLogicConditionNode>::iterator itNodes;
548 for( itNodes = Nodes.begin(); itNodes != Nodes.end(); ++itNodes )
550 if( (*itNodes).testLogic() == false )
552 return false;
556 return true;
558 } // testLogic //
562 //-------------------------------------------------
563 // fillVarSet :
565 //-------------------------------------------------
566 void CLogicCondition::fillVarSet( set<string>& condVars )
568 vector<CLogicConditionNode>::iterator itNode;
569 for( itNode = Nodes.begin(); itNode != Nodes.end(); ++itNode )
571 (*itNode).fillVarSet( condVars );
574 } // fillVarSet //
578 //-------------------------------------------------
579 // serial :
581 //-------------------------------------------------
582 /*void CLogicCondition::serial( IStream &f )
584 f.xmlPush("CONDITION");
586 f.serial( _ConditionName );
587 f.serialCont( Nodes );
589 f.xmlPop();
591 } // serial //*/
593 void CLogicCondition::write (xmlNodePtr node) const
595 xmlNodePtr elmPtr = xmlNewChild ( node, NULL, (const xmlChar*)"CONDITION", NULL);
596 xmlSetProp (elmPtr, (const xmlChar*)"Name", (const xmlChar*)_ConditionName.c_str());
598 uint i;
599 for (i = 0; i < Nodes.size(); i++)
601 Nodes[i].write(elmPtr);
605 void CLogicCondition::read (xmlNodePtr node)
607 xmlCheckNodeName (node, "CONDITION");
609 _ConditionName = getXMLProp (node, "Name");
612 // Count the parent
613 uint nb = CIXml::countChildren (node, "CONDITION_NODE");
614 uint i = 0;
615 xmlNodePtr parent = CIXml::getFirstChildNode (node, "CONDITION_NODE");
616 while (i<nb)
618 CLogicConditionNode v;
619 v.read(parent);
620 Nodes.push_back (v);
622 // Next parent
623 parent = CIXml::getNextChildNode (parent, "CONDITION_NODE");
624 i++;
630 } // NLLOGIC