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

0001 /* This file is part of KsirK.
0002    Copyright (C) 2001-2007 Gael de Chalendar <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 
0020 /* begin                : Wed Jul 18 2001 */
0021 
0022 #include "country.h"
0023 #include "player.h"
0024 #include "Sprites/backgnd.h"
0025 #include "kgamewin.h"
0026 #include "ksirksettings.h"
0027 #include "Sprites/flagsprite.h"
0028 #include "Sprites/skinSpritesData.h"
0029 #include "GameLogic/onu.h"
0030 
0031 #include <KLocalizedString>
0032 #include "ksirk_debug.h"
0033 #include <QSvgRenderer>
0034 #include <QApplication>
0035 #include <QDataStream>
0036 #include <QBitmap>
0037 #include <QGraphicsSvgItem>
0038 #include <QTextStream>
0039 
0040 namespace Ksirk
0041 {
0042 
0043 namespace GameLogic
0044 {
0045 
0046 Country::Country(GameAutomaton* game,
0047                   const QString& theName,
0048                   const QPointF& anchorPoint,
0049                   const QPointF& centralPoint,
0050                   const QPointF& flagPoint,
0051                   const QPointF& cannonPoint, 
0052                   const QPointF& cavalryPoint,
0053                   const QPointF& infantryPoint) :
0054   m_automaton(game),
0055   m_belongsTo(nullptr),
0056   m_flag(nullptr),
0057   m_nbArmies(0),
0058   m_name(theName),
0059   m_anchorPoint(anchorPoint),
0060   m_centralPoint(centralPoint),
0061   m_pointFlag(flagPoint),
0062   m_pointCannon(cannonPoint), 
0063   m_pointCavalry(cavalryPoint),
0064   m_pointInfantry(infantryPoint),
0065   m_highlighting(nullptr),
0066   m_renderer(new QSvgRenderer()),
0067   m_highlighting_locked(false),
0068   m_nbArmiesItem(nullptr)
0069 {
0070 //   qCDebug(KSIRK_LOG) << m_name << ", " << this ;
0071 }
0072 
0073 Country::~Country()
0074 {
0075 //   qCDebug(KSIRK_LOG) << "Deleting country " << m_name << ", " << this ;
0076   if (m_flag)
0077   {
0078     m_flag->hide();
0079     delete m_flag;
0080     m_flag = nullptr;
0081   }
0082   delete m_renderer;
0083 }
0084 
0085 void Country::reset()
0086 {
0087 //   qCDebug(KSIRK_LOG) << "Country::reset " << m_name ;
0088   clearAllSprites();
0089   m_belongsTo = nullptr;
0090   nbArmies(1);
0091   createArmiesSprites();
0092 
0093   if (m_flag)
0094   {
0095     m_flag->hide();
0096     delete m_flag;
0097     m_flag = nullptr;
0098   }
0099 }
0100 
0101 void Country::createArmiesSprites()
0102 {
0103 //   qCDebug(KSIRK_LOG) << name() << nbArmies();
0104   BackGnd* bg = m_automaton->game()->backGnd();
0105   
0106   unsigned int armies = nbArmies();
0107   clearAllSprites();
0108   int i = 0;
0109   while (armies >= 10) // Ajout des sprites de canon
0110   {
0111 //     qCDebug(KSIRK_LOG) << "  cannon" << i << armies;
0112     CannonSprite *sprite = new CannonSprite(bg->onu()->zoom(), bg);
0113     sprite-> setDestination(nullptr);             // Sprite immobile
0114     if (m_automaton->game()->currentWidgetType() == Ksirk::KGameWindow::Arena)
0115     {
0116       sprite-> setPos(
0117         m_pointCannon.x()*bg->onu()->zoom(),
0118         (m_pointCannon.y()+(1-2*(i%2))*(Sprites::SkinSpritesData::single().intData("cannon-height")+8)*((i+1)/2))*bg->onu()->zoom());
0119       if (this->name() == m_automaton->game()->secondCountry()->name())
0120       {
0121         sprite->setLookLeft();
0122       }
0123     }
0124     else
0125     {
0126       sprite-> setPos((m_pointCannon.x()+5*i)*bg->onu()->zoom(),(m_pointCannon.y()+5*i)*bg->onu()->zoom());
0127     }
0128     m_spritesCannons.append(sprite);
0129     i++;
0130     armies -= 10;
0131   }
0132   i = 0;
0133   while (armies >= 5) // Adding the cavalryman  sprites
0134   {
0135 //     qCDebug(KSIRK_LOG) << "  cavalry" << i << armies;
0136     CavalrySprite *sprite = new CavalrySprite(bg->onu()->zoom(), bg);
0137     sprite-> setDestination(nullptr);             // Sprite immobile
0138     if (m_automaton->game()->currentWidgetType() == Ksirk::KGameWindow::Arena)
0139     {
0140 //       qCDebug(KSIRK_LOG) << "arena";
0141       sprite-> setPos(
0142         m_pointCavalry.x()*bg->onu()->zoom(),
0143         (m_pointCavalry.y()+(1-2*(i%2))*(Sprites::SkinSpritesData::single().intData("cavalry-height")+8)*((i+1)/2))*bg->onu()->zoom());
0144 //       qCDebug(KSIRK_LOG) << "setPos done";
0145       if (this->name() == m_automaton->game()->secondCountry()->name())
0146       {
0147         sprite->setLookLeft();
0148       }
0149     }
0150     else
0151     {
0152       sprite-> setPos((m_pointCavalry.x()+5*i)*bg->onu()->zoom(),(m_pointCavalry.y()+5*i)*bg->onu()->zoom());
0153     }
0154 //     qCDebug(KSIRK_LOG) << "appending";
0155     m_spritesCavalry.append(sprite);
0156     i++;
0157     armies -= 5;
0158   }
0159   i = 0;
0160   while (armies > 0) // Ajout des sprites de fantassin
0161   {
0162 //     qCDebug(KSIRK_LOG) << "  infantry" << i << armies;
0163     InfantrySprite *sprite = new InfantrySprite(bg->onu()->zoom(), bg);
0164     sprite-> setDestination(nullptr);             // Sprite immobile
0165     if (m_automaton->game()->currentWidgetType() == Ksirk::KGameWindow::Arena)
0166     {
0167       sprite-> setPos(
0168         m_pointInfantry.x()*bg->onu()->zoom(),
0169         (m_pointInfantry.y()+(1-2*(i%2))*(Sprites::SkinSpritesData::single().intData("infantry-height")+8)*((i+1)/2))*bg->onu()->zoom());
0170       if (this->name() == m_automaton->game()->secondCountry()->name())
0171       {
0172         sprite->setLookLeft();
0173       }
0174     }
0175     else
0176     {
0177       sprite-> setPos((m_pointInfantry.x()+5*i)*bg->onu()->zoom(),(m_pointInfantry.y()+5*i)*bg->onu()->zoom());
0178     }
0179     m_spritesInfantry.append(sprite);
0180     i++;
0181     armies--;
0182   }
0183 
0184 //   qCDebug(KSIRK_LOG) << "adding flag" << m_belongsTo ;
0185   if (m_belongsTo)
0186   {
0187 //     qCDebug(KSIRK_LOG) << m_belongsTo->flagFileName();
0188     flag(m_belongsTo->flagFileName(), bg);
0189   }
0190 
0191 //   qCDebug(KSIRK_LOG) << "adding nb armies text";
0192   if (m_nbArmiesItem == nullptr)
0193   {
0194     m_nbArmiesItem = new QGraphicsSimpleTextItem(QString::number(m_nbArmies),bg);
0195     m_nbArmiesItem->setPos((m_pointFlag.x()+5),(m_pointFlag.y()+7));
0196     m_nbArmiesItem->setZValue(20);
0197     m_nbArmiesItem->setBrush(Qt::white);
0198     m_nbArmiesItem->setPen(QPen(Qt::yellow));
0199   }
0200   if (!KsirkSettings::showArmiesNumbers())
0201   {
0202     m_nbArmiesItem->hide();
0203   }
0204   else
0205   {
0206     m_nbArmiesItem->show();
0207   }
0208 //   qCDebug(KSIRK_LOG) << "Done";
0209 }
0210 
0211 void Country::flag(const QString& theFlagFileName, BackGnd *backGnd)
0212 {
0213 //   qCDebug(KSIRK_LOG) << "Country("<<m_name<<", "<<this<<")::flag flagFileName " << theFlagFileName ;
0214 
0215   if (m_flag)
0216   {
0217     m_flag->hide();
0218     delete m_flag;
0219     m_flag = nullptr;
0220   }
0221   
0222   m_flag = new FlagSprite(theFlagFileName, backGnd->onu()->zoom(), backGnd);
0223   m_flag-> setDestination(nullptr);
0224   m_flag-> setPos(m_pointFlag.x()*backGnd->onu()->zoom(),m_pointFlag.y()*backGnd->onu()->zoom());
0225   m_flag-> setZValue(10);
0226 
0227 //    qDebug("OUT Country::flag");
0228 }
0229 
0230 bool Country::communicateWith(const Country* otherCountry) const
0231 {
0232   if (!otherCountry)
0233   {
0234     qCDebug(KSIRK_LOG) << "OUT otherCountry null Country::communicateWith";
0235     return false;
0236   }
0237 
0238   // a country is considered to communicate with itself
0239   if (otherCountry == this) {return true;}
0240 
0241 //    qCDebug(KSIRK_LOG) << "Country::communicateWith (" << name() << ", " << otherCountry-> name() << ")" << endl << flush;
0242 //   unsigned int nbNeighbours = neighbours().size();
0243   foreach (Country* neighbour, neighbours())
0244   {
0245     if (neighbour == otherCountry)
0246     {
0247 //            qCDebug(KSIRK_LOG) << "OUT true Country::communicateWith" << endl << flush;
0248       return true;
0249     }
0250   }
0251 //    qCDebug(KSIRK_LOG) << "OUT false Country::communicateWith" << endl << flush;
0252   return false;
0253 }
0254 
0255 /** @returns a pointer on the Player that holds this Country */
0256 const Player * Country::owner() const
0257 {
0258   return m_belongsTo;
0259 }
0260 
0261 Player * Country::owner() 
0262 {
0263   return m_belongsTo;
0264 }
0265 
0266 /** At the end of this method, the Country belogns to the argument player */
0267 void Country::owner(Player *player)
0268 {  
0269   m_belongsTo = player;
0270   if (player != nullptr)
0271   {
0272     createArmiesSprites();
0273     flag(m_belongsTo->flagFileName(), m_automaton->game()-> backGnd());
0274   }
0275 }
0276 
0277 unsigned int Country::nbArmies() const
0278 {
0279   return m_nbArmies;
0280 }
0281 
0282 void Country::nbArmies(unsigned int nb)
0283 {
0284   m_nbArmies = nb;
0285   if (m_nbArmiesItem!=nullptr)
0286   {
0287     m_nbArmiesItem->setText(QString::number(m_nbArmies));
0288   }
0289 }
0290 
0291 void Country::incrNbArmies(unsigned int nb)
0292 {
0293   nbArmies(nbArmies() + nb);
0294 }
0295 
0296 void Country::decrNbArmies(unsigned int nb)
0297 {
0298   nbArmies(nbArmies() - nb);
0299 }
0300 
0301 const QString Country::name() const
0302 {
0303   return (m_name);
0304 }
0305 
0306 const QString Country::i18name() const
0307 {
0308   return (i18n(m_name.toUtf8().data()));
0309 }
0310 
0311 const QPointF& Country::anchorPoint() const
0312 {
0313   return (m_anchorPoint);
0314 }
0315 
0316 const QPointF& Country::centralPoint() const
0317 {
0318   return (m_centralPoint);
0319 }
0320 
0321 const QPointF& Country::pointFlag() const
0322 {
0323   return (m_pointFlag);
0324 }
0325 
0326 const QPointF& Country::pointCannon() const
0327 {
0328   return (m_pointCannon);
0329 }
0330 
0331 const QPointF& Country::pointCavalry() const
0332 {
0333   return (m_pointCavalry);
0334 }
0335 
0336 const QPointF& Country::pointInfantry() const
0337 {
0338   return (m_pointInfantry);
0339 }
0340 
0341 void Country::anchorPoint(const QPointF pt)
0342 {
0343   m_anchorPoint = pt;
0344 }
0345 
0346 void Country::centralPoint(const QPointF pt)
0347 {
0348   m_centralPoint = pt;
0349 }
0350 
0351 void Country::pointFlag(const QPointF pt)
0352 {
0353   m_pointFlag = pt;
0354 }
0355 
0356 void Country::pointCannon(const QPointF pt)
0357 {
0358   m_pointCannon = pt;
0359 }
0360 
0361 void Country::pointCavalry(const QPointF pt)
0362 {
0363   m_pointCavalry = pt;
0364 }
0365 
0366 void Country::pointInfantry(const QPointF pt)
0367 {
0368   m_pointInfantry = pt;
0369 }
0370 
0371 AnimSpritesList< CannonSprite >& Country::spritesCannons()
0372 {
0373   return (m_spritesCannons);
0374 }
0375 
0376 AnimSpritesList< CavalrySprite >& Country::spritesCavalry()
0377 {
0378   return (m_spritesCavalry);
0379 }
0380 
0381 AnimSpritesList< InfantrySprite >& Country::spritesInfantry()
0382 {
0383   return (m_spritesInfantry);
0384 }
0385 
0386 /** No descriptions */
0387 void Country::neighbours(const QList<Country*>& neighboursVect)
0388 {
0389   m_neighbours = neighboursVect;
0390 }
0391 
0392 /** No descriptions */
0393 QList< Country* >& Country::neighbours()
0394 {
0395 //    qCDebug(KSIRK_LOG) << "Country::neighbours" << endl << flush;
0396   return m_neighbours;
0397 }
0398 
0399 /** No descriptions */
0400 const QList< Country* >& Country::neighbours() const
0401 {
0402 //    qCDebug(KSIRK_LOG) << "Country::neighbours const" << endl << flush;
0403   return m_neighbours;
0404 }
0405 
0406 /*!
0407     \fn Ksirk::Country::clearAllSprites()
0408  */
0409 void Country::clearAllSprites()
0410 {
0411 //   qCDebug(KSIRK_LOG);
0412   m_spritesCannons.hideAndRemoveAll();
0413   m_spritesCavalry.hideAndRemoveAll();
0414   m_spritesInfantry.hideAndRemoveAll();
0415 }
0416 
0417 const QPointF& Country::pointFor(const AnimSprite* sprite)
0418 {
0419   if (dynamic_cast<const InfantrySprite*>(sprite))
0420   {
0421     return pointInfantry();
0422   }
0423   else if (dynamic_cast<const CavalrySprite*>(sprite))
0424   {
0425     return pointCavalry();
0426   }
0427   else if (dynamic_cast<const CannonSprite*>(sprite))
0428   {
0429     return pointCannon();
0430   }
0431   else if (dynamic_cast<const FlagSprite*>(sprite))
0432   {
0433     return pointFlag();
0434   }
0435   else 
0436   {
0437     qCCritical(KSIRK_LOG) << "Unknown sprite type";
0438     exit(1);
0439   }
0440 }
0441 
0442 void Country::saveXml(QTextStream& xmlStream)
0443 {
0444   QString name = m_name;
0445   name = name.replace("&","&amp;");
0446   name = name.replace("<","&lt;");
0447   name = name.replace(">","&gt;");
0448   xmlStream << "<country name=\""<<name<<"\" owner=\"";
0449   if (m_belongsTo == nullptr)
0450     xmlStream << "none";
0451   else
0452   {
0453     QString pname = m_belongsTo->name();
0454     pname = pname.replace("&","&amp;");
0455     pname = pname.replace("<","&lt;");
0456     pname = pname.replace(">","&gt;");
0457     xmlStream << pname;
0458   }
0459   xmlStream << "\" ";
0460 
0461   xmlStream << "nbArmies=\""<<nbArmies() << "\" ";
0462 
0463   xmlStream << " />";
0464 
0465 }
0466 
0467 void Country::send(QDataStream& stream)
0468 {
0469 //   qCDebug(KSIRK_LOG) << (m_belongsTo?m_belongsTo->name():"") << quint32(m_nbArmies);
0470   stream << m_name << (m_belongsTo?m_belongsTo->name():"") << quint32(m_nbArmies);
0471 }
0472 
0473 bool Country::hasAdjacentEnemy()
0474 {
0475   for (int j = 0; j < m_neighbours.size(); j++)
0476   {
0477     if ( m_neighbours[j]->owner() != m_belongsTo )
0478     {
0479       return true;
0480     }
0481   }
0482   return false;
0483 }
0484 
0485 void Country::highlight(const QColor& color, qreal opacity)
0486 {
0487 //   qCDebug(KSIRK_LOG) << color;
0488   if (m_highlighting_locked)
0489   {
0490     return;
0491   }
0492   clearHighlighting();
0493 
0494   ONU* onu = m_automaton->game()->theWorld();
0495   if (onu == nullptr)
0496   {
0497     qCWarning(KSIRK_LOG) << "onu is null";
0498     return;
0499   }
0500   QDomNode countryElement = onu->svgDom()->elementById(m_name);
0501   if (countryElement.isNull())
0502   {
0503     qCWarning(KSIRK_LOG) << "Got a null element";
0504     return;
0505   }
0506 //   qCDebug(KSIRK_LOG) <<"got country";
0507 
0508   onu->svgDom()->setCurrentNode(countryElement);
0509   onu->svgDom()->setStyleProperty("fill", color.name());
0510   onu->svgDom()->setStyleProperty("fill-opacity", QString::number(opacity));
0511 
0512 //   qCDebug(KSIRK_LOG) <<"loading";
0513   QByteArray svg = onu->svgDom()->nodeToByteArray();
0514   m_renderer->load(svg);
0515 
0516 //   qCDebug(KSIRK_LOG) <<"loaded";
0517   m_highlighting = new QGraphicsSvgItem(m_automaton->game()->backGndWorld());
0518   m_highlighting->setSharedRenderer(m_renderer);
0519   m_highlighting->setElementId(m_name);
0520   m_highlighting->setPos(
0521       (m_anchorPoint.x()-m_highlighting->boundingRect().width()/2)*onu->zoom(),
0522       (m_anchorPoint.y()-m_highlighting->boundingRect().height()/2)*onu->zoom());
0523 
0524   m_highlighting->setScale(onu->zoom());
0525 //   qCDebug(KSIRK_LOG) << "done";
0526 }
0527 
0528 void Country::highlightAsAttacker()
0529 {
0530 //   qCDebug(KSIRK_LOG);
0531   highlight(Qt::red, 0.6);
0532   m_highlighting_locked = true;
0533 }
0534 
0535 void Country::highlightAsDefender()
0536 {
0537 //   qCDebug(KSIRK_LOG);
0538   highlight(Qt::yellow,0.6);
0539   m_highlighting_locked = true;
0540 }
0541 
0542 void Country::clearHighlighting()
0543 {
0544 //   qCDebug(KSIRK_LOG) << m_highlighting_locked << (void*)m_highlighting;
0545   if (!m_highlighting_locked && m_highlighting!=nullptr)
0546   {
0547     m_highlighting->hide();
0548     delete m_highlighting;
0549     m_highlighting = nullptr;
0550   }
0551 //   qCDebug(KSIRK_LOG) << "done";
0552 }
0553 
0554 bool Country::isHighlightingLocked()
0555 {
0556 //   qCDebug(KSIRK_LOG);
0557   return m_highlighting_locked;
0558 }
0559 
0560 void Country::releaseHighlightingLock()
0561 {
0562 //   qCDebug(KSIRK_LOG);
0563   m_highlighting_locked=false;
0564 }
0565 
0566 
0567 QDataStream& operator>>(QDataStream& stream, Country* country)
0568 {
0569   country->reset();
0570   quint32 nbArmies/*, nbAddedArmies*/;
0571   QString ownerName;
0572   stream >> ownerName >> nbArmies/* >> nbAddedArmies*/;
0573 //   qCDebug(KSIRK_LOG) << ownerName << nbArmies/* << nbAddedArmies*/;
0574   country->owner(country->automaton()->playerNamed(ownerName));
0575   country->nbArmies(nbArmies);
0576 //   country->nbAddedArmies(nbAddedArmies);
0577   country->createArmiesSprites();
0578   return stream;
0579 }
0580 
0581 
0582 void Country::copyForArena(Country* trueCountry)
0583 {
0584 //   qCDebug(KSIRK_LOG) << trueCountry->name();
0585   // remove existing elements
0586   clearAllSprites();
0587   if (m_flag)
0588   {
0589     m_flag->hide();
0590     delete m_flag;
0591     m_flag = nullptr;
0592   }
0593 
0594   // change parameters
0595   m_name = trueCountry->m_name;
0596   m_continent = trueCountry->m_continent;
0597   m_belongsTo = trueCountry->m_belongsTo;
0598   m_nbArmies = trueCountry->m_nbArmies;
0599 //   m_id = trueCountry->m_id;
0600 
0601   // make again the display
0602   createArmiesSprites();
0603 }
0604 
0605 } // closing namespace GameLogic
0606 
0607 } // closing namespace Ksirk