File indexing completed on 2024-04-28 05:37:00

0001 /***************************************************************************
0002  *   Copyright (C) 2015 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 
0021 #include "operationcondition.h"
0022 
0023 OperationCondition::OperationCondition()
0024     : m_operator(Dice::ConditionOperator::Modulo), m_boolean(nullptr), m_value(nullptr)
0025 {
0026 }
0027 OperationCondition::~OperationCondition()
0028 {
0029     if(m_value != nullptr)
0030     {
0031         delete m_value;
0032         m_value= nullptr;
0033     }
0034 }
0035 BooleanCondition* OperationCondition::getBoolean() const
0036 {
0037     return m_boolean;
0038 }
0039 
0040 void OperationCondition::setBoolean(BooleanCondition* boolean)
0041 {
0042     m_boolean= boolean;
0043 }
0044 
0045 qint64 OperationCondition::hasValid(Die* b, bool recursive, bool unhighlight) const
0046 {
0047     if(nullptr == m_boolean)
0048     {
0049         return 0;
0050     }
0051     QList<qint64> listValues;
0052     if(recursive)
0053     {
0054         listValues= b->getListValue();
0055     }
0056     else
0057     {
0058         listValues.append(b->getLastRolledValue());
0059     }
0060 
0061     qint64 sum= 0;
0062     for(qint64& value : listValues)
0063     {
0064         switch(m_operator)
0065         {
0066         case Dice::ConditionOperator::Modulo:
0067         {
0068             Die die;
0069             die.setMaxValue(b->getMaxValue());
0070             auto valueScalar= valueToScalar();
0071             if(valueScalar == 0)
0072                 valueScalar= 1;
0073             die.insertRollValue(value % valueScalar);
0074             sum+= m_boolean->hasValid(&die, recursive, false) ? 1 : 0;
0075         }
0076         break;
0077         }
0078     }
0079     if((unhighlight) && (sum == 0))
0080     {
0081         b->setHighlighted(false);
0082     }
0083     else
0084     {
0085         b->setHighlighted(true);
0086     }
0087 
0088     return sum;
0089 }
0090 
0091 void OperationCondition::setOperator(Dice::ConditionOperator m)
0092 {
0093     m_operator= m;
0094 }
0095 
0096 void OperationCondition::setValueNode(ExecutionNode* node)
0097 {
0098     m_value= node;
0099 }
0100 
0101 QString OperationCondition::toString()
0102 {
0103     QString str("");
0104     switch(m_operator)
0105     {
0106     case Dice::ConditionOperator::Modulo:
0107         str.append(QStringLiteral("\\%"));
0108         break;
0109     }
0110     return QStringLiteral("[%1%2%3]").arg(str).arg(valueToScalar()).arg(m_boolean->toString());
0111 }
0112 Dice::CONDITION_STATE OperationCondition::isValidRangeSize(const std::pair<qint64, qint64>& range) const
0113 {
0114     Dice::CONDITION_STATE valid= Dice::CONDITION_STATE::REACHABLE;
0115 
0116     auto rangeIsClose= (range.first == range.second);
0117 
0118     Die die;
0119     die.insertRollValue(range.first);
0120 
0121     if(nullptr == m_boolean)
0122         return Dice::CONDITION_STATE::ERROR_STATE;
0123 
0124     if(rangeIsClose && m_boolean->hasValid(&die, false, false))
0125         valid= Dice::CONDITION_STATE::ALWAYSTRUE;
0126     else if(rangeIsClose && !m_boolean->hasValid(&die, false, false))
0127         valid= Dice::CONDITION_STATE::UNREACHABLE;
0128 
0129     return valid;
0130 }
0131 
0132 Validator* OperationCondition::getCopy() const
0133 {
0134     OperationCondition* val= new OperationCondition();
0135     val->setOperator(m_operator);
0136     val->setValueNode(m_value->getCopy());
0137     BooleanCondition* boolean= dynamic_cast<BooleanCondition*>(m_boolean->getCopy());
0138     val->setBoolean(boolean);
0139     return val;
0140 }
0141 
0142 qint64 OperationCondition::valueToScalar() const
0143 {
0144     if(m_value == nullptr)
0145         return 0;
0146 
0147     m_value->run(nullptr);
0148     auto result= m_value->getResult();
0149     return result->getResult(Dice::RESULT_TYPE::SCALAR).toInt();
0150 }
0151 
0152 const std::set<qint64>& OperationCondition::getPossibleValues(const std::pair<qint64, qint64>& range)
0153 {
0154     if(nullptr == m_boolean)
0155         return m_values;
0156 
0157     for(qint64 i= std::min(range.first, range.second); i <= std::max(range.first, range.second); ++i)
0158     {
0159         auto valueScalar= valueToScalar();
0160         auto val= i % valueScalar;
0161         Die die;
0162         die.insertRollValue(val);
0163         if(m_boolean->hasValid(&die, false, false))
0164             m_values.insert(i);
0165     }
0166     return m_values;
0167 }