File indexing completed on 2024-04-28 07:53:32

0001 /* This file is part of KsirK.
0002  *   Copyright (C) 2005-2007 Gael de Chalendar (aka Kleag) <kleag@free.fr>
0003  *
0004  *   KsirK is free software; you can redistribute it and/or
0005  *   modify it under the terms of the GNU General Public
0006  *   License as published by the Free Software Foundation, either version 2
0007    of the License, or (at your option) any later version.
0008  *
0009  *   This program is distributed in the hope that it will be useful,
0010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012  *   General Public License for more details.
0013  *
0014  *   You should have received a copy of the GNU General Public License
0015  *   along with this program; if not, write to the Free Software
0016  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
0017  *   02110-1301, USA
0018  */
0019 #include "goal.h"
0020 #include "player.h"
0021 #include "onu.h"
0022 #include "kgamewin.h"
0023 #include "gameautomaton.h"
0024 
0025 #include "ksirk_debug.h"
0026 #include <KLocalizedString>
0027 #include <KMessageBox>
0028 
0029 namespace Ksirk {
0030 
0031 namespace GameLogic {
0032 
0033 Goal::Goal() :
0034   m_automaton(nullptr),
0035   m_type(NoGoal),
0036   m_description(""),
0037   m_nbCountries(0),
0038   m_nbArmiesByCountry(0),
0039   m_continents(),
0040   m_players(),
0041   m_player(nullptr)
0042 {
0043 }
0044 
0045 Goal::Goal(GameAutomaton* automaton) :
0046 m_automaton(automaton),
0047 m_type(NoGoal),
0048 m_description(""),
0049 m_nbCountries(0),
0050 m_nbArmiesByCountry(0),
0051 m_continents(),
0052 m_players(),
0053 m_player(nullptr)
0054 {
0055 }
0056 
0057 Goal::~Goal()
0058 {
0059 }
0060 
0061 bool Goal::checkFor(const GameLogic::Player* player) const 
0062 {
0063   qCDebug(KSIRK_LOG) << message(GoalAdvance);
0064   int diff = 0;
0065   switch (type())
0066   {
0067   case Goal::GoalPlayer :
0068     if (m_automaton->playerNamed(*m_players.begin()) != nullptr)
0069     {
0070       return false;
0071     }
0072     else
0073     {
0074       diff  = m_nbCountries-m_player->countries().size();
0075       if (diff > 0)
0076       {
0077         return false;
0078       }
0079       else
0080       {
0081         return true;
0082       }
0083     }
0084     return false;
0085     break;
0086   case Goal::Countries:
0087     return checkCountriesFor(player);
0088     break;
0089   case Goal::Continents:
0090     return checkContinentsFor(player);
0091     break;
0092   default:
0093     return ((int) player->getNbCountries() >= m_automaton->game()->theWorld()->getCountries().size());
0094   }
0095 }
0096 
0097 bool Goal::checkCountriesFor(const GameLogic::Player* player) const
0098 {
0099   qCDebug(KSIRK_LOG) << player->name();
0100   if (player->getNbCountries() >= m_nbCountries)
0101   {
0102     uint nbCountriesOk = 0;
0103     foreach (Country* country, player->countries())
0104     {
0105       if (country->nbArmies() >= m_nbArmiesByCountry)
0106       {
0107         nbCountriesOk++;
0108       }
0109     }
0110     return (nbCountriesOk >= m_nbCountries);
0111   }
0112   else 
0113   {
0114     return false;
0115   }
0116 }
0117 
0118 bool Goal::checkContinentsFor(const GameLogic::Player* player) const
0119 {
0120   qCDebug(KSIRK_LOG) << "Goal::checkContinentsFor " << player->name();
0121   foreach (const QString& continent, m_continents)
0122   {
0123     qCDebug(KSIRK_LOG) << "Should be owned continent id: " << continent;
0124     if ( m_automaton->game()->theWorld()->continentNamed(continent) == nullptr
0125        || m_automaton->game()->theWorld()->continentNamed(continent)->owner() != player)
0126     {
0127       return false;
0128     }
0129   }
0130   if (!m_continents.contains(QString()))
0131   {
0132     return true;
0133   }
0134   bool otherFound = false;
0135   QList<Continent*>& continents = m_automaton->game()->theWorld()->getContinents();
0136   foreach (Continent* continent, continents)
0137   {
0138     if ( ( !m_continents.contains(continent->name()) )
0139           && ( continent->owner() == player) )
0140     {
0141       otherFound = true;
0142       break;
0143     }
0144   }
0145   return otherFound;
0146 }
0147 
0148 QString Goal::message(int displayType) const
0149 {
0150   qCDebug(KSIRK_LOG);
0151   KLocalizedString res;
0152 
0153   QList<QString>::const_iterator it, it_end, it_next;
0154   
0155   if(type()==NoGoal) {
0156     QString mes = i18n("You must conquer the World!");
0157     return mes;
0158   }
0159   else
0160   {
0161     if (displayType & GoalDesc)
0162     {
0163       res = ki18n(m_description.toUtf8().data());
0164       if (m_player == nullptr)
0165       {
0166         res = res.subs("");
0167       }
0168       else
0169       {
0170         res = res.subs(m_player->name());
0171       }
0172       qCDebug(KSIRK_LOG) << "Goal type='" << m_type << "' mes = '" << res.toString() << "'";
0173     
0174       QList<unsigned int>::const_iterator it, it_end;
0175       switch (m_type)
0176       {
0177       case Goal::GoalPlayer :
0178         if (!m_players.empty())
0179         {
0180           qCDebug(KSIRK_LOG) << "  player name='" << *m_players.begin();
0181           qCDebug(KSIRK_LOG) << "  this is player='" << m_automaton->playerNamed(*m_players.begin());
0182           if (m_automaton->playerNamed(*m_players.begin())==nullptr)
0183           {
0184             res = res.subs(i18n("%1 (already dead)",*m_players.begin()));
0185           }
0186           else
0187           {
0188             qCDebug(KSIRK_LOG) << "  its name is='" << *m_players.begin();
0189             res = res.subs(*m_players.begin());
0190           }
0191           res = res.subs(m_nbCountries);
0192         }
0193         else
0194         {
0195           res = res.subs(i18n("Error: no player to destroy"));
0196         }
0197         break;
0198       case Goal::Countries:
0199         qCDebug(KSIRK_LOG) << "  arg1 = '" << m_nbCountries << "'";
0200         res=res.subs(m_nbCountries);
0201         if (m_nbArmiesByCountry > 0)
0202         {
0203           qCDebug(KSIRK_LOG) << "  arg2 = '" << m_nbArmiesByCountry << "'";
0204           res=res.subs(m_nbArmiesByCountry);
0205         }
0206         break;
0207       case Goal::Continents:
0208         foreach (const QString& continent, m_continents)
0209         {
0210           if (!continent.isEmpty())
0211           {
0212             qCDebug(KSIRK_LOG) << "  arg = '" << continent << "'";
0213             res=res.subs(i18n(continent.toUtf8().data()));
0214           }
0215         }
0216         break;
0217       default:;
0218       }
0219     }
0220   }
0221 
0222   QString mes = res.toString();
0223   if (displayType & GoalAdvance)
0224   {
0225     int diff = 0;
0226     switch (m_type)
0227     {
0228     case Goal::GoalPlayer :
0229       if (m_automaton->playerNamed(*m_players.begin()) != nullptr)
0230       {
0231         mes += i18n("<br>%1 is still alive...",*m_players.begin());
0232       }
0233       else
0234       {
0235         diff  = m_nbCountries-m_player->countries().size();
0236         if (diff > 0)
0237         {
0238           mes += i18np("<br>%2, you still have 1 country to conquer...","<br>%2, you still have %1 countries to conquer...",diff,m_player->name());
0239         }
0240         else
0241         {
0242           mes += i18np("<br>Your goal is reached: %2 is dead and you possess %1 country.",
0243                        "<br>Your goal is reached: %2 is dead and you possess %1 countries.",
0244                        m_nbCountries, *m_players.begin());
0245         }
0246       }
0247     break;
0248     case Goal::Countries:
0249       diff  = m_nbCountries-m_player->countries().size();
0250       if (diff > 0)
0251       {
0252         mes += i18np("<br>%2, you still have 1 country to conquer...","<br>%2, you still have %1 countries to conquer...",diff,m_player->name());
0253       }
0254       else
0255       {
0256         int nbOk = 0;
0257         for (int i = 0; i < m_player->countries().size();++i)
0258         {
0259           if (m_player->countries().at(i)->nbArmies() >= m_nbArmiesByCountry)
0260           {
0261             nbOk++;
0262           }
0263         }
0264         mes += i18np("<br>%2, you have enough countries but you still have to put more than 1 army on %3 of them...","<br>%2, you have enough countries but you still have to put more than %1 armies on %3 of them...",m_nbArmiesByCountry,m_player->name(),m_nbCountries-nbOk);
0265         
0266       }
0267       break;
0268     case Goal::Continents:
0269       mes += i18n("<br>%1, you still have to conquer ",m_player->name());
0270       it = m_continents.begin(); it_end = m_continents.end();
0271       if (*it != nullptr)
0272       {
0273         Continent* continent = const_cast<Continent*>(m_automaton->game()->theWorld()->continentNamed(*it));
0274         int nb = continent->getMembers().size() - continent->countriesOwnedBy(m_player).size();
0275         mes += i18np("1 country in %2","%1 countries in %2",nb,i18n(continent->name().toUtf8().data()));
0276       }
0277       it++;
0278       while (it != it_end)
0279       {
0280         it_next = it;
0281         it_next++;
0282         QString joint;
0283         if (it_next==it_end)
0284         {
0285           joint = i18n(" and ");
0286         }
0287         else
0288         {
0289           joint = i18n(", ");
0290         }
0291         if (*it != nullptr)
0292         {
0293           Continent* continent = const_cast<Continent*>(m_automaton->game()->theWorld()->continentNamed(*it));
0294           int nb = continent->getMembers().size() - continent->countriesOwnedBy(m_player).size();
0295           mes += joint + i18nc("@info An element of the enumeration of the number of countries in the given continent", "%1 in %2",nb,i18n(continent->name().toUtf8().data()));
0296         }
0297         it++;
0298       }
0299       mes += '.';
0300       break;
0301     default:
0302       break;
0303 ;
0304     }
0305   }
0306 
0307   return mes;
0308 }
0309   
0310 void Goal::show(int displayType)
0311 {
0312   qCDebug(KSIRK_LOG) << message(displayType);
0313 //   m_automaton->game()->showMessage(message(displayType),5, KGameWindow::ForceShowing);
0314   KMessageBox::information(
0315                             m_automaton->game(),
0316                             message(displayType), 
0317                             i18n("KsirK - Goal Display"));
0318 }
0319 
0320 QDataStream& operator<<(QDataStream& stream, const Goal& goal)
0321 {
0322   qCDebug(KSIRK_LOG) << "Goal operator<< : type" << goal.type();
0323   stream << quint32(goal.type());
0324   if (goal.player() != nullptr)
0325   {
0326     qCDebug(KSIRK_LOG) << "Goal operator<< : player " << goal.player()->id();
0327     stream << quint32(goal.player()->id());
0328   }
0329   else
0330   {
0331     qCDebug(KSIRK_LOG) << "Goal operator<< : player " << 0 ;
0332     stream << quint32(0);
0333   }
0334   qCDebug(KSIRK_LOG) << "Goal operator<< : description " << goal.description();
0335   stream << goal.description();
0336   QList<QString>::ConstIterator it, it_end;
0337   QList<QString>::ConstIterator itc, itc_end;
0338   switch (goal.type())
0339   {
0340   case Goal::GoalPlayer :
0341     qCDebug(KSIRK_LOG) << "Goal operator<< : players " << goal.players().size();
0342     stream << quint32(goal.players().size());
0343     it = goal.players().constBegin(); it_end = goal.players().constEnd();
0344     for (; it != it_end; it++)
0345     {
0346       qCDebug(KSIRK_LOG) << "Goal operator<< : player " << (*it);
0347       stream << *it;
0348     }
0349     qCDebug(KSIRK_LOG) << "Goal operator<< : nbCountries " << goal.nbCountries();
0350     stream << quint32(goal.nbCountries());
0351     break;
0352   case Goal::Countries:
0353     qCDebug(KSIRK_LOG) << "Goal operator<< : nbCountries " << goal.nbCountries();
0354     stream << quint32(goal.nbCountries());
0355     qCDebug(KSIRK_LOG) << "Goal operator<< : nbArmiesByCountry " << goal.nbArmiesByCountry();
0356     stream << quint32(goal.nbArmiesByCountry());
0357     break;
0358   case Goal::Continents:
0359     qCDebug(KSIRK_LOG) << "Goal operator<< : continents " << goal.continents().size();
0360     stream << quint32(goal.continents().size());
0361     itc = goal.continents().constBegin(); itc_end = goal.continents().constEnd();
0362     for (; itc != itc_end; itc++)
0363     {
0364       qCDebug(KSIRK_LOG) << "Goal operator<< : continent " << (*itc);
0365       stream << (*itc);
0366     }
0367     break;
0368   default: break;
0369   }
0370   return stream;
0371 }
0372 
0373 QDataStream& operator>>(QDataStream& stream, Goal& goal)
0374 {
0375   qCDebug(KSIRK_LOG) << "Goal operator>>";
0376   quint32 type;
0377   QString description;
0378   QString playerName;
0379   quint32 nb, nbp;
0380   QString id;
0381   quint32 ownerId;
0382   stream >> type;
0383   qCDebug(KSIRK_LOG) << "Goal operator>> type: " << type ;
0384   stream >> ownerId;
0385   qCDebug(KSIRK_LOG) << "Goal operator>> ownerId: " << ownerId ;
0386   goal.player(static_cast<Player*>(goal.m_automaton->findPlayer(ownerId)));
0387   goal.type(Goal::GoalType(type));
0388   stream >> description;
0389   qCDebug(KSIRK_LOG) << "Goal operator>> description: " << description ;
0390   goal.description(description);
0391   switch (type)
0392   {
0393   case Goal::GoalPlayer :
0394     goal.players().clear();
0395     stream >> nbp;
0396     qCDebug(KSIRK_LOG) << "Goal operator>> nbp: " << nbp ;
0397     for (quint32 i = 0; i < nbp; i++)
0398     {
0399       stream >> playerName;
0400       qCDebug(KSIRK_LOG) << "Goal operator>> player name: " << playerName ;
0401       goal.players().push_back(playerName);
0402     }
0403     stream >> nb;
0404     qCDebug(KSIRK_LOG) << "Goal operator>> nbCountries: " << nb ;
0405     goal.nbCountries(nb);
0406     break;
0407   case Goal::Countries:
0408     stream >> nb;
0409     qCDebug(KSIRK_LOG) << "Goal operator>> nbCountries: " << nb ;
0410     goal.nbCountries(nb);
0411     stream >> nb;
0412     goal.nbArmiesByCountry(nb);
0413     qCDebug(KSIRK_LOG) << "Goal operator>> nbArmiesByCountry: " << nb ;
0414     break;
0415   case Goal::Continents:
0416     stream >> nb;
0417     qCDebug(KSIRK_LOG) << "Goal operator>> nbContinents: " << nb ;
0418     goal.continents().clear();
0419     for (quint32 i = 0; i < nb; i++)
0420     {
0421       stream >> id;
0422       qCDebug(KSIRK_LOG) << "Goal operator>> continent: " << id ;
0423       goal.continents().push_back(id);
0424     }
0425     break;
0426   default:;
0427   }
0428   return stream;
0429 }
0430 
0431 void Goal::saveXml(QTextStream& xmlStream) const
0432 {
0433   
0434   xmlStream << "<goal player=\"";
0435   if (m_player != nullptr)
0436   {
0437     xmlStream << m_player->name();
0438   }
0439   xmlStream << "\" type=\"" << m_type << "\" description=\"" << m_description;
0440   xmlStream << "\" nbCountries=\"" << m_nbCountries << "\" nbArmiesByCountry=\"" << m_nbArmiesByCountry << "\">";
0441   xmlStream << "<continents>";
0442   QList<QString>::ConstIterator itc, itc_end;
0443   itc = continents().constBegin(); itc_end = continents().constEnd();
0444   for (; itc != itc_end; itc++)
0445   {
0446     QString name = ((*itc).isEmpty())?"":(*itc);
0447     xmlStream << "<continent name=\"" << name << "\"/>";
0448   }
0449   xmlStream << "</continents>";
0450   xmlStream << "<players>";
0451   QList<QString>::ConstIterator itp, itp_end;
0452   itp = m_players.constBegin(); itp_end = m_players.constEnd();
0453   for (; itp != itp_end; itp++)
0454   {
0455     xmlStream << "<player name=\"" << (*itp) << "\"/>";
0456   }
0457   xmlStream << "</players>";
0458   xmlStream << "</goal>";
0459 }
0460 
0461 }
0462 
0463 }