File indexing completed on 2024-05-12 05:39:27

0001 /***************************************************************************
0002  *   Copyright (C) 2016 by Renaud Guezennec                                *
0003  *   https://rolisteam.org/contact                   *
0004  *                                                                         *
0005  *   rolisteam is free software; you can redistribute it and/or modify     *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "ifnode.h"
0021 #include "result/diceresult.h"
0022 #include "validatorlist.h"
0023 
0024 PartialDiceRollNode::PartialDiceRollNode() : m_diceResult(new DiceResult)
0025 {
0026     m_result= m_diceResult;
0027 }
0028 
0029 void PartialDiceRollNode::insertDie(Die* die)
0030 {
0031     m_diceResult->insertResult(die);
0032 }
0033 
0034 void PartialDiceRollNode::run(ExecutionNode* previous)
0035 {
0036     m_previousNode= previous;
0037     Result* presult= previous->getResult();
0038     if(nullptr != presult)
0039     {
0040         m_result->setPrevious(presult);
0041     }
0042     if(nullptr != m_nextNode)
0043     {
0044         m_nextNode->run(this);
0045     }
0046 }
0047 ExecutionNode* PartialDiceRollNode::getCopy() const
0048 {
0049     return new PartialDiceRollNode();
0050 }
0051 qint64 PartialDiceRollNode::getPriority() const
0052 {
0053     qint64 priority= 4;
0054     return priority;
0055 }
0056 
0057 QString PartialDiceRollNode::toString(bool withLabel) const
0058 {
0059     if(withLabel)
0060     {
0061         return QString("%1 [label=\"PartialDiceRollNode \"]").arg(m_id);
0062     }
0063     else
0064     {
0065         return m_id;
0066     }
0067 }
0068 
0069 DiceResult* getFirstDiceResult(Result* result)
0070 {
0071     DiceResult* found= nullptr;
0072 
0073     if(nullptr == result)
0074         return found;
0075     do
0076     {
0077         found= dynamic_cast<DiceResult*>(result);
0078         result= result->getPrevious();
0079     } while((nullptr == found) && (result != nullptr));
0080 
0081     return found;
0082 }
0083 
0084 IfNode::IfNode() : m_conditionType(Dice::AllOfThem), m_true(nullptr), m_false(nullptr)
0085 {
0086     // m_result = new DiceResult();
0087 }
0088 
0089 IfNode::~IfNode()
0090 {
0091     m_result= nullptr;
0092 }
0093 
0094 void IfNode::run(ExecutionNode* previous)
0095 {
0096     m_previousNode= previous;
0097     if(nullptr == previous)
0098     {
0099         return;
0100     }
0101     ExecutionNode* previousLoop= previous;
0102     ExecutionNode* nextNode= nullptr;
0103     bool runNext= (nullptr == m_nextNode) ? false : true;
0104     Result* previousResult= previous->getResult();
0105     m_result= previousResult->getCopy();
0106 
0107     if(nullptr != m_result)
0108     {
0109         qreal value= previousResult->getResult(Dice::RESULT_TYPE::SCALAR).toReal();
0110 
0111         if(nullptr != m_validatorList)
0112         {
0113             DiceResult* previousDiceResult= getFirstDiceResult(previousResult);
0114             if(nullptr != previousDiceResult)
0115             {
0116                 QList<Die*> diceList= previousDiceResult->getResultList();
0117 
0118                 if(m_conditionType == Dice::OnEach)
0119                 {
0120                     for(Die* dice : diceList)
0121                     {
0122                         auto diceNode= new PartialDiceRollNode();
0123                         diceNode->insertDie(new Die(*dice));
0124                         if(m_validatorList->hasValid(dice, true, true))
0125                         {
0126                             nextNode= (nullptr == m_true) ? nullptr : m_true->getCopy();
0127                         }
0128                         else
0129                         {
0130                             nextNode= (nullptr == m_false) ? nullptr : m_false->getCopy();
0131                         }
0132 
0133                         if(nullptr != nextNode)
0134                         {
0135                             if(nullptr == previousLoop->getNextNode())
0136                             {
0137                                 previousLoop->setNextNode(nextNode);
0138                             }
0139                             if(nullptr == m_nextNode)
0140                             {
0141                                 m_nextNode= nextNode;
0142                             }
0143                             diceNode->setNextNode(nextNode);
0144                             diceNode->run(previousLoop);
0145                             previousLoop= getLeafNode(nextNode);
0146                         }
0147                     }
0148                 }
0149                 else if((m_conditionType == Dice::OneOfThem) || (m_conditionType == Dice::AllOfThem))
0150                 {
0151                     bool trueForAll= true;
0152                     bool falseForAll= true;
0153 
0154                     bool oneIsTrue= false;
0155                     bool oneIsFalse= false;
0156 
0157                     for(Die* dice : diceList)
0158                     {
0159                         bool result= m_validatorList->hasValid(dice, true, true);
0160                         trueForAll= trueForAll ? result : false;
0161                         falseForAll= falseForAll ? result : false;
0162 
0163                         oneIsTrue|= result;
0164                         oneIsFalse= !result ? true : oneIsFalse;
0165                     }
0166                     if(m_conditionType == Dice::OneOfThem)
0167                     {
0168                         if(oneIsTrue)
0169                         {
0170                             nextNode= (nullptr == m_true) ? nullptr : m_true->getCopy();
0171                         }
0172                         else // if(oneIsFalse)
0173                         {
0174                             nextNode= (nullptr == m_false) ? nullptr : m_false->getCopy();
0175                         }
0176                     }
0177                     else if(m_conditionType == Dice::AllOfThem)
0178                     {
0179                         if(trueForAll)
0180                         {
0181                             nextNode= (nullptr == m_true) ? nullptr : m_true->getCopy();
0182                         }
0183                         else // if(falseForAll)
0184                         {
0185                             nextNode= (nullptr == m_false) ? nullptr : m_false->getCopy();
0186                         }
0187                     }
0188 
0189                     if(nullptr != nextNode)
0190                     {
0191                         if(nullptr == m_nextNode)
0192                         {
0193                             m_nextNode= nextNode;
0194                         }
0195                         nextNode->run(previousLoop);
0196                         previousLoop= getLeafNode(nextNode);
0197                     }
0198                 }
0199             }
0200 
0201             if(m_conditionType == Dice::OnScalar)
0202             {
0203                 Die dice;
0204                 auto val= static_cast<qint64>(value);
0205                 dice.setValue(val);
0206                 dice.insertRollValue(val);
0207                 dice.setMaxValue(val);
0208                 if(m_validatorList->hasValid(&dice, true, true))
0209                 {
0210                     nextNode= m_true;
0211                 }
0212                 else
0213                 {
0214                     nextNode= m_false;
0215                 }
0216                 if(nullptr != nextNode)
0217                 {
0218                     if(nullptr == m_nextNode)
0219                     {
0220                         m_nextNode= nextNode;
0221                     }
0222                     nextNode->run(previousLoop);
0223                     previousLoop= getLeafNode(nextNode);
0224                 }
0225             }
0226         }
0227     }
0228 
0229     if((nullptr != m_nextNode) && (runNext))
0230     {
0231         m_nextNode->run(previousLoop);
0232     }
0233 }
0234 
0235 void IfNode::setValidatorList(ValidatorList* val)
0236 {
0237     m_validatorList= val;
0238 }
0239 void IfNode::setInstructionTrue(ExecutionNode* node)
0240 {
0241     m_true= node;
0242 }
0243 
0244 void IfNode::setInstructionFalse(ExecutionNode* node)
0245 {
0246     m_false= node;
0247 }
0248 void IfNode::generateDotTree(QString& s)
0249 {
0250     s.append(toString(true));
0251     s.append(";\n");
0252 
0253     if((nullptr != m_true) && (m_true != m_nextNode))
0254     {
0255         s.append(toString(false));
0256         s.append(" -> ");
0257         s.append(m_true->toString(false));
0258         s.append("[label=\"true" + m_validatorList->toString() + "\"];\n");
0259 
0260         m_true->generateDotTree(s);
0261     }
0262     if((nullptr != m_false) && (m_false != m_nextNode))
0263     {
0264         s.append(toString(false));
0265         s.append(" -> ");
0266         s.append(m_false->toString(false));
0267         s.append("[label=\"false\"];\n");
0268         m_false->generateDotTree(s);
0269     }
0270 
0271     if(nullptr != m_nextNode)
0272     {
0273         s.append(toString(false));
0274         s.append(" -> ");
0275         s.append(m_nextNode->toString(false));
0276         s.append("[label=\"next\"];\n");
0277         m_nextNode->generateDotTree(s);
0278     }
0279     else
0280     {
0281         s.append(toString(false));
0282         s.append(" -> ");
0283         s.append("nullptr;\n");
0284 
0285         if(nullptr != m_result)
0286         {
0287             s.append(toString(false));
0288             s.append(" ->");
0289             s.append(m_result->toString(false));
0290             s.append(" [label=\"Result\"];\n");
0291             m_result->generateDotTree(s);
0292         }
0293     }
0294 }
0295 
0296 QString IfNode::toString(bool wl) const
0297 {
0298     if(wl)
0299     {
0300         return QString("%1 [label=\"IfNode\"]").arg(m_id);
0301     }
0302     else
0303     {
0304         return m_id;
0305     }
0306 }
0307 
0308 qint64 IfNode::getPriority() const
0309 {
0310     return 0;
0311 }
0312 
0313 ExecutionNode* IfNode::getLeafNode(ExecutionNode* node)
0314 {
0315     ExecutionNode* next= node;
0316     while(nullptr != next->getNextNode())
0317     {
0318         next= next->getNextNode();
0319     }
0320     return next;
0321 }
0322 
0323 Dice::ConditionType IfNode::getConditionType() const
0324 {
0325     return m_conditionType;
0326 }
0327 
0328 void IfNode::setConditionType(const Dice::ConditionType& conditionType)
0329 {
0330     m_conditionType= conditionType;
0331 }
0332 ExecutionNode* IfNode::getCopy() const
0333 {
0334     IfNode* node= new IfNode();
0335 
0336     node->setConditionType(m_conditionType);
0337     if(nullptr != m_validatorList)
0338     {
0339         node->setValidatorList(m_validatorList->getCopy());
0340     }
0341     if(nullptr != m_false)
0342     {
0343         node->setInstructionFalse(m_false->getCopy());
0344     }
0345     if(nullptr != m_true)
0346     {
0347         node->setInstructionTrue(m_true->getCopy());
0348     }
0349     if(nullptr != m_nextNode)
0350     {
0351         node->setNextNode(m_nextNode->getCopy());
0352     }
0353     return node;
0354 }