File indexing completed on 2024-04-21 07:52:02

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                : mer jui 11 22:27:28 EDT 2001   */
0021 
0022 // application specific includes
0023 #include "kgamewin.h"
0024 #include "ksirkConfigDialog.h"
0025 #include "ksirksettings.h"
0026 #include "Sprites/animspritesgroup.h"
0027 #include "Sprites/arrowsprite.h"
0028 #include "GameLogic/aiplayer.h"
0029 #include "GameLogic/aiColsonPlayer.h"
0030 #include "GameLogic/aiplayerio.h"
0031 #include "GameLogic/dice.h"
0032 #include "GameLogic/KMessageParts.h"
0033 #include "GameLogic/goal.h"
0034 #include "GameLogic/KsirkChatItem.h"
0035 #include "GameLogic/KsirkChatModel.h"
0036 #include "GameLogic/KsirkChatDelegate.h"
0037 #include "SaveLoad/ksirkgamexmlloader.h"
0038 #include "Sprites/backgnd.h"
0039 #include "Dialogs/kplayersetupwidget.h"
0040 #include "Dialogs/kwaitedplayersetupdialog.h"
0041 #include "Dialogs/restartOrExitDialogImpl.h"
0042 #include "Dialogs/newGameDialogImpl.h"
0043 #include "Dialogs/newGameSummaryWidget.h"
0044 #include "Dialogs/tcpconnectwidget.h"
0045 #if HAVE_JABBER_SUPPORT
0046 #include "Dialogs/jabbergameui.h"
0047 #include "im.h"
0048 #include "xmpp_tasks.h"
0049 #endif
0050 
0051 //include files for QT
0052 #include <QAction>
0053 #include <QApplication>
0054 #include <QDialog>
0055 #include <QDockWidget>
0056 #include <QFileDialog>
0057 #include <QGridLayout>
0058 #include <QHostInfo>
0059 #include <QIcon>
0060 #include <QMediaPlayer>
0061 #include <QMenuBar>
0062 #include <QMovie>
0063 #include <QStatusBar>
0064 #include <QString>
0065 #include <QSvgRenderer>
0066 #include <QTreeView>
0067 #include <QUuid>
0068 
0069 // include files for KDE
0070 #include <KMessageBox>
0071 #include <KLazyLocalizedString>
0072 #include <KLocalizedString>
0073 #include <KConfig>
0074 #include <KGameStandardAction>
0075 #include <KStandardAction>
0076 #include <KActionCollection>
0077 #include "ksirk_debug.h"
0078 #include <KGamePopupItem>
0079 #include <KToolBar>
0080 #include <KAboutData>
0081 #define USE_UNSTABLE_LIBKDEGAMESPRIVATE_API
0082 #include <libkdegamesprivate/kgame/kgamechat.h>
0083 #include <libkdegamesprivate/kgame/kmessageserver.h>
0084 #include <sys/utsname.h>
0085 
0086 namespace Ksirk
0087 {
0088 using namespace GameLogic;
0089 
0090 // port all occurrences of m_accels
0091 // port all occurrences of setBarPos
0092 
0093 KGameWindow::KGameWindow(QWidget* parent) :
0094   KXmlGuiWindow(parent),
0095   m_rightDock(nullptr),
0096   m_rightDialog(nullptr),
0097   m_automaton(new GameAutomaton()),
0098   m_wSlide(nullptr),
0099   m_currentDisplayedWidget(MainMenu),
0100   NKD(0), NKA(0),
0101   m_useArena(false),
0102   nbSpriteAttacking(0),
0103   nbSpriteDefending(0),
0104   relativePosInArenaAttack(0),
0105   relativePosInArenaDefense(0),
0106   m_theWorld(nullptr),
0107   m_scene_world(nullptr), m_scene_arena(nullptr),
0108   m_backGnd_world(nullptr), m_backGnd_arena(nullptr),
0109   m_animFighters(new AnimSpritesGroup(this,SLOT(slotMovingFightersArrived(AnimSpritesGroup*)))),
0110   m_nbMovedArmies(0),
0111   m_firstCountry(nullptr), m_secondCountry(nullptr),
0112   m_frame(nullptr),
0113   m_arena(nullptr),
0114   m_mainMenu(nullptr),
0115   m_goalAction(nullptr),
0116   m_barFlag(new QLabel(this)),
0117   m_chatDlg(nullptr),
0118   m_audioPlayer(new QMediaPlayer(this)),
0119   m_timer(this),
0120   m_message(nullptr),
0121   m_mouseLocalisation(nullptr),
0122   m_defenseDialog(nullptr),
0123   m_fileName(),
0124   m_uparrow(nullptr),
0125   m_downarrow(nullptr),
0126   m_leftarrow(nullptr),
0127   m_rightarrow(nullptr),
0128   m_reinitializingGame(false),
0129   m_newGameDialog(nullptr),
0130   m_newPlayerWidget(nullptr),
0131   m_stateBeforeNewGame(GameAutomaton::INVALID),
0132   m_stackWidgetBeforeNewGame(-1),
0133 #if HAVE_JABBER_SUPPORT
0134   m_jabberClient(new JabberClient()),
0135   m_advertizedHostName(QHostInfo::localHostName()),
0136   m_jabberGameWidget(nullptr),
0137   m_presents(),
0138 #endif
0139   m_newGameSetup(new NewGameSetup(m_automaton))
0140   {
0141   qCDebug(KSIRK_LOG) << "KGameWindow constructor begin";
0142 
0143   statusBar()->addWidget(m_barFlag);
0144 
0145 //   m_accels.setEnabled(true);
0146   
0147   QString iconFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + "/Images/soldierKneeling.png");
0148   if (iconFileName.isNull())
0149   {
0150       KMessageBox::error(nullptr, i18n("Cannot load icon<br>Program cannot continue"), i18n("Error!"));
0151       exit(2);
0152   }
0153   QPixmap icon(iconFileName);
0154 
0155   m_bottomDock = new QDockWidget(this);
0156   m_bottomDock->setObjectName("bottom-dock");
0157   m_bottomDock->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
0158   m_bottomDock->setAllowedAreas(Qt::BottomDockWidgetArea|Qt::TopDockWidgetArea);
0159 
0160   QWidget* titleChatWidget = new QWidget(m_bottomDock);
0161   QHBoxLayout* titleChatLayout = new QHBoxLayout(titleChatWidget);
0162   titleChatWidget->setLayout(titleChatLayout);
0163   titleChatWidget->setFixedHeight(35);
0164 
0165   QWidget* newMessageChat = new QWidget(titleChatWidget);
0166   QHBoxLayout* newMessageChatLayout = new QHBoxLayout(newMessageChat);
0167   newMessageChat->setLayout(newMessageChatLayout);
0168 
0169   KsirkChatModel* chatModel = new KsirkChatModel(m_bottomDock,this);
0170   KsirkChatDelegate* chatDelegate = new KsirkChatDelegate(m_bottomDock);
0171   // m_bottomDock is the KGameChat parent widget
0172   m_chatDlg = new KGameChat(m_automaton, 10000, m_bottomDock,chatModel,chatDelegate);
0173   // TODO: signal does not exist in libkdegames 7.5, research if it ever existed, perhaps emitted from KGameChat::returnPressed
0174   // connect(m_chatDlg, SIGNAL(signalReturnPressed(QString)), this, SLOT(slotChatMessage()));
0175 
0176 
0177   m_upChatFloatPix.load(QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + "/Images/2UpArrow.png"));
0178   m_downChatFloatPix.load(QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + "/Images/2DownArrow.png"));
0179   m_chatIsReduced = false;
0180 
0181   m_titleChatMsg = new QLabel(i18n("No message..."));
0182   QPixmap downChatReducePix(QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + "/Images/downArrow.png"));
0183   m_reduceChatButton = new QPushButton(downChatReducePix,"");
0184   m_floatChatButton = new QPushButton(m_upChatFloatPix,"");
0185   m_reduceChatButton->setFixedSize(30,30);
0186   m_floatChatButton->setFixedSize(30,30);
0187   connect(m_floatChatButton, &QAbstractButton::clicked, this, &KGameWindow::slotChatFloatButtonPressed);
0188   connect(m_bottomDock, &QDockWidget::topLevelChanged, this, &KGameWindow::slotChatFloatChanged);
0189   connect(m_reduceChatButton, &QAbstractButton::clicked, this, &KGameWindow::slotChatReduceButton);
0190 
0191   newMessageChatLayout->addWidget(m_titleChatMsg);
0192   m_titleChatMsg->hide();
0193 
0194   titleChatLayout->addWidget(newMessageChat);
0195   titleChatLayout->addWidget(m_reduceChatButton);
0196   titleChatLayout->addWidget(m_floatChatButton);
0197 
0198   m_bottomDock->setWidget(m_chatDlg);
0199   m_bottomDock->setTitleBarWidget(titleChatWidget);
0200   addDockWidget(Qt::BottomDockWidgetArea, m_bottomDock); // master dockwidget
0201 
0202 //    qCDebug(KSIRK_LOG) << "Before initActions";
0203   initActions();
0204 
0205   qCDebug(KSIRK_LOG) << "Setting up GUI";
0206   setupGUI();
0207 
0208   qCDebug(KSIRK_LOG) << "Creating automaton";
0209   m_automaton->init(this);
0210 
0211   // create a central widget if it doesent' exists
0212   m_centralWidget = new QStackedWidget(this);
0213   setCentralWidget(m_centralWidget);
0214   m_mainMenu = new mainMenu(this, m_centralWidget);
0215   m_mainMenu->init(m_theWorld);
0216   
0217 #if HAVE_JABBER_SUPPORT
0218   /// @FIXME Hides the "Play KsirK over Jabber Network" button while Jabber
0219   /// connection does not work
0220   m_mainMenu->pbJabberGame->hide();
0221 #endif
0222   
0223   m_newGameDialog = new NewGameWidget(m_newGameSetup, m_centralWidget);
0224   connect(m_newGameDialog, &NewGameWidget::newGameOK, this, &KGameWindow::slotNewGameNext);
0225   connect(m_newGameDialog, &NewGameWidget::newGameKO, this, &KGameWindow::slotNewGameKO);
0226   m_newPlayerWidget = new KPlayerSetupWidget(m_centralWidget);
0227   connect(m_newPlayerWidget, &KPlayerSetupWidget::next, this, &KGameWindow::slotNewPlayerNext);
0228   connect(m_newPlayerWidget, &KPlayerSetupWidget::previous, this, &KGameWindow::slotNewPlayerPrevious);
0229   connect(m_newPlayerWidget, &KPlayerSetupWidget::cancel, this, &KGameWindow::slotNewPlayerCancel);
0230   connect(m_newPlayerWidget, &KPlayerSetupWidget::previous, this, &KGameWindow::slotNewPlayerPrevious);
0231   connect(m_newPlayerWidget, &KPlayerSetupWidget::cancel, this, &KGameWindow::slotNewPlayerCancel);
0232 #if HAVE_JABBER_SUPPORT
0233   qCDebug(KSIRK_LOG) << "create the Jabber widget if it doesn't exist";
0234   m_jabberGameWidget = new KsirkJabberGameWidget(m_centralWidget);
0235 #endif
0236   m_centralWidget->addWidget(m_mainMenu); // MAINMENU_INDEX 0
0237   m_centralWidget->addWidget(m_newGameDialog); // NEWGAME_INDEX 1
0238 #if HAVE_JABBER_SUPPORT
0239   m_centralWidget->addWidget(m_jabberGameWidget); // JABBERGAME_INDEX 2
0240 #endif
0241   m_centralWidget->addWidget(m_newPlayerWidget);  // NEWPLAYER_INDEX 3
0242   m_newGameSummaryWidget = new NewGameSummaryWidget(m_centralWidget);
0243   connect(m_newGameSummaryWidget->finishButton, &QAbstractButton::clicked, this, &KGameWindow::slotStartNewGame);
0244   connect(m_newGameSummaryWidget, &NewGameSummaryWidget::previous, this, &KGameWindow::slotNewPlayerPrevious);
0245   connect(m_newGameSummaryWidget, &NewGameSummaryWidget::cancel, this, &KGameWindow::slotNewPlayerCancel);
0246   m_centralWidget->addWidget(m_newGameSummaryWidget);  // NEWGAMESUMMARY_INDEX 4
0247   m_tcpConnectWidget = new TcpConnectWidget(this);
0248   m_centralWidget->addWidget(m_tcpConnectWidget);  // TCPCONNECT_INDEX 5
0249   connect(m_tcpConnectWidget, &TcpConnectWidget::next, this, &KGameWindow::slotConnectToServer);
0250   connect(m_tcpConnectWidget, &TcpConnectWidget::previous, this, &KGameWindow::slotTcpConnectPrevious);
0251   connect(m_tcpConnectWidget, &TcpConnectWidget::cancel, this, &KGameWindow::slotTcpConnectCancel);
0252   m_centralWidget->setCurrentIndex(MAINMENU_INDEX);
0253   m_currentDisplayedWidget = MainMenu;
0254   m_bottomDock->hide();
0255   
0256   
0257 //    qCDebug(KSIRK_LOG) << "Before initStatusBar";
0258   initStatusBar();
0259   
0260   menuBar()-> show();
0261   
0262   explain();
0263   m_automaton->run();
0264   setMouseTracking(true);
0265 
0266   m_timer.setSingleShot(true);
0267   connect(&m_timer, &QTimer::timeout, this, &KGameWindow::evenementTimer);
0268 
0269 #if HAVE_JABBER_SUPPORT
0270   m_initialPresence = XMPP::Status ( "", "", 5, true );
0271 
0272   qCDebug(KSIRK_LOG) << "Connecting Jabber signals";
0273   connect(m_jabberClient, &JabberClient::csDisconnected, this, &KGameWindow::slotCSDisconnected);
0274   connect(m_jabberClient, &JabberClient::csError, this, &KGameWindow::slotCSError);
0275   connect(m_jabberClient, &JabberClient::tlsWarning, this, &KGameWindow::slotHandleTLSWarning);
0276   connect(m_jabberClient, &JabberClient::connected, this, &KGameWindow::slotConnected);
0277   connect(m_jabberClient, &JabberClient::error, this, &KGameWindow::slotClientError);
0278   
0279 //   connect(m_jabberClient, &JabberClient::subscription, this, &KGameWindow::slotSubscription);
0280   connect(m_jabberClient, &JabberClient::rosterRequestFinished, this, &KGameWindow::slotRosterRequestFinished);
0281 //   connect(m_jabberClient, &JabberClient::newContact(XMPP::RosterItem)), this, SLOT (slotContactUpdated(XMPP::RosterItem)) );
0282 //   connect(m_jabberClient, &JabberClient::contactUpdated, this, &KGameWindow::slotContactUpdated);
0283 //   connect(m_jabberClient, &JabberClient::contactDeleted, this, &KGameWindow::slotContactDeleted);
0284 //   connect(m_jabberClient, &JabberClient::resourceAvailable, this, &KGameWindow::slotResourceAvailable);
0285 //   connect(m_jabberClient, &JabberClient::resourceUnavailable, this, &KGameWindow::slotResourceUnavailable);
0286   connect(m_jabberClient, &JabberClient::messageReceived, this, &KGameWindow::slotReceivedMessage);
0287 //   connect(m_jabberClient, &JabberClient::incomingFileTransfer, this, &KGameWindow::slotIncomingFileTransfer);
0288   connect(m_jabberClient, &JabberClient::groupChatJoined, this, &KGameWindow::slotGroupChatJoined);
0289   connect(m_jabberClient, &JabberClient::groupChatLeft, this, &KGameWindow::slotGroupChatLeft);
0290   connect(m_jabberClient, &JabberClient::groupChatPresence, this, &KGameWindow::slotGroupChatPresence);
0291   
0292   connect(m_jabberClient, &JabberClient::groupChatError, this, &KGameWindow::slotGroupChatError);
0293   connect(m_jabberClient, &JabberClient::debugMessage, this, &KGameWindow::slotClientDebugMessage);
0294   
0295   m_jabberClient->setUseXMPP09 ( true );
0296 //     m_jabberClient->setUseSSL ( true );
0297   m_jabberClient->setAllowPlainTextPassword ( true );
0298 
0299   struct utsname utsBuf;
0300   uname (&utsBuf);
0301   m_jabberClient->setClientName ("KsirK");
0302   m_jabberClient->setClientVersion (KAboutData::applicationData().version());
0303   m_jabberClient->setOSName (QString ("%1 %2").arg (utsBuf.sysname, 1).arg (utsBuf.release, 2));
0304   
0305   // Set caps node information
0306   m_jabberClient->setCapsNode("http://ksirk.kde.org/jabber/caps");
0307   m_jabberClient->setCapsVersion(KAboutData::applicationData().version());
0308   
0309   // Set Disco Identity information
0310   DiscoItem::Identity identity;
0311   identity.category = "client";
0312   identity.type = "pc";
0313   identity.name = "KsirK";
0314   m_jabberClient->setDiscoIdentity(identity);
0315 
0316   connect (this, &KGameWindow::newJabberGame, m_automaton, &GameAutomaton::newJabberGame);
0317 #endif
0318 
0319   m_automaton->skin("skins/default");
0320 }
0321 
0322 KGameWindow::~KGameWindow()
0323 {
0324   qCDebug(KSIRK_LOG);
0325 
0326 #if HAVE_JABBER_SUPPORT
0327   if (m_jabberClient != nullptr)
0328   {
0329     delete m_jabberClient;
0330     m_jabberClient = nullptr;
0331   }
0332 #endif
0333   if (m_automaton != nullptr)
0334   {
0335     m_automaton->setGameStatus( KGame::End );
0336     delete m_automaton; m_automaton = nullptr;
0337   }
0338   delete m_backGnd_world; m_backGnd_world = nullptr;
0339   delete m_scene_world; m_scene_world = nullptr;
0340 //   if (m_barFlagButton) {delete m_barFlagButton; m_barFlagButton = 0;}
0341   delete m_frame; m_frame = nullptr;
0342   delete m_backGnd_arena; m_backGnd_arena = nullptr;
0343   delete m_arena; m_arena = nullptr;
0344   delete m_scene_arena; m_scene_arena = nullptr;
0345   delete m_mainMenu; m_mainMenu = nullptr;
0346   delete m_audioPlayer;
0347   delete m_rightDialog;
0348   delete m_defenseDialog;
0349   delete m_newGameSetup;
0350 }
0351 
0352 void KGameWindow::initActions()
0353 {
0354   QAction *action;
0355 
0356   // standard game actions
0357   action = KGameStandardAction::gameNew(this, &KGameWindow::slotNewGame, this);
0358   actionCollection()->addAction(action->objectName(), action);
0359   action = KGameStandardAction::load(this, &KGameWindow::slotOpenGame, this);
0360   actionCollection()->addAction(action->objectName(), action);
0361   m_saveGameAction = KGameStandardAction::save(this, &KGameWindow::slotSaveGame, this);
0362   m_saveGameAction->setEnabled(false);
0363   actionCollection()->addAction(m_saveGameAction->objectName(), m_saveGameAction);
0364   action = KGameStandardAction::quit(this, &KGameWindow::close, this);
0365   actionCollection()->addAction(action->objectName(), action);
0366 
0367   m_zoomInAction = KStandardAction::zoomIn(this, &KGameWindow::slotZoomIn, this);
0368   m_zoomInAction->setEnabled(false);
0369   actionCollection()->addAction(m_zoomInAction->objectName(), m_zoomInAction);
0370 
0371   m_zoomOutAction = KStandardAction::zoomOut(this, &KGameWindow::slotZoomOut, this);
0372   m_zoomOutAction->setEnabled(false);
0373   actionCollection()->addAction(m_zoomOutAction->objectName(), m_zoomOutAction);
0374 
0375   KStandardAction::preferences( this, &KGameWindow::optionsConfigure, actionCollection() );
0376 
0377   QString imageFileName;
0378 #if HAVE_JABBER_SUPPORT
0379   // specific ksirk action
0380   imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, "jabber.png");
0381   //   qCDebug(KSIRK_LOG) << "Trying to load button image file: " << imageFileName;
0382   if (imageFileName.isNull())
0383   {
0384     KMessageBox::error(nullptr, i18n("Cannot load button image %1<br>Program cannot continue",QString("jabber.png")), i18n("Error!"));
0385     exit(2);
0386   }
0387   m_jabberAction = new QAction(QIcon(QPixmap(imageFileName)), i18n("Play over Jabber"), this);
0388   m_jabberAction-> setText(i18n("Play KsirK over the Jabber Network"));
0389   m_jabberAction-> setIconText(i18n("Jabber"));
0390   KActionCollection::setDefaultShortcut(m_jabberAction, Qt::CTRL | Qt::Key_J);
0391   m_jabberAction->setStatusTip(i18n("Allow to connect to a KsirK Jabber Multi User Gaming Room to create new games or to join present games"));
0392   connect(m_jabberAction, &QAction::triggered, this, &KGameWindow::slotJabberGame);
0393   qCDebug(KSIRK_LOG) << "Adding action game_jabber";
0394   actionCollection()->addAction("game_jabber", m_jabberAction);
0395 #endif
0396   // specific ksirk action
0397   imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + '/' + CM_NEWNETGAME);
0398   //   qCDebug(KSIRK_LOG) << "Trying to load button image file: " << imageFileName;
0399   if (imageFileName.isNull())
0400   {
0401     KMessageBox::error(nullptr, i18n("Cannot load button image %1<br>Program cannot continue",QString(CM_NEWNETGAME)), i18n("Error!"));
0402     exit(2);
0403   }
0404   QAction * newSocketAction = new QAction(QIcon(QPixmap(imageFileName)), i18n("New Standard TCP/IP Network Game"), this);
0405   newSocketAction->setIconText(i18n("New TCP/IP"));
0406   KActionCollection::setDefaultShortcut(newSocketAction, Qt::CTRL | Qt::Key_T);
0407   newSocketAction->setStatusTip(i18n("Create a new standard TCP/IP network game"));
0408   connect(newSocketAction, &QAction::triggered, this, &KGameWindow::slotNewSocketGame);
0409   qCDebug(KSIRK_LOG) << "Adding action game_new_socket";
0410   actionCollection()->addAction("game_new_socket", newSocketAction);
0411   
0412                                      
0413   // specific ksirk action
0414   imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + '/' + CM_NEWNETGAME);
0415   //   qCDebug(KSIRK_LOG) << "Trying to load button image file: " << imageFileName;
0416   if (imageFileName.isNull())
0417   {
0418     KMessageBox::error(nullptr, i18n("Cannot load button image %1<br>Program cannot continue",QString(CM_NEWNETGAME)), i18n("Error!"));
0419     exit(2);
0420   }
0421   QAction * joinAction = new QAction(QIcon(QPixmap(imageFileName)),
0422         i18n("Join a Standard TCP/IP Network Game"), this);
0423   joinAction->setIconText(i18n("Join TCP/IP"));
0424   KActionCollection::setDefaultShortcut(joinAction, Qt::CTRL | Qt::SHIFT | Qt::Key_J);
0425   joinAction->setStatusTip(i18n("Join a standard TCP/IP network game"));
0426   connect(joinAction, &QAction::triggered, this, &KGameWindow::slotJoinNetworkGame);
0427    qCDebug(KSIRK_LOG) << "Adding action game_join_socket";
0428   actionCollection()->addAction("game_join_socket", joinAction);
0429 
0430   m_goalAction = new QAction(i18n("Goal"), this);
0431   m_goalAction-> setText(i18n("Display the Current Player's Goal"));
0432   m_goalAction-> setIconText("  ");
0433   KActionCollection::setDefaultShortcut(m_goalAction, Qt::CTRL | Qt::Key_G);
0434   m_goalAction->setStatusTip(i18n("Display the current player's goal"));
0435   connect(m_goalAction, &QAction::triggered, this, &KGameWindow::slotShowGoal);
0436   m_goalAction->setVisible(false);
0437   qCDebug(KSIRK_LOG) << "Adding action game_goal";
0438   actionCollection()->addAction("game_goal", m_goalAction);
0439   
0440   m_contextualHelpAction = new QAction(
0441         i18n("Contextual Help"), this);
0442   m_contextualHelpAction->setEnabled(false);
0443   KActionCollection::setDefaultShortcut(m_contextualHelpAction, Qt::CTRL | Qt::Key_F1);
0444   connect(m_contextualHelpAction, &QAction::triggered, this, &KGameWindow::slotContextualHelp);
0445   actionCollection()->addAction("help_contextual", m_contextualHelpAction);
0446 
0447 
0448   QString nextPlayerActionImageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + '/' + CM_NEXTPLAYER);
0449   m_nextPlayerAction =  new QAction(QIcon(nextPlayerActionImageFileName),
0450         i18n("Next Player"), this);
0451   connect(m_nextPlayerAction, &QAction::triggered, this, &KGameWindow::slotNextPlayer);
0452   m_contextualHelpAction->setStatusTip(i18n("Lets the next player play"));
0453   m_nextPlayerAction->setEnabled(false);
0454   actionCollection()->addAction("game_nextplayer", m_nextPlayerAction);
0455 
0456   QAction * finishMovesAction = new QAction(
0457         i18n("Finish moves"), this);
0458   KActionCollection::setDefaultShortcut(finishMovesAction, Qt::Key_Space);
0459   finishMovesAction->setStatusTip(i18n("Finish moving the current sprites"));
0460   connect(finishMovesAction, &QAction::triggered, this, &KGameWindow::slotFinishMoves);
0461   actionCollection()->addAction("game_finish_moves", finishMovesAction);
0462 
0463 
0464 }
0465 
0466 void KGameWindow::initStatusBar()
0467 {
0468   statusBar()-> setSizeGripEnabled(true);
0469   //QT5 statusBar()->insertPermanentItem("", ID_STATUS_MSG, 2);
0470   //QT5 statusBar()-> setItemAlignment(ID_STATUS_MSG, Qt::AlignLeft | Qt::AlignVCenter);
0471 
0472   //QT5 statusBar()->insertPermanentItem("", ID_STATUS_MSG2, 3);
0473   //QT5 statusBar()-> setItemAlignment(ID_STATUS_MSG2, Qt::AlignLeft | Qt::AlignVCenter);
0474   //QT5 statusBar()->addPermanentWidget(m_barFlag);
0475 }
0476 
0477 Country* KGameWindow::clickIn(const QPointF &pointf)
0478 {
0479 //   qCDebug(KSIRK_LOG) << "KGameWindow::clickIn " << pointf;
0480  /* if(isMyState(GameLogic::GameAutomaton::INIT) || m_theWorld-> countryAt( pointf )==0)
0481   {
0482     m_rightDock->hide();
0483   }*/
0484   return m_theWorld-> countryAt( pointf );
0485 }
0486 
0487 Player* KGameWindow::currentPlayer()
0488 {
0489 //   qCDebug(KSIRK_LOG) << "KGameWindow::currentPlayer";
0490   Player* current = m_automaton->currentPlayer();
0491 
0492   return current;
0493 }
0494 
0495 void KGameWindow::loadDices()
0496 {
0497   qCDebug(KSIRK_LOG);
0498   
0499   m_dices[Blue] = QList<QPixmap>();
0500   m_dices[Red] = QList<QPixmap>();
0501   m_dices[Blue].push_back(buildDice("bluedice1"));
0502   m_dices[Blue].push_back(buildDice("bluedice2"));
0503   m_dices[Blue].push_back(buildDice("bluedice3"));
0504   m_dices[Blue].push_back(buildDice("bluedice4"));
0505   m_dices[Blue].push_back(buildDice("bluedice5"));
0506   m_dices[Blue].push_back(buildDice("bluedice6"));
0507   m_dices[Red].push_back(buildDice("reddice1"));
0508   m_dices[Red].push_back(buildDice("reddice2"));
0509   m_dices[Red].push_back(buildDice("reddice3"));
0510   m_dices[Red].push_back(buildDice("reddice4"));
0511   m_dices[Red].push_back(buildDice("reddice5"));
0512   m_dices[Red].push_back(buildDice("reddice6"));
0513 }
0514 
0515 QPixmap KGameWindow::buildDice(const QString& id)
0516 {
0517   qCDebug(KSIRK_LOG);
0518 
0519   QSize size(32,32);
0520   const qreal dpr = qApp->devicePixelRatio();
0521   QPixmap pixmap(size * dpr);
0522   pixmap.fill(Qt::transparent);
0523   QPainter p(&pixmap);
0524   if (m_theWorld != nullptr)
0525   {
0526     m_theWorld->renderer()->render(&p, id);
0527   }
0528   pixmap.setDevicePixelRatio(dpr);
0529 
0530   return pixmap;
0531 }
0532 
0533 QPixmap KGameWindow::getDice(DiceColor color, int num)
0534 {
0535   if(num==0 || num==-1)
0536 {return QPixmap();}
0537   else {return m_dices[color][num-1];}
0538 }
0539 
0540 void KGameWindow::newSkin(const QString& onuFileName)
0541 {
0542   qCDebug(KSIRK_LOG) << onuFileName;
0543   clear();
0544 
0545   m_animFighters->clear();
0546   foreach(AnimSpritesGroup* sprites, m_animSpritesGroups)
0547   {
0548     sprites->clear();
0549     delete sprites;
0550   }
0551   m_animSpritesGroups.clear();
0552 
0553   if (m_centralWidget != nullptr)
0554   {
0555     m_centralWidget->setCurrentIndex(-1);
0556   }
0557 
0558 // NOTE:I wanted to recreate the automaton here. But it isn't possible as this
0559 // method is called from inside a GameAutomaton method. Furthermore, it isn't
0560 // a good solution because the central KGame object should not be recreated
0561 // but reinitialized as needed
0562 //   m_automaton->init(0);
0563 //   delete m_automaton;
0564 //   m_automaton = new GameAutomaton();
0565 //   m_automaton->init(this);
0566 
0567   m_mouseLocalisation = nullptr;
0568   if (m_theWorld != nullptr)
0569   {
0570 //     m_theWorld-> reset();
0571     delete m_theWorld;
0572     m_theWorld = nullptr;
0573   }
0574 
0575   QString onuDefinitionFileName = onuFileName;
0576   if (onuDefinitionFileName.isEmpty())
0577   {
0578     onuDefinitionFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + "/Data/world.desktop");
0579   }
0580   else if (!QFile::exists(onuDefinitionFileName))
0581   {
0582     onuDefinitionFileName.clear();
0583   }
0584   if (onuDefinitionFileName.isEmpty())
0585   {
0586       KMessageBox::error(nullptr,
0587           i18n("World definition file not found - Verify your installation<br>Program cannot continue"), i18n("Error!"));
0588       exit(2);
0589   }
0590   // Bug 308527. Need to remove all goals on new game. Only goals for selected skin will be loaded.
0591   m_automaton->removeAllGoals();
0592   qCDebug(KSIRK_LOG) << "Got World definition file name: " <<  onuDefinitionFileName;
0593   m_theWorld = new ONU(m_automaton, onuDefinitionFileName);
0594   if (m_theWorld->skin().isEmpty())
0595   {
0596     delete m_theWorld;
0597     m_theWorld = nullptr;
0598   }
0599   loadDices();
0600 
0601   // put the size to the window size if it's the main menu
0602   int width;
0603   int height;
0604   if (m_scene_arena == nullptr || m_theWorld == nullptr)
0605   {
0606      width = 2000;
0607      height = 2000;
0608   }
0609   else
0610   {
0611      width = m_theWorld->width();
0612      height = m_theWorld->height();
0613   }
0614 
0615   //Creation of the arena background
0616   if (m_backGnd_arena != nullptr)
0617   {
0618     qCDebug(KSIRK_LOG) << "Before m_backGnd_arena delete";
0619     delete m_backGnd_arena;
0620   }
0621   //Creation of the background
0622   if (m_backGnd_world != nullptr)
0623   {
0624     qCDebug(KSIRK_LOG) << "Before m_backGnd_world delete";
0625     delete m_backGnd_world;
0626   }
0627 
0628   // create the arena view
0629   if (m_scene_arena != nullptr)
0630   {
0631     qCDebug(KSIRK_LOG) << "Before m_scene_arena delete";
0632     delete m_scene_arena;
0633   }
0634   m_scene_arena = new QGraphicsScene(0, 0, width, height,this);
0635 
0636   if (m_frame != nullptr)
0637   {
0638     m_frame->setUpdatesEnabled(false);
0639     m_uparrow = nullptr;
0640     m_downarrow = nullptr;
0641     m_leftarrow = nullptr;
0642     m_rightarrow = nullptr;
0643     m_centralWidget->removeWidget(m_frame);
0644     delete m_frame;
0645     m_frame = nullptr;
0646   }
0647   if (m_scene_world != nullptr)
0648   {
0649     qCDebug(KSIRK_LOG) << "Before m_scene_world delete";
0650     delete m_scene_world;
0651   }
0652   m_scene_world = new QGraphicsScene(0, 0, width, height,this);
0653 
0654   qCDebug(KSIRK_LOG) << "create the world map view";
0655   if (m_theWorld != nullptr)
0656   {
0657     m_frame = new DecoratedGameFrame(m_centralWidget, width, height, m_automaton);
0658     m_frame->setMaximumWidth(width);
0659     m_frame->setMaximumHeight(height);
0660     m_frame->setCacheMode( QGraphicsView::CacheBackground );
0661     m_frame->setIcon();
0662   }
0663   
0664   if (m_arena != nullptr)
0665   {
0666     m_centralWidget->removeWidget(m_arena);
0667     delete m_arena;
0668     m_arena = nullptr;
0669   }
0670   if (m_theWorld != nullptr)
0671   {
0672     m_arena = new FightArena(m_centralWidget, width, height, m_scene_arena, m_theWorld, m_automaton);
0673     m_arena->setMaximumWidth(width);
0674     m_arena->setMaximumHeight(height);
0675     m_arena->setCacheMode( QGraphicsView::CacheBackground );
0676   }
0677   
0678   qCDebug(KSIRK_LOG) << "put the menu, map and arena in the central widget";
0679   if (m_frame != nullptr)
0680   {
0681     m_centralWidget->addWidget(m_frame); // MAP_INDEX 6
0682   }
0683   if (m_arena != nullptr)
0684   {
0685     m_centralWidget->addWidget(m_arena); // ARENA_INDEX 7
0686   }
0687   
0688   if (m_theWorld == nullptr)
0689   {
0690     return;
0691   }
0692   m_backGnd_arena = new BackGnd(m_scene_arena, m_theWorld, true);
0693   m_backGnd_world = new BackGnd(m_scene_world, m_theWorld);
0694 
0695 //   m_scene_world->setDoubleBuffering(true);
0696   qCDebug(KSIRK_LOG) << "Before initView";
0697   initView();
0698   qCDebug(KSIRK_LOG) <<"After m_backGnd new="<< m_backGnd_world;
0699   m_frame->setFocus();
0700 
0701   m_uparrow = new Sprites::ArrowSprite(Qt::UpArrow, m_backGnd_world);
0702   m_uparrow->setZValue(1000);
0703   QPointF pos = m_frame->mapToScene(QPoint(m_frame->viewport()->width()/2,0));
0704   pos = pos + QPointF(-(m_uparrow->boundingRect().width()/2),m_uparrow->boundingRect().height());
0705   m_uparrow->setPos(pos);
0706   m_uparrow->setActive(false);
0707   
0708   m_downarrow = new Sprites::ArrowSprite(Qt::DownArrow, m_backGnd_world);
0709   m_downarrow->setZValue(1000);
0710   pos = m_frame->mapToScene(QPoint(m_frame->viewport()->width()/2,m_frame->viewport()->height()));
0711   pos = pos - QPointF(m_downarrow->boundingRect().width()/2,m_downarrow->boundingRect().height());
0712   m_downarrow->setPos(pos);
0713   m_downarrow->setActive(false);
0714   pos = m_frame->mapToScene(QPoint(0,m_frame->viewport()->height()/2));
0715   
0716   m_leftarrow = new Sprites::ArrowSprite(Qt::LeftArrow, m_backGnd_world);
0717   m_leftarrow->setZValue(1000);
0718   pos = pos + QPointF(m_leftarrow->boundingRect().width(),-(m_leftarrow->boundingRect().height()/2));
0719   m_leftarrow->setPos(pos);
0720   m_leftarrow->setActive(false);
0721   
0722   m_rightarrow = new Sprites::ArrowSprite(Qt::RightArrow, m_backGnd_world);
0723   m_rightarrow->setZValue(1000);
0724   pos = m_frame->mapToScene(QPoint(m_frame->viewport()->width(),m_frame->viewport()->height()/2));
0725   pos = pos - QPointF(m_rightarrow->boundingRect().width(),m_rightarrow->boundingRect().height()/2);
0726   m_rightarrow->setPos(pos);
0727   m_rightarrow->setActive(false);
0728   
0729   qCDebug(KSIRK_LOG) <<"End new skin";
0730 }
0731 
0732 KRightDialog * KGameWindow::getRightDialog()
0733 {
0734   return m_rightDialog;
0735 }
0736 
0737 void KGameWindow::initView()
0738 {
0739   qCDebug(KSIRK_LOG);
0740   QString iconFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + "/Images/soldierKneeling.png");
0741   if (iconFileName.isNull())
0742   {
0743       KMessageBox::error(nullptr, i18n("Cannot load icon<br>Program cannot continue"), i18n("Error!"));
0744       exit(2);
0745   }
0746 // to port : still necessary ?
0747 //   m_frame->setIcon(QPixmap(iconFileName));
0748 
0749   disconnectMouse();
0750   reconnectMouse();
0751   setCaption("KsirK",false);
0752   m_scene_world-> update();
0753   m_frame->setScene(m_scene_world);
0754   
0755   m_scene_arena-> update();
0756   m_arena->setScene(m_scene_arena);
0757 
0758   //ADD a dock widget on the right
0759 
0760   if (m_rightDialog != nullptr)
0761   {
0762     m_rightDialog->hide();
0763     delete m_rightDialog;
0764   }
0765 
0766   if (m_rightDock != nullptr)
0767   {
0768     m_rightDock->hide();
0769     delete m_rightDock;
0770   }
0771   m_rightDock = new QDockWidget(this);
0772   m_rightDock->setObjectName("right-dock");
0773   m_rightDock->setAllowedAreas(Qt::RightDockWidgetArea | Qt::LeftDockWidgetArea);
0774   m_rightDock->setFeatures(QDockWidget::NoDockWidgetFeatures);
0775 
0776   m_rightDialog = new KRightDialog(m_rightDock,theWorld(),this);
0777   m_rightDock->setWidget(m_rightDialog);
0778   qCDebug(KSIRK_LOG) << "hiding right dock";
0779   m_rightDock->hide();
0780   addDockWidget(Qt::RightDockWidgetArea, m_rightDock);
0781   m_frame->setFocus();
0782 }
0783 
0784 bool KGameWindow::attackEnd()
0785 {
0786   qCDebug(KSIRK_LOG);
0787   if (m_firstCountry==nullptr || m_secondCountry == nullptr)
0788   {
0789     return false;
0790   }
0791 
0792   m_firstCountry->releaseHighlightingLock();
0793   m_firstCountry->clearHighlighting();
0794   m_secondCountry->releaseHighlightingLock();
0795   m_secondCountry->clearHighlighting();
0796 
0797   // Bug 315491.
0798   bool playerDeleted = false;
0799   bool res = false;
0800   QString mes = "";
0801   qCDebug(KSIRK_LOG) << "There is now " << m_secondCountry-> nbArmies() << " armies in " << m_secondCountry->name() << ".";
0802   if (m_secondCountry-> nbArmies() < 1)
0803   {
0804     QPixmap pm = currentPlayer()->getFlag()->image(0);
0805 
0806     KMessageParts messageParts;
0807     messageParts << pm << kli18n("<font color=\"red\">%1 conquered %2 from %3</font>").untranslatedText() << currentPlayer()->name() << m_secondCountry-> name() << m_firstCountry-> name();
0808     broadcastChangeItem(messageParts, ID_NO_STATUS_MSG);
0809     
0810     Player* oldOwner = m_secondCountry-> owner();
0811     unsigned int newOldOwnerNbCountries = oldOwner-> getNbCountries() - 1;
0812     
0813     if (m_automaton->isAdmin())
0814     {
0815       currentPlayer()-> incrNbCountries();
0816       oldOwner-> decrNbCountries();
0817     }
0818 
0819     m_secondCountry-> owner(currentPlayer());
0820     m_secondCountry-> nbArmies(currentPlayer()->getNbAttack());
0821     m_firstCountry-> decrNbArmies(currentPlayer()->getNbAttack());
0822     m_scene_world-> update();
0823     if (m_firstCountry->nbArmies() > 1)
0824     {
0825       res = true;
0826     }
0827     qCDebug(KSIRK_LOG) << oldOwner-> name() << " now owns " << newOldOwnerNbCountries << " countries.";
0828     if (newOldOwnerNbCountries == 0)
0829     {
0830       QString oldOwnerId = oldOwner->name();
0831       showMessage(i18n("%1, you are defeated! Bye, bye...",oldOwner->name()), 10, ForceShowing);
0832 /*      KMessageBox::information(this,
0833                                i18n("%1, you are defeated! Bye, bye...",oldOwner->name()),
0834                                i18n("KsirK - Game Over!"));*/
0835       if (m_automaton->isAdmin())
0836       {
0837         // Bug 315491.
0838         playerDeleted = true;
0839         qCDebug(KSIRK_LOG) << "Removing player " << oldOwner-> name();
0840         int i = m_automaton->playerList()->indexOf(oldOwner);
0841         if (i != -1)
0842           delete m_automaton->playerList()->takeAt(i);
0843         qCDebug(KSIRK_LOG) << "There is now " << m_automaton->playerList()->count() << " players";
0844         m_automaton->setMinPlayers(m_automaton->playerList()->count());
0845         m_automaton->setGameStatus(KGame::Run);
0846       }
0847       if ( m_automaton->isAdmin()
0848         && ( ( m_automaton->useGoals()
0849              && ( currentPlayer()->goal().type() == GameLogic::Goal::GoalPlayer)
0850              && ( *currentPlayer()->goal().players().begin() == oldOwnerId ) )
0851            || (m_automaton->playerList()->count() == 1) ) )
0852       {
0853         m_automaton->state(GameLogic::GameAutomaton::GAME_OVER);
0854         QByteArray buffer;
0855         QDataStream stream(&buffer, QIODevice::WriteOnly);
0856         stream << currentPlayer()->id();
0857         m_automaton->sendMessage(buffer,Winner);
0858         res = false;
0859       }
0860       else if (m_automaton->isAdmin())
0861       {
0862         foreach (KPlayer* player, *m_automaton->playerList())
0863         {
0864           m_automaton->checkGoal((Player*)player);
0865         }
0866       }
0867     }
0868     else if (m_automaton->isAdmin())
0869     {
0870       m_automaton->checkGoal();
0871     }
0872   }
0873   // Bug 315491.
0874   if (!playerDeleted)
0875   {
0876     if (backGnd()->bgIsArena())
0877     {
0878       m_arena->countryAttack()->createArmiesSprites();
0879       m_arena->countryDefense()->createArmiesSprites();
0880     }
0881     else
0882     {
0883       m_firstCountry->createArmiesSprites();
0884       m_secondCountry->createArmiesSprites();
0885     }
0886   }
0887   if (m_automaton->isAdmin())
0888   {
0889     if (res)
0890     {
0891       QByteArray buffer;
0892       QDataStream stream(&buffer, QIODevice::WriteOnly);
0893       m_automaton->sendMessage(buffer,StartLocalCurrentAI);
0894     }
0895     else
0896     {
0897       if (m_firstCountry->nbArmies() < 2 || !m_automaton->isAttackAuto())
0898       {
0899         QByteArray buffer;
0900         QDataStream stream(&buffer, QIODevice::WriteOnly);
0901         m_automaton->sendMessage(buffer,ClearHighlighting);
0902         KMessageParts messageParts;
0903         messageParts << kli18n("%1: it is up to you again").untranslatedText() << currentPlayer()-> name();
0904         broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
0905       }
0906     }
0907   }
0908   m_automaton->setGameStatus(KGame::Run);
0909   return res;
0910 }
0911 
0912 void KGameWindow::winner(const Player* player)
0913 {
0914   qCDebug(KSIRK_LOG) << player->name();
0915   QString msg = i18n("%1 won!");
0916   if (!player->isVirtual())
0917   {
0918     msg = i18n("<big><b>%1</b>, you won!</big>");
0919   }
0920   if (m_automaton->useGoals())
0921   {
0922     msg += i18n("<br>Winner's goal was stated like this:<br><i>%1</i><br><br>Do you want to play again?", player->goal().message());
0923   }
0924   else
0925   {
0926     if (!player->isVirtual())
0927     {
0928       msg += i18n("<br>You conquered all the world!");
0929     }
0930     else
0931     {
0932       msg += i18n("<br>He conquered all the world!");
0933     }
0934   }
0935   RestartOrExitDialogImpl* restartDia = new RestartOrExitDialogImpl(i18n(msg.toUtf8().data(),player->name()));
0936               
0937   connect(restartDia->newGameButton, &QAbstractButton::clicked, this, &KGameWindow::slotNewGame);
0938   connect(restartDia->exitButton, &QAbstractButton::clicked, this, &KGameWindow::slotExit);
0939 
0940   restartDia->show();
0941 }
0942 
0943 void KGameWindow::resolveAttack()
0944 {
0945 
0946 //    qCDebug(KSIRK_LOG) << "KGameWindow::resolveAttack";
0947 
0948   int A1 = -1; int A2 = -1; int A3 = -1; int AE = -1;
0949   int D1 = -1; int D2 = -1; int DE = -1;
0950 
0951   NKD = NKA = 0;
0952   if (currentPlayer() == nullptr || m_secondCountry == nullptr || m_secondCountry->owner() == nullptr || m_firstCountry == nullptr)
0953     return;
0954 
0955   int secondOldNbArmies = m_secondCountry->nbArmies();
0956 
0957   A1 = Dice::roll();
0958   if (currentPlayer()-> getNbAttack() > 1) A2 = Dice::roll();
0959   if (currentPlayer()-> getNbAttack() > 2) A3 = Dice::roll();
0960   if ((A1>=A2)&&(A1>=A3))  // A1 is the greater ; don't move it; look at the two others
0961     if (A2>=A3) {} // A2 greater than A3 ; don't move
0962     else {AE = A2;A2 = A3;A3 = AE;} // A2 lesser than A3 ; swap them
0963   else
0964   { // A1 is not the greater
0965     if (A2>=A3) {AE=A1;A1=A2;A2=AE;}  // A2 is greater than A3, so it is the greater; swap it with A1
0966     else {AE=A1;A1=A3;A3=AE;} // A3 is greater than A2, so it is the greater; swap it with A1
0967                                             // now the new A1 is the greater, look at the 2 others
0968     if (A2>=A3) {} // A2 greater than A3, nothing to do
0969     else {AE=A2;A2=A3;A3=AE;} // A2 lesser than A3; swap them
0970   }
0971   D1 = Dice::roll();
0972   if (m_secondCountry-> owner()-> getNbDefense() > 1)
0973     D2 = Dice::roll();
0974   if (D2>D1) {DE=D1;D1=D2;D2=DE;}
0975   if (A1>D1)
0976   {
0977     QByteArray buffer;
0978     QDataStream stream(&buffer, QIODevice::WriteOnly);
0979     stream << m_secondCountry->name() << quint32(1);
0980     m_automaton->sendMessage(buffer,DecrNbArmies);
0981     NKD++;
0982   }
0983   else
0984   {
0985     QByteArray buffer;
0986     QDataStream stream(&buffer, QIODevice::WriteOnly);
0987     stream << m_firstCountry->name() << quint32(1);
0988     m_automaton->sendMessage(buffer,DecrNbArmies);
0989     NKA++;
0990   }
0991   if ((A2>0)&&(D2>0))
0992   {
0993     if (A2>D2)
0994     {
0995       QByteArray buffer;
0996       QDataStream stream(&buffer, QIODevice::WriteOnly);
0997       stream << m_secondCountry->name() << quint32(1);
0998       m_automaton->sendMessage(buffer,DecrNbArmies);
0999       NKD++;
1000     }
1001     else
1002     {
1003       QByteArray buffer;
1004       QDataStream stream(&buffer, QIODevice::WriteOnly);
1005       stream << m_firstCountry->name() << quint32(1);
1006       m_automaton->sendMessage(buffer,DecrNbArmies);
1007       NKA++;
1008     }
1009   }
1010 //   qCDebug(KSIRK_LOG) << "(" << A1<<", "<<A2<<", "<<A3<<") <-> ("<<D1<<", "<<D2<<")" ;
1011 //   qCDebug(KSIRK_LOG) << "Attacker loses " << NKA<<" armies; Defender loses "<<NKD<<" armies." ;
1012   
1013   QByteArray buffer3;
1014   QDataStream stream3(&buffer3, QIODevice::WriteOnly);
1015   stream3 << (quint32)A1 << (quint32)A2 << (quint32)A3 << (quint32)D1 << (quint32)D2 << (quint32)NKA << (quint32)NKD << (quint32)(secondOldNbArmies-NKD < 1);
1016   qCDebug(KSIRK_LOG) << "sending DisplayFightResult";
1017   m_automaton->sendMessage(buffer3,DisplayFightResult);
1018 
1019   QByteArray buffer2;
1020   QDataStream stream2(&buffer2, QIODevice::WriteOnly);
1021   
1022   if ((NKD != 0)&&(NKA != 0)) stream2 << quint32(2);
1023   else if (NKA != 0) stream2 << quint32(0);
1024   else if (NKD != 0) stream2 << quint32(1);
1025   m_automaton->sendMessage(buffer2,AnimExplosion);
1026 
1027   //qCDebug(KSIRK_LOG)<< "A1:"<< A1<<", A2: " <<A2 <<"A3:" << A3;
1028   //qCDebug(KSIRK_LOG)<< "D1:"<< D1<<", D2: " <<D2;
1029   // if arena is displayed, update the arena countries too
1030   if (currentWidgetType() == Arena) {
1031     arena()->countryAttack()->decrNbArmies(NKA);
1032     arena()->countryDefense()->decrNbArmies(NKD);
1033   }
1034   m_secondCountry-> owner()-> setNbDefense(0);
1035 }
1036 
1037 
1038 
1039 /**
1040   * Reimplementation of the inherited function called when a window close event arise
1041   */
1042 bool KGameWindow::queryClose()
1043 {
1044   qCDebug(KSIRK_LOG);
1045 
1046   if ((m_automaton->state() == GameAutomaton::INIT) || (m_automaton->state() ==  GameAutomaton::INTERLUDE))
1047   {
1048     switch ( KMessageBox::warningTwoActions( this,
1049                                         i18n("Do you want to quit the game?"),
1050                                         QString(),
1051                                         KGuiItem(i18nc("@action:button", "Quit Game")),
1052                                         KStandardGuiItem::cancel()) )
1053     {
1054     case KMessageBox::PrimaryAction :
1055         break;
1056     default:
1057         return false;
1058     }
1059   }
1060   else
1061   {
1062     switch ( KMessageBox::warningTwoActionsCancel( this,
1063                                               i18n("Before you quit, do you want to save your game?"),
1064                                               QString(),
1065                                               KStandardGuiItem::save(),
1066                                               KStandardGuiItem::discard()) )
1067     {
1068     case KMessageBox::PrimaryAction :
1069         slotSaveGame();
1070         break;
1071     case KMessageBox::SecondaryAction :
1072         break;
1073     default: // cancel
1074         return false;
1075     }
1076   }
1077 //   hide();
1078   disconnect(&m_timer, &QTimer::timeout, this, &KGameWindow::evenementTimer);
1079   disconnectMouse();
1080   m_mouseLocalisation = nullptr;
1081   m_automaton->setGameStatus(KGame::End);
1082   
1083 /*  if (m_theWorld != 0)
1084   {
1085     delete m_theWorld;
1086     m_theWorld = 0;
1087   }
1088   while (!m_automaton->playerList()->isEmpty())
1089   {
1090     delete m_automaton->playerList()->takeFirst();
1091   }
1092   delete m_automaton; m_automaton = 0;*/
1093   KSharedConfig::openConfig()->sync();
1094   return true;
1095 }
1096 
1097 bool KGameWindow::actionOpenGame()
1098 {
1099   qCDebug(KSIRK_LOG) << "KGameWindow::actionOpenGame";
1100 
1101   QString fileName = QFileDialog::getOpenFileName(this, i18nc("@title:window", "KsirK - Load Game"), QString(), "*.xml");
1102   if (!fileName.isEmpty())
1103   {
1104     m_fileName = fileName;
1105     m_automaton->setGameStatus(KGame::End);
1106     m_waitedPlayers.clear();
1107     qCDebug(KSIRK_LOG) << "KGameWindow::actionOpenGame loader";
1108     Ksirk::SaveLoad::GameXmlLoader loader(fileName, *this, m_waitedPlayers);
1109     qCDebug(KSIRK_LOG) << "KGameWindow::actionOpenGame loading done";
1110     for (unsigned int i = 0; i < m_theWorld->getNbCountries(); i++)
1111     {
1112       Country* country = m_theWorld-> getCountries().at(i);
1113       qCDebug(KSIRK_LOG) << "Adding sprites to " << country->name();
1114       country-> createArmiesSprites();
1115       Player *player = country-> owner();
1116       if (player)
1117       {
1118         country-> flag(player->flagFileName(), m_backGnd_world);
1119       }
1120     }
1121     m_backGnd_world->hide();
1122     m_backGnd_world->show();
1123     if (m_waitedPlayers.empty())
1124     {
1125       QByteArray buffer;
1126       QDataStream stream(&buffer, QIODevice::WriteOnly);
1127       m_automaton->sendMessage(buffer,StartGame);
1128       m_automaton->sendMessage(buffer,ClearHighlighting);
1129       m_frame->setFocus();
1130       qCDebug(KSIRK_LOG) << "KGameWindow::actionOpenGame false1";
1131       m_frame->setArenaOptionEnabled(true);
1132       reduceChat();
1133 
1134       return false;
1135     }
1136     else
1137     {
1138       KMessageParts messageParts;
1139       messageParts << kli18n("Waiting for the connection of %1 network players.").untranslatedText() << QString::number(m_waitedPlayers.size());
1140       broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
1141       qCDebug(KSIRK_LOG) << "KGameWindow::actionOpenGame true";
1142       unreduceChat();
1143       m_frame->setArenaOptionEnabled(false);
1144       return true;
1145     }
1146   }
1147   qCDebug(KSIRK_LOG) << "KGameWindow::actionOpenGame false2";
1148   return false;
1149 }
1150 
1151 void KGameWindow::displayRecyclingButtons()
1152 {
1153   qCDebug(KSIRK_LOG);
1154   if (m_automaton->allLocalPlayersComputer())
1155   {
1156 //     qCDebug(KSIRK_LOG) << "There is only computer local players";
1157     PlayersArray::iterator it = m_automaton->playerList()->begin();
1158     PlayersArray::iterator it_end = m_automaton->playerList()->end();
1159     for (; it != it_end; it++)
1160     {
1161 //       qCDebug(KSIRK_LOG) << "Looking at player " << (*it)->name() 
1162 //               << ". is AI  : " << ((Player*)(*it))->isAI() 
1163 //               << ". isRunning: " << ((static_cast<AIPlayer *>(*it))-> isRunning())
1164 //               << ". virtual: " << (*it)->isVirtual() 
1165 //                      ;
1166       if ( ((Player*)(*it))->isAI() 
1167            && (!(static_cast<AIPlayer *>(*it))-> isRunning())
1168         && (!(*it)->isVirtual()) ) 
1169       {
1170 //         qCDebug(KSIRK_LOG) << "Starting computer player " << (*it)->name();
1171         (static_cast<AIPlayer *>(*it))-> start();
1172         break;
1173       }
1174     }
1175   }
1176   else
1177   {
1178     m_rightDock->show();
1179   }
1180   m_nextPlayerAction->setEnabled(false);
1181 }
1182 
1183 void KGameWindow::clearHighlighting()
1184 {
1185   qCDebug(KSIRK_LOG);
1186   if (m_firstCountry != nullptr)
1187   {
1188     m_firstCountry->releaseHighlightingLock();
1189     m_firstCountry->clearHighlighting();
1190     m_firstCountry = nullptr;
1191   }
1192   if (m_secondCountry != nullptr)
1193   {
1194     m_secondCountry->releaseHighlightingLock();
1195     m_secondCountry->clearHighlighting();
1196     m_secondCountry = nullptr;
1197   }
1198 
1199   if (currentPlayer() && currentPlayer()-> isAI() && (!currentPlayer()->isVirtual()))
1200   {
1201     if (!(static_cast<AIPlayer *>(currentPlayer()))-> isRunning()) (static_cast<AIPlayer *>(currentPlayer()))-> start();
1202     m_nextPlayerAction->setEnabled(false);
1203   }
1204   else if (currentPlayer() && !currentPlayer()->isVirtual())
1205   {
1206     slotContextualHelp();
1207     m_nextPlayerAction->setEnabled(true);
1208   }
1209   else
1210   {
1211     m_nextPlayerAction->setEnabled(false);
1212   }
1213 }
1214 
1215 QString KGameWindow::defenseLabel()
1216 {
1217   if (firstCountry() && firstCountry()->owner() && secondCountry())
1218     return i18np("<font color=\"red\">%2</font> attacks you from <font color=\"red\">%3</font> with 1 army!<br> How do you want to defend <font color=\"blue\">%4</font>?",
1219                         "<font color=\"red\">%2</font> attacks you from <font color=\"red\">%3</font> with %1 armies!<br> How do you want to defend <font color=\"blue\">%4</font>?",
1220                         QString::number(this->firstCountry()->owner()->getNbAttack()),
1221                         this->firstCountry()->owner()->name(),
1222                         this->firstCountry()->name(),
1223                         this->secondCountry()->name());
1224   else
1225     return "";
1226 }
1227 
1228 void KGameWindow::createDefenseDialog()
1229 {
1230   qCDebug(KSIRK_LOG);
1231   // Create Window Dialog
1232   m_defenseDialog = new QDialog ();
1233 
1234   QWidget* widget = new QWidget(m_defenseDialog);
1235   QGridLayout * mainLayout = new QGridLayout(widget);
1236 
1237   // Create the differents layout for buttons and label
1238   QGridLayout * bottomLayout = new QGridLayout();
1239   QGridLayout * topLayout = new QGridLayout();
1240 
1241   // Create and add the main Layout
1242   widget->setLayout(mainLayout);
1243   mainLayout->addLayout(bottomLayout, 1, 0, Qt::AlignCenter);
1244   mainLayout->addLayout(topLayout, 0, 0, Qt::AlignCenter);
1245   
1246   // Creat buttons and label of defense
1247   QPushButton * def1 = new QPushButton (i18n("Defend 1"));
1248   QPushButton * def2 = new QPushButton (i18n("Defend 2"));
1249   QPushButton * defAuto = new QPushButton (i18n("Defend-Auto"));
1250 
1251   m_labDef = new QLabel ();
1252   m_labDef->setText(defenseLabel());
1253 
1254   // Add icons on buttons
1255   QString skin = m_automaton->game()->theWorld()->skin();
1256   QString imageFileName;
1257 
1258   imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/defendOne.png");
1259   def1->setIcon(QIcon(imageFileName));
1260   imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/defendTwo.png");
1261   def2->setIcon(QIcon(imageFileName));
1262   imageFileName = QStandardPaths::locate(QStandardPaths::AppDataLocation, skin + "/Images/attackAuto.png");
1263   defAuto->setIcon(QIcon(imageFileName));
1264 
1265 
1266   // Disable Defend 2 when attack with 1 army or defender have only 1 army
1267   if (this->firstCountry()->owner()->getNbAttack() == 1)
1268      def2->setEnabled(false);
1269 
1270   // Add buttons and layout
1271   bottomLayout->addWidget(def1,0,0);
1272   bottomLayout->addWidget(def2,0,1);
1273   bottomLayout->addWidget(defAuto,0,2);
1274   topLayout->addWidget(m_labDef, 0, 0);
1275 
1276   connect(def1, &QAbstractButton::clicked, this, &KGameWindow::slotWindowDef1);
1277   connect(def2, &QAbstractButton::clicked, this, &KGameWindow::slotWindowDef2);
1278   connect(defAuto, &QAbstractButton::clicked, this, &KGameWindow::slotDefAuto);
1279 
1280   QVBoxLayout *dialogLayout = new QVBoxLayout(m_defenseDialog);
1281   dialogLayout->addWidget(widget);
1282 }
1283 
1284 void KGameWindow::displayDefenseWindow()
1285 {
1286   qCDebug(KSIRK_LOG);
1287   if (m_defenseDialog == nullptr)
1288     createDefenseDialog();
1289   else
1290     m_labDef->setText(defenseLabel());
1291   m_defenseDialog->exec();
1292 }
1293 
1294 void KGameWindow::startLocalCurrentAI()
1295 {
1296   qCDebug(KSIRK_LOG);
1297   if (currentPlayer() && currentPlayer()-> isAI()  && (!currentPlayer()->isVirtual()))
1298   {
1299     if (!(static_cast<AIPlayer *>(currentPlayer()))-> isRunning())
1300       (static_cast<AIPlayer *>(currentPlayer()))-> start();
1301   }
1302 }
1303 
1304 void KGameWindow::setBarFlagButton(const Player* player)
1305 {
1306 //   qCDebug(KSIRK_LOG) << "KGameWindow::setBarFlagButton";
1307 
1308   if (player == nullptr)
1309   {
1310     if (currentPlayer() 
1311         && currentPlayer()-> getFlag())
1312     {
1313       if (!m_goalAction->isVisible())
1314         m_goalAction->setVisible(true);
1315       m_goalAction-> setIcon(QIcon(currentPlayer()->getFlag()-> image(0)));
1316       m_goalAction-> setIconText(i18n("Goal"));
1317       m_barFlag-> setPixmap(currentPlayer()->getFlag()-> image(0));
1318       m_barFlag->show();
1319     }
1320   }
1321   else
1322   {
1323     if (player-> getFlag())
1324     {
1325       if (!m_goalAction->isVisible())
1326         m_goalAction->setVisible(true);
1327       m_goalAction-> setIcon(QIcon(player-> getFlag()-> image(0)));
1328       m_goalAction-> setIconText(i18n("Goal"));
1329       m_barFlag-> setPixmap(player->getFlag()-> image(0));
1330       m_barFlag->show();
1331     }
1332   }
1333   m_frame->setFocus();
1334 }
1335 
1336 bool KGameWindow::finishSetupPlayers()
1337 {
1338   qCDebug(KSIRK_LOG);
1339   if (!(m_automaton->playerList()->isEmpty()))
1340   {
1341     m_automaton->playerList()->clear();
1342     m_automaton->currentPlayer(nullptr);
1343     qCDebug(KSIRK_LOG) << "  playerList size = " << m_automaton->playerList()->count();
1344   }
1345   theWorld()->reset();
1346   
1347   QMap< QString, QString > nations = nationsList();
1348   if (!(m_automaton->playerList()->isEmpty()))
1349   {
1350     m_automaton->playerList()->clear();
1351   }
1352   qCDebug(KSIRK_LOG) << "newPlayersNumber = " << m_newGameSetup->players().size();
1353   unsigned int nbAvailArmies = (unsigned int)(m_theWorld->getNbCountries() * 2.5 / m_newGameSetup->players().size());
1354   qCDebug(KSIRK_LOG) << "nbAvailArmies = " << nbAvailArmies << " ; nb countries = " << m_theWorld->getNbCountries();
1355   QString nomEntre = "";
1356   QString password = "";
1357   QString nationName = "";
1358   m_newPlayerWidget->init(m_automaton,m_theWorld,(int)1,nomEntre,password,false,nations,nationName, m_newGameSetup);
1359   m_centralWidget->setCurrentIndex(NEWPLAYER_INDEX);
1360   // Players names
1361   QString mes = "";
1362   if (m_newGameSetup->networkGameType() != GameAutomaton::None)
1363   {
1364     m_frame->setArenaOptionEnabled(false);
1365     unreduceChat();
1366     qCDebug(KSIRK_LOG) << "In setupPlayers: networkGame";
1367     KMessageParts messageParts;
1368     messageParts << kli18n("Waiting for %1 players to connect").untranslatedText()
1369       << QString::number(m_newGameSetup->nbNetworkPlayers());
1370     broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
1371   }
1372   else
1373   {
1374     m_frame->setArenaOptionEnabled(true);
1375     reduceChat();
1376   }
1377   m_frame->setFocus();
1378   return true;
1379 }
1380 
1381 bool KGameWindow::setupOnePlayer()
1382 {
1383   qCDebug(KSIRK_LOG) << "KGameWindow::setupOnePlayer";
1384   
1385   qCDebug(KSIRK_LOG) << "  building the list of available nations";
1386   QMap< QString, QString > nations = nationsList();
1387   PlayersArray::iterator it = m_automaton->playerList()->begin();
1388   PlayersArray::iterator it_end = m_automaton->playerList()->end();
1389   for (; it != it_end; it++)
1390   {
1391     Player* player = (Player*)(*it);
1392     qCDebug(KSIRK_LOG) << "    removing nation of player " << player-> name();
1393     /// Don't understand why if using Player::getNation below, the method is
1394     /// not executed (get 0) but if using the same named myNation, it works...
1395     /// Ideas anybody ????
1396     Nationality* nation = player-> getNation();
1397     qCDebug(KSIRK_LOG) << "    got player nation " << nation;
1398     QString nationName = nation->name();
1399     QMap<QString,QString>::iterator nationsIt;
1400     nationsIt = nations.find(nationName);
1401     if (nationsIt !=  nations.end())
1402     {
1403       nations.erase(nationsIt);
1404     }
1405   }
1406   qCDebug(KSIRK_LOG) << "  number of available nations: " << nations.size();
1407   unsigned int nbAvailArmies = (unsigned int)(m_theWorld->getNbCountries() * 2.5 / (m_automaton->nbPlayers()));
1408   qCDebug(KSIRK_LOG) << "KGameWindow::setupOnePlayer: nbAvailArmies = " << nbAvailArmies << " ; nb countries = " << m_theWorld->getNbCountries();
1409   // Players names
1410   QString mes = "";
1411   QString nationName;
1412     
1413   QString nomEntre = "";
1414   QString password;
1415   bool computer=false;
1416 
1417   m_newPlayerWidget->init(m_automaton, m_theWorld, 1, nomEntre, password, computer, nations, nationName, m_newGameSetup);
1418   m_centralWidget->setCurrentIndex(NEWPLAYER_INDEX);
1419   return true;
1420 }
1421 
1422 bool KGameWindow::setupOneWaitedPlayer()
1423 {
1424   qCDebug(KSIRK_LOG) << "KGameWindow::setupOneWaitedPlayer";
1425   
1426   QString password;
1427   int result;
1428   KWaitedPlayerSetupDialog(m_automaton, password, result, this).exec();
1429   qCDebug(KSIRK_LOG) << "After KWaitedPlayerSetupDialog. number: " << result << ", password: " << password;
1430   QByteArray buffer;
1431   QDataStream stream(&buffer, QIODevice::WriteOnly);
1432   stream << (quint32)result << password;
1433   m_automaton->sendMessage(buffer,ValidateWaitedPlayerPassword);
1434   return true;
1435 }
1436 
1437 bool KGameWindow::createWaitedPlayer(quint32 waitedPlayerId)
1438 {
1439   qCDebug(KSIRK_LOG) << "KGameWindow::createWaitedPlayer";
1440   
1441   PlayerMatrix& pm = m_waitedPlayers[waitedPlayerId];
1442   Player* player = addPlayer(pm.name, pm.nbAvailArmies,
1443                               pm.nbCountries, pm.nation,
1444                               pm.isAI, pm.password,
1445                               pm.nbAttack, pm.nbDefense);
1446 
1447   player->goal(pm.goal);
1448   QList<QString>::iterator it, it_end;
1449   it = pm.countries.begin(); it_end = pm.countries.end();
1450   for (; it != it_end; it++)
1451   {
1452     QByteArray buffer;
1453     QDataStream stream(&buffer, QIODevice::WriteOnly);
1454     stream << (*it) << pm.name;
1455     m_automaton->sendMessage(buffer,CountryOwner);
1456   }
1457   return true;
1458 }
1459 
1460 void KGameWindow::distributeArmies()
1461 {
1462   qCDebug(KSIRK_LOG) << "KGameWindow::distributeArmies";
1463   PlayersArray::iterator it = m_automaton->playerList()->begin();
1464   PlayersArray::iterator it_end = m_automaton->playerList()->end();
1465   for (; it != it_end; it++)
1466   {
1467     unsigned int nb = nbNewArmies(dynamic_cast<Player*>(*it));
1468 //     qCDebug(KSIRK_LOG) << "    Giving " << nb << " armies to " << static_cast<Player*>(*it)->name();
1469     dynamic_cast<Player*>(*it)-> setNbAvailArmies(nb, true);
1470   }
1471 }
1472 
1473 int KGameWindow::nbNewArmies(Player *player)
1474 {
1475 //    qCDebug(KSIRK_LOG) << "KGameWindow::nbNewArmies for "  << player-> name();
1476 
1477   unsigned int res = 0;
1478 
1479   for (unsigned int i = 0; i<m_theWorld->getNbCountries(); i++)
1480       if (m_theWorld-> getCountries().at(i)-> owner() == player) res++;
1481   res = (res/3) < 3 ? 3 : res/3 ;
1482 
1483   QList<Continent*>& continents = m_theWorld-> getContinents();
1484   QList<Continent*>::iterator it = continents.begin();
1485   for (; it != continents.end(); it++)
1486   {
1487     Continent* currCont = *it;
1488     if (currCont-> owner() == player)
1489     {
1490 //            qCDebug(KSIRK_LOG) << ">>>>>>>>>>> Adding bonus for "  << currCont-> name();
1491       res += currCont-> getBonus();
1492     }
1493   }
1494 
1495   return res;
1496 }
1497 
1498 void KGameWindow::changeItem( const QString& text, int id, bool log )
1499 {
1500   if (id != ID_NO_STATUS_MSG)
1501   {
1502       //QT5 statusBar()-> changeItem(text, id);
1503   }
1504   if (log)
1505   {
1506     KsirkChatItem item;
1507     item << text;
1508 //     m_chatDlg->addMessage("",text);
1509 // to port
1510 //     m_chatDlg->addSystemMessage   ( "", text  ) ;
1511   }
1512 }
1513 
1514 void KGameWindow::changeItem( KMessageParts& strings, int id, bool log )
1515 {
1516 //  qCDebug(KSIRK_LOG) << "KGameWindow::changeItem(KMessageParts,int, log)" << strings.size() << id << log;
1517   if (strings.begin() == strings.end())
1518   {
1519 //     qCDebug(KSIRK_LOG) << "  nothing " << strings.size();
1520     return;
1521   }
1522   bool arguing = false;
1523   KLocalizedString argument;
1524   KsirkChatItem item;
1525   KMessageParts::iterator it, it_end;
1526   it = strings.begin(); it_end = strings.end();
1527   if (it.curIsStr())
1528   {
1529     if (!it.curStr().isEmpty())
1530     {
1531 //       qCDebug(KSIRK_LOG) << "setting argument to: '" << it.curStr() << "'";
1532       argument = ki18n(it.curStr().toUtf8().data());
1533     }
1534     else
1535     {
1536 //       qCDebug(KSIRK_LOG) << "setting argument to empty";
1537       argument = KLocalizedString();
1538     }
1539     arguing = true;
1540   }
1541   else if (it.curIsPix())
1542   {
1543 //     qCDebug(KSIRK_LOG) << "first item is pixmap";
1544     item << it.curPix();
1545   }
1546   
1547   it++;
1548   for (; it != it_end; it++)
1549   {
1550 //     qCDebug(KSIRK_LOG) << "next item";
1551     if (it.curIsStr())
1552     {
1553 //       qCDebug(KSIRK_LOG) << "item is: '" << it.curStr() << "'";
1554       if (arguing)
1555       {
1556 //         qCDebug(KSIRK_LOG) << "  substituting";
1557         argument=argument.subs(it.curStr());
1558       }
1559       else
1560       {
1561 //         qCDebug(KSIRK_LOG) << "  assigning new argument";
1562         if (!it.curStr().isEmpty())
1563         {
1564 //           qCDebug(KSIRK_LOG) << "setting argument to: '" << it.curStr() << "'";
1565           argument = ki18n(it.curStr().toUtf8().data());
1566         }
1567         else
1568         {
1569 //           qCDebug(KSIRK_LOG) << "setting argument to empty";
1570           argument = KLocalizedString();
1571         }
1572         arguing = true;
1573       }
1574     }
1575     else
1576     {
1577       if (arguing)
1578       {
1579 //         qCDebug(KSIRK_LOG) << "  storing";
1580         if (argument.isEmpty())
1581         {
1582           item << QString("");
1583         }
1584         else
1585         {
1586           item << argument.toString();
1587         }
1588       }
1589       item << it.curPix();
1590       arguing = false;
1591     }
1592   }
1593 //   qCDebug(KSIRK_LOG) << "no more items";
1594   if (arguing)
1595   {
1596     if (argument.isEmpty())
1597     {
1598       item << QString("");
1599     }
1600     else
1601     {
1602       item << argument.toString();
1603     }
1604   }
1605   if (log)
1606   {
1607     ((KsirkChatModel*)(m_chatDlg->model()))->addMessage(item);
1608   }
1609   if (id != ID_NO_STATUS_MSG)
1610   {
1611     if (argument.toString() == "(I18N_EMPTY_MESSAGE)")
1612     {
1613       qCCritical(KSIRK_LOG) << "received a (I18N_EMPTY_MESSAGE)";
1614     }
1615 //     qCDebug(KSIRK_LOG) << "  argument: " << argument.toString();
1616     //QT5 statusBar()-> changeItem(argument.toString(), id);
1617   }
1618 }
1619 
1620 void KGameWindow::broadcastChangeItem(KMessageParts& strings, int id, bool log)
1621 {
1622   if (strings.empty())
1623   {
1624     return;
1625   }
1626   QByteArray buffer;
1627   QDataStream stream(&buffer, QIODevice::WriteOnly);
1628 //   qCDebug(KSIRK_LOG) << "Broadcasting change item, size=" << strings.size();
1629   stream << (quint32)id << (quint32)log << (quint32)strings.size();
1630   
1631   KMessageParts::iterator it, it_end;
1632   it = strings.begin(); it_end = strings.end();
1633   if (it != it_end)
1634   {
1635 /*    // if first element is string, convert it to id 
1636     if (it.curIsStr())
1637     {
1638       qCDebug(KSIRK_LOG) << "Pushing first element: id "<<m_automaton->idForMsg(it.curStr())<<" for '" << it.curStr() << "'";
1639       stream << (quint32)KMessageParts::StringId << m_automaton->idForMsg(it.curStr());
1640     }
1641     else if (it.curIsPix())
1642     {
1643       qCDebug(KSIRK_LOG) << "Pushing first element pix";
1644       stream << (quint32)KMessageParts::Pixmap << it.curPix();
1645     }
1646     else
1647     {
1648       qCCritical(KSIRK_LOG) << "Unsupported KMessageParts elem type ";
1649     }
1650     it++;*/
1651     for (; it != it_end; it++)
1652     {
1653       if (it.curIsStr())
1654       {
1655 //         qCDebug(KSIRK_LOG) << "Pushing string '" << it.curStr() << "'";
1656         stream << (quint32)KMessageParts::Text << it.curStr();
1657       }
1658       else if (it.curIsPix())
1659       {
1660 //         qCDebug(KSIRK_LOG) << "Pushing pix";
1661         stream << (quint32)KMessageParts::Pixmap << it.curPix();
1662       }
1663       else
1664       {
1665         qCCritical(KSIRK_LOG) << "Unsupported KMessageParts elem type ";
1666       }
1667     }
1668   }
1669   m_automaton->sendMessage(buffer,ChangeItem);
1670   changeItem(strings, id, log );
1671 }
1672 
1673 void KGameWindow::enterEvent(QEnterEvent* /*ev*/)
1674 {
1675 //   qCDebug(KSIRK_LOG) << "KGameWindow::enterEvent()";
1676   // Restart the AIs threads
1677   if ( currentPlayer() )
1678     if ( (currentPlayer()-> isAI()) && (!currentPlayer()->isVirtual()) && ( !((static_cast<AIPlayer*>(currentPlayer()))-> isRunning())) )
1679       (static_cast<AIPlayer*>(currentPlayer()))-> start();
1680           
1681 }
1682 
1683 void KGameWindow::leaveEvent(QEvent* /*ev*/)
1684 {
1685 //    qCDebug(KSIRK_LOG) << "KGameWindow::leaveEvent()";
1686     // Stops the AIs threads
1687   PlayersArray::iterator it = m_automaton->playerList()->begin();
1688   PlayersArray::iterator it_end = m_automaton->playerList()->end();
1689   for (; it != it_end; it++)
1690   {
1691     if (static_cast<Player*>(*it)-> isAI())
1692     {
1693         (static_cast<AIPlayer*>(*it))-> stop();
1694     }
1695   }
1696 }
1697 
1698 
1699 /** Return true if the state of the game is the argument; false otherwise */
1700 bool KGameWindow::isMyState(GameLogic::GameAutomaton::GameState state) const
1701 {
1702   return (m_automaton->state() == state);
1703 }
1704 
1705 /**
1706   * returns the current state of the game
1707   */
1708 GameLogic::GameAutomaton::GameState KGameWindow::getState() const
1709 {
1710   return m_automaton->state();
1711 }
1712 
1713 void KGameWindow::moveArmies(Country& src, Country& dest, unsigned int nb)
1714 {
1715 //    qCDebug(KSIRK_LOG) << "KGameWindow::moveArmies()";
1716   if ((src.owner() == currentPlayer())
1717       && (dest.owner() == currentPlayer())
1718       && (src.communicateWith(&dest))
1719       && (src.nbArmies() > nb) )
1720   {
1721     QByteArray bufferSrc;
1722     QDataStream streamSrc(&bufferSrc, QIODevice::WriteOnly);
1723     streamSrc << src.name();
1724     m_automaton->sendMessage(bufferSrc,FirstCountry);
1725     
1726     QByteArray bufferDest;
1727     QDataStream streamDest(&bufferDest, QIODevice::WriteOnly);
1728     streamDest << src.name();
1729     m_automaton->sendMessage(bufferDest,SecondCountry);
1730     
1731     int toMove = nb;
1732     while ( toMove >= 10 )
1733     {
1734       toMove -= 10;
1735       slotInvade10();
1736     }
1737     while ( toMove >= 5 )
1738     {
1739       toMove -= 5;
1740       slotInvade5();
1741     }
1742     while ( toMove >= 1 )
1743     {
1744       toMove -= 1;
1745       slotInvade1();
1746     }
1747   }
1748 //    qCDebug(KSIRK_LOG) << "OUT KGameWindow::moveArmies()";
1749 }
1750 
1751 bool KGameWindow::isMoveValid(const QPointF& point)
1752 {
1753   bool res = false;
1754   KMessageParts messageParts;
1755   Country* secondCountry = clickIn(point); 
1756   if  ( ( m_firstCountry == nullptr ) || ( secondCountry == nullptr ) )
1757   {
1758     messageParts << kli18n("There is no country here!").untranslatedText();
1759   }
1760   else if  ( m_firstCountry->owner() != currentPlayer() )
1761   {
1762     messageParts << kli18n("You are not the owner of the first country: %1!").untranslatedText() << m_firstCountry->name();
1763   }
1764   else if ( secondCountry->owner() != currentPlayer() )
1765   {
1766     messageParts << kli18n("You are not the owner of the second country: %1!").untranslatedText() << secondCountry->name();
1767   }
1768   else if (m_firstCountry == secondCountry)
1769   {
1770     messageParts << kli18n("You are trying to move armies from %1 to itself!").untranslatedText() << m_firstCountry->name();
1771   }
1772   else if (!m_firstCountry->communicateWith(secondCountry))
1773   {
1774     messageParts
1775       << kli18n("%1 is not a neighbour of %2!").untranslatedText()
1776       << secondCountry-> name() 
1777       << m_firstCountry-> name();
1778   }
1779   else 
1780   {
1781     messageParts << kli18n("Moving armies from %1 to %2.").untranslatedText()
1782             << m_firstCountry->name() 
1783             << secondCountry->name();
1784     res = true;
1785   }
1786   broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
1787   return res;    
1788 }
1789 
1790 bool KGameWindow::isFightValid(const QPointF& point)
1791 {
1792   bool res = false;
1793   KMessageParts messageParts;
1794   Country* secondCountry = clickIn(point); 
1795   if  ( ( m_firstCountry == nullptr ) || ( secondCountry == nullptr ) )
1796   {
1797     qCDebug(KSIRK_LOG) << "There is no country here!";
1798     messageParts << kli18n("There is no country here!").untranslatedText();
1799   }
1800   else if  ( m_firstCountry->owner() != currentPlayer() )
1801   {
1802     qCDebug(KSIRK_LOG) << "You are not the owner of the first country: "<< m_firstCountry->name();
1803     messageParts << kli18n("You are not the owner of the first country: %1!").untranslatedText()
1804             << m_firstCountry->name();
1805   }
1806   else if ( secondCountry->owner() == currentPlayer() )
1807   {
1808     qCDebug(KSIRK_LOG) << "You are the owner of the second country: " << secondCountry->name();
1809     messageParts << kli18n("You are the owner of the second country: %1!").untranslatedText() << secondCountry->name();
1810   }
1811   else if (m_firstCountry == secondCountry)
1812   {
1813     qCDebug(KSIRK_LOG) <<"You are trying to move armies from "<<m_firstCountry->name()<<" to itself ";
1814     messageParts << kli18n("You are trying to move armies from %1 to itself!").untranslatedText() << m_firstCountry->name();
1815   }
1816   else if (!m_firstCountry->communicateWith(secondCountry))
1817   {
1818     qCDebug(KSIRK_LOG) << secondCountry-> name() << "is not a neighbour of " << secondCountry-> name();
1819     messageParts 
1820       << kli18n("%1 is not a neighbour of %2!").untranslatedText()
1821       << secondCountry-> name() 
1822       << m_firstCountry-> name();
1823   }
1824   else 
1825   {
1826     qCDebug(KSIRK_LOG) << "Ready to fight !";
1827     messageParts << kli18n("Ready to fight!").untranslatedText();
1828     res = true;
1829   }
1830   broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
1831   return res;    
1832 }
1833 
1834 int KGameWindow::setCurrentPlayerToFirst()
1835 {
1836   if (currentPlayer() && currentPlayer()->isAI() 
1837                       && (static_cast<AIPlayer *>(currentPlayer())->isRunning()))
1838   {
1839         static_cast<AIPlayer *>(currentPlayer())->stop();
1840   }
1841   m_automaton->currentPlayer((Player*)(*m_automaton->playerList()->begin()));
1842 
1843 /*  if (currentPlayer() && currentPlayer()->isAI() && !currentPlayer()->isVirtual()
1844       && !(static_cast<AIPlayer *>(currentPlayer())->isRunning()))
1845   {
1846           static_cast<AIPlayer *>(currentPlayer())->start();
1847           qCDebug(KSIRK_LOG) <<"setCurrentPlayerToFirst : step 3";
1848   }*/
1849   m_frame->setFocus();
1850   return 0;
1851 }
1852 
1853 int KGameWindow::setCurrentPlayerToNext(bool restartRunningAIs)
1854 {
1855   qCDebug(KSIRK_LOG) << restartRunningAIs;
1856   m_rightDock->hide();
1857   int looped(0);
1858 //   qCDebug(KSIRK_LOG) << "KGameWindow::setCurrentPlayerToNext()";
1859   if ( currentPlayer() && ( currentPlayer()-> isAI())  && ( static_cast<AIPlayer *>(currentPlayer())-> isRunning() ) )
1860       static_cast<AIPlayer *>(currentPlayer())-> stop();
1861   
1862   PlayersArray::iterator it = m_automaton->playerList()->begin();
1863   PlayersArray::iterator it_end = m_automaton->playerList()->end();
1864   for (;it != it_end; it++)
1865   {
1866     if (*it == currentPlayer())
1867     {
1868       it++;
1869       break;
1870     }
1871   }
1872   if (it == it_end)
1873   {
1874       setCurrentPlayerToFirst();
1875       looped = 1;
1876   }
1877   else
1878   {
1879     m_automaton->currentPlayer((Player*)(*it));
1880   }
1881 
1882   if ( restartRunningAIs && currentPlayer() && currentPlayer()-> isAI() && (!currentPlayer()->isVirtual()) && !looped)
1883   {
1884     if ( ! (static_cast< AIPlayer* >(currentPlayer())-> isRunning()))
1885     {
1886       static_cast< AIPlayer* >(currentPlayer())-> start();
1887     }
1888   }
1889 
1890   if ( currentPlayer()->isAI() || currentPlayer()->isVirtual() )
1891   {
1892     m_nextPlayerAction->setEnabled(false);
1893   }
1894   else
1895   {
1896     m_nextPlayerAction->setEnabled(true);
1897   }
1898   
1899   qCDebug(KSIRK_LOG) << "New current player is " << currentPlayer()->name() << " ; return value is " << looped;
1900   return looped;
1901 }
1902 
1903 bool KGameWindow::terminateAttackSequence()
1904 {
1905   if (m_firstCountry != nullptr)
1906     m_firstCountry->clearHighlighting();
1907   if (m_secondCountry != nullptr)
1908     m_secondCountry->clearHighlighting();
1909   if (m_animFighters != nullptr)
1910     m_animFighters->hideAndRemoveAll();
1911   return attackEnd();
1912 }
1913 
1914 bool KGameWindow::attacker(const QPointF& point)
1915 {
1916   qCDebug(KSIRK_LOG);
1917   Country* clickedCountry = clickIn(point);
1918   KMessageParts messageParts;
1919   if (clickedCountry == nullptr)
1920   {
1921     messageParts << kli18n("<font color=\"orange\">No country here!</font>").untranslatedText();
1922     broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
1923     clearHighlighting();
1924     return false;
1925   }
1926 
1927   if (clickedCountry-> owner() != currentPlayer())
1928   {
1929     messageParts << kli18n("<font color=\"orange\">You are not the owner of %1!</font>").untranslatedText()  << clickedCountry-> name();
1930     clearHighlighting();
1931     broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
1932     return false;
1933   }
1934   else if (clickedCountry-> nbArmies() <= currentPlayer()-> getNbAttack())
1935   {
1936     messageParts << kli18n("<font color=\"orange\">There is only %1 armies in %2!</font>").untranslatedText()
1937       << QString::number(clickedCountry-> nbArmies())
1938       << clickedCountry-> name();
1939     clearHighlighting();
1940     broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
1941     return false;
1942   }
1943   else
1944   {
1945     QByteArray buffer;
1946     QDataStream stream(&buffer, QIODevice::WriteOnly);
1947     stream << clickedCountry->name();
1948     m_automaton->sendMessage(buffer,FirstCountry);
1949     QByteArray buffer2;
1950     QDataStream stream2(&buffer2, QIODevice::WriteOnly);
1951     stream2 << "";
1952     m_automaton->sendMessage(buffer2,SecondCountry);
1953 
1954     QPixmap pm = currentPlayer()->getFlag()->image(0);
1955     /*messageParts
1956       << pm
1957       << kli18n("%1 attacks from %2 with <font color=\"red\">%3 armies</font>").untranslatedText()
1958       << currentPlayer()-> name()
1959       << clickedCountry-> name()
1960       << QString::number(currentPlayer()-> getNbAttack());
1961     broadcastChangeItem(messageParts, ID_STATUS_MSG2);*/
1962     return true;
1963   }
1964 }
1965 
1966 unsigned int KGameWindow::attacked(const QPointF& point)
1967 {
1968   qCDebug(KSIRK_LOG) << point << (void*)m_firstCountry << (void*)m_secondCountry;
1969   //if (currentPlayer()-> isAI()) return 3;
1970   // executed on the admin side only
1971   if (!m_automaton->isAdmin()) return 3;
1972 
1973   unsigned int res = 0;
1974   //Country* secondCountry = clickIn(point);
1975   //m_secondCountry = secondCountry;
1976   KMessageParts messageParts;
1977 
1978 //   qCDebug(KSIRK_LOG) << "2nd country is now set";
1979   if ( (m_firstCountry == nullptr) || (m_secondCountry == nullptr)
1980           || (m_firstCountry-> owner() != currentPlayer()) )
1981   {
1982     qCDebug(KSIRK_LOG) << ("Nothing to attack !");
1983     QByteArray buffer;
1984     QDataStream stream(&buffer, QIODevice::WriteOnly);
1985     m_automaton->sendMessage(buffer,ClearHighlighting);
1986   }
1987   else if (!m_secondCountry-> owner())
1988   {
1989     qCDebug(KSIRK_LOG) << ("Invalid attacked country.");
1990     QByteArray buffer;
1991     QDataStream stream(&buffer, QIODevice::WriteOnly);
1992     m_automaton->sendMessage(buffer,ClearHighlighting);
1993   }
1994 /*  else if (!m_secondCountry-> owner()->isVirtual())
1995   {
1996     // messageParts << kli18n("Invalid attacked country.").untranslatedText();
1997     return 3;
1998   }*/
1999   else if (m_firstCountry == m_secondCountry)
2000   {
2001    qCDebug(KSIRK_LOG) << ("You are trying to attack %1 from itself !") << m_firstCountry-> name();
2002     QByteArray buffer;
2003     QDataStream stream(&buffer, QIODevice::WriteOnly);
2004     m_automaton->sendMessage(buffer,ClearHighlighting);
2005   }
2006   else if (!m_firstCountry-> communicateWith(m_secondCountry))
2007   {
2008     qCDebug(KSIRK_LOG) << ("%1 is not a neighbour of %2 !") << m_secondCountry-> name() << m_firstCountry-> name();
2009     QByteArray buffer;
2010     QDataStream stream(&buffer, QIODevice::WriteOnly);
2011     m_automaton->sendMessage(buffer,ClearHighlighting);
2012   }
2013   else if (m_firstCountry-> owner() == m_secondCountry-> owner())
2014   {
2015     qCDebug(KSIRK_LOG) << ("%1! You cannot attack %2! It is yours!") << currentPlayer()-> name()
2016            << m_secondCountry-> name();
2017     QByteArray buffer;
2018     QDataStream stream(&buffer, QIODevice::WriteOnly);
2019     m_automaton->sendMessage(buffer,ClearHighlighting);
2020   }
2021   else if (m_firstCountry-> owner() != currentPlayer()) 
2022   {
2023     qCDebug(KSIRK_LOG) << ("%1 ! You are not the owner of %2!") << currentPlayer()-> name() << m_firstCountry-> name();
2024     QByteArray buffer;
2025     QDataStream stream(&buffer, QIODevice::WriteOnly);
2026     m_automaton->sendMessage(buffer,ClearHighlighting);
2027   }
2028   else if (m_firstCountry->nbArmies() - currentPlayer()->getNbAttack() < 1)
2029   {
2030    qCDebug(KSIRK_LOG)
2031       << ("%1, you have to keep one army to defend %2.")
2032       << m_firstCountry->owner()-> name()
2033       << m_firstCountry-> name();
2034     QByteArray buffer;
2035     QDataStream stream(&buffer, QIODevice::WriteOnly);
2036     m_automaton->sendMessage(buffer,ClearHighlighting);
2037   }
2038   else if (m_secondCountry-> nbArmies() > 1)
2039   {
2040     QByteArray buffer;
2041     QDataStream stream(&buffer, QIODevice::WriteOnly);
2042     if (m_secondCountry != nullptr)
2043     {
2044       stream << m_secondCountry->name();
2045     }
2046     else
2047     {
2048       stream << QString("");
2049     }
2050     m_automaton->sendMessage(buffer,SecondCountry);
2051 
2052     qCDebug(KSIRK_LOG)
2053         << ("%1, with how many armies do you defend %2 ?")
2054         << m_secondCountry->owner()-> name()
2055         << m_secondCountry-> name();
2056     QByteArray buffer2;
2057     QDataStream stream2(&buffer2, QIODevice::WriteOnly);
2058     stream2 << m_secondCountry->owner()->name();
2059     m_automaton->sendMessage(buffer2,DisplayDefenseButtons);
2060     res = 1;
2061   }
2062   else
2063   {
2064     QByteArray buffer;
2065     QDataStream stream(&buffer, QIODevice::WriteOnly);
2066     if (m_secondCountry != nullptr)
2067     {
2068       stream << m_secondCountry->name();
2069     }
2070     else
2071     {
2072       stream << QString("");
2073     }
2074     m_automaton->sendMessage(buffer,SecondCountry);
2075     messageParts
2076       << kli18n("%1, you defend with the only army you have in %2.").untranslatedText()
2077       << m_secondCountry->owner()-> name()
2078       << m_secondCountry-> name();
2079     res = 2;
2080   }
2081   qCDebug(KSIRK_LOG) << "will change item";
2082   broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
2083   qCDebug(KSIRK_LOG) << "change item broadcasted; returning " << res;
2084   return res;
2085 }
2086 
2087 bool KGameWindow::firstCountryAt(const QPointF& point)
2088 {
2089   Country* c = clickIn(point);
2090   if (c)
2091   {
2092     if (c-> owner() == currentPlayer())
2093     {
2094       QByteArray buffer;
2095       QDataStream stream(&buffer, QIODevice::WriteOnly);
2096       stream << c->name();
2097       m_automaton->sendMessage(buffer,FirstCountry);
2098       return true;
2099     }
2100   }
2101   return false;
2102 }
2103 
2104 bool KGameWindow::secondCountryAt(const QPointF& point)
2105 {
2106   if (clickIn(point))
2107   {
2108     QByteArray buffer;
2109     QDataStream stream(&buffer, QIODevice::WriteOnly);
2110     stream << clickIn(point)->name();
2111     m_automaton->sendMessage(buffer,SecondCountry);
2112     return true;
2113   }
2114   return false;
2115 }
2116 
2117 bool KGameWindow::playerPutsArmy(const QPointF& point, bool removable)
2118 {
2119   qCDebug(KSIRK_LOG) << removable;
2120   Country* clickedCountry = clickIn(point);
2121 
2122   if (clickedCountry)
2123   {
2124     qCDebug(KSIRK_LOG) << "clickedCountry name=" << clickedCountry->name() ;
2125     qCDebug(KSIRK_LOG) << "clickedCountry owner=" << clickedCountry-> owner()->name();
2126     qCDebug(KSIRK_LOG) << "currentPlayer=" << currentPlayer()->name();
2127     unsigned int nbAvailArmies = currentPlayer()->getNbAvailArmies();
2128     qCDebug(KSIRK_LOG) << "nbAvailArmies=" << nbAvailArmies;
2129     if (clickedCountry->owner() == currentPlayer() &&  nbAvailArmies > 0)
2130     {
2131       nbAvailArmies--;
2132       qCDebug(KSIRK_LOG) << "owner new available armies=" << nbAvailArmies;
2133       currentPlayer()->putArmiesInto(1, theWorld()->indexOfCountry(clickedCountry));
2134       clickedCountry-> incrNbArmies();
2135       clickedCountry-> createArmiesSprites();
2136       QPixmap pm = currentPlayer()->getFlag()->image(0);
2137       KMessageParts messageParts;
2138       messageParts 
2139         << pm 
2140         << kli18n("%1: %2 armies to place").untranslatedText()
2141         << currentPlayer()-> name()
2142         << QString::number(nbAvailArmies);
2143       broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
2144 
2145       getRightDialog()->updateRecycleDetails(clickedCountry,false,nbAvailArmies);
2146 
2147       if (m_automaton->isAdmin())
2148       {
2149         m_automaton->checkGoal();
2150       }
2151     }
2152   }
2153   return false;
2154 }
2155 
2156 bool KGameWindow::playerPutsInitialArmy(const QPointF& point)
2157 {
2158   {
2159     qCDebug(KSIRK_LOG) << point;
2160     Country* clickedCountry = clickIn(point);
2161     
2162     if ( (clickedCountry) )
2163     {
2164       qCDebug(KSIRK_LOG) << "clickedCountry name=" << clickedCountry->name() ;
2165       qCDebug(KSIRK_LOG) << "clickedCountry owner=" << clickedCountry-> owner()->name();
2166       qCDebug(KSIRK_LOG) << "clickedCountry had armies=" << clickedCountry-> nbArmies();
2167       qCDebug(KSIRK_LOG) << "currentPlayer=" << currentPlayer()->name();
2168       qCDebug(KSIRK_LOG) << "nbAvailArmies=" << currentPlayer()->getNbAvailArmies();
2169       
2170       if (
2171            (clickedCountry-> owner() == currentPlayer()) &&
2172            (((GameLogic::Player*)currentPlayer())-> getNbAvailArmies() > 0))
2173       {
2174         unsigned int currentAvailArmiesNumber = ((GameLogic::Player*)currentPlayer())-> getNbAvailArmies() - 1;
2175         bool last = (currentAvailArmiesNumber == 0);
2176         currentPlayer()->putArmiesInto(1, theWorld()->indexOfCountry(clickedCountry));
2177         qCDebug(KSIRK_LOG) << "owner new available armies=" << currentAvailArmiesNumber;
2178         clickedCountry-> incrNbArmies();
2179         clickedCountry-> createArmiesSprites();
2180 
2181         if ( last )
2182         {
2183           if (m_automaton->isAdmin())
2184           {
2185             PlayersArray::iterator it = m_automaton->playerList()->begin();
2186             PlayersArray::iterator it_end = m_automaton->playerList()->end();
2187             for (;it != it_end; it++)
2188             {
2189               if (*it == currentPlayer())
2190               {
2191                 it++;
2192                 break;
2193               }
2194             }
2195             if (it != it_end)
2196             {
2197               QPixmap pm= ((Player*)(*it))->getFlag()->image(0);
2198 
2199              /* KMessageParts messageParts;
2200               messageParts
2201                 << pm
2202                 << kli18n("%1: %2 armies to place").untranslatedText() << ((Player*)(*it))-> name()
2203                 << QString::number(((Player*)(*it))-> getNbAvailArmies());
2204               broadcastChangeItem(messageParts, ID_STATUS_MSG2);*/
2205 /*            m_nbAvailArmies = ((Player*)(*it))-> getNbAvailArmies();
2206               QByteArray buffer;
2207               QDataStream stream(&buffer, QIODevice::WriteOnly);
2208               stream << (quint32)m_nbAvailArmies;
2209               m_automaton->sendMessage(buffer,KGameWinAvailArmies);*/
2210               getRightDialog()->close();
2211 
2212               QByteArray buffer2;
2213               QDataStream stream2(&buffer2, QIODevice::WriteOnly);
2214               stream2 << ((GameLogic::Player*)(*it))->name();
2215               stream2 << (quint32) ((GameLogic::Player*)(*it))->getNbAvailArmies();
2216               qCDebug(KSIRK_LOG) << "sending DisplayRecycleDetails "
2217                 << ((Player*)(*it))->name() << (quint32) ((GameLogic::Player*)(*it))->getNbAvailArmies()
2218                 << " at " << __FILE__ << ", line " << __LINE__;
2219               m_automaton->sendMessage(buffer2,DisplayRecycleDetails);
2220             }
2221             int ret = setCurrentPlayerToNext();
2222             setContextualHelpActionEnabled(getState(), currentPlayer() && currentPlayer()->isAI());
2223             return ret;
2224           }
2225           else
2226           {
2227             return false;
2228           }
2229         }
2230         else
2231         {
2232           getRightDialog()->updateRecycleDetails(clickedCountry,false,(quint32) ((GameLogic::Player*)(currentPlayer()))->getNbAvailArmies());
2233           QPixmap pm = currentPlayer()->getFlag()->image(0);
2234           KMessageParts messageParts;
2235           messageParts << pm << kli18n("%1: %2 armies to place").untranslatedText()
2236             << currentPlayer()-> name()
2237             << QString::number((quint32) ((GameLogic::Player*)(currentPlayer()))->getNbAvailArmies());
2238           changeItem(messageParts, ID_STATUS_MSG2, false);
2239         }
2240       }
2241     }
2242     return false;
2243   }
2244 }
2245 
2246 bool KGameWindow::playerRemovesArmy(const QPointF& point)
2247 {
2248   qCDebug(KSIRK_LOG) << point;
2249   
2250   Country *clickedCountry = clickIn(point);
2251   qCDebug(KSIRK_LOG) << "  currentPlayer=" << currentPlayer()->name();
2252   if (clickedCountry == nullptr)
2253   {
2254     return false;
2255   }
2256   qCDebug(KSIRK_LOG) << "  owner=" << clickedCountry-> owner()->name();
2257   qCDebug(KSIRK_LOG) << "  nbArmies=" << clickedCountry->nbArmies();
2258   qCDebug(KSIRK_LOG) << "  canRemoveArmiesFrom=" << clickedCountry-> owner()->canRemoveArmiesFrom(1, theWorld()->indexOfCountry(clickedCountry) );
2259   if ( clickedCountry
2260       && ( clickedCountry-> owner() == currentPlayer() )
2261       && ( clickedCountry-> nbArmies() > 1)
2262       && ( clickedCountry-> owner()->canRemoveArmiesFrom(1, theWorld()->indexOfCountry(clickedCountry) ) )
2263   )
2264   {
2265     clickedCountry-> owner()->removeArmiesFrom(1, theWorld()->indexOfCountry(clickedCountry) );
2266     unsigned int newNbAvailArmies = currentPlayer()-> getNbAvailArmies() /*+ 1*/;
2267 
2268     if ( m_automaton->isAdmin() )
2269     {
2270       QPixmap pm = currentPlayer()->getFlag()->image(0);
2271       KMessageParts messageParts;
2272       messageParts <<pm<< kli18n("%1: %2 armies to place").untranslatedText() << currentPlayer()-> name()
2273         << QString::number(newNbAvailArmies);
2274       broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
2275     }
2276     clickedCountry-> decrNbArmies();
2277     clickedCountry-> createArmiesSprites();
2278 
2279     getRightDialog()->updateRecycleDetails(clickedCountry,false,newNbAvailArmies);
2280     return true;
2281   }
2282   return false;
2283 }
2284 
2285 /**
2286   * @brief setups window for recycling
2287   */
2288 void KGameWindow::initRecycling()
2289 {
2290   qCDebug(KSIRK_LOG) << "Initiating recycling";
2291   m_nextPlayerAction->setEnabled(false);
2292 
2293   setCurrentPlayerToFirst();
2294   QByteArray buffer;
2295   QDataStream stream(&buffer, QIODevice::WriteOnly);
2296   stream << quint32(0);
2297   m_automaton->sendMessage(buffer,DisplayRecyclingButtons);
2298   
2299   KMessageParts messageParts;
2300   messageParts << kli18n("Exchange armies again or continue?").untranslatedText();
2301   broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
2302 }
2303 
2304 void KGameWindow::clear()
2305 {
2306   m_nbMovedArmies = 0;
2307   m_firstCountry = m_secondCountry = nullptr;
2308   NKD = NKA = 0;
2309   if (m_message !=nullptr)
2310   {
2311     delete m_message;
2312   }
2313   m_message = nullptr;
2314 }
2315 
2316 bool KGameWindow::nextPlayerRecycling()
2317 {
2318   qCDebug(KSIRK_LOG);
2319   m_nextPlayerAction->setEnabled(false);
2320   if ( currentPlayer() && currentPlayer()-> getNbAvailArmies() > 0)
2321   {
2322     qCDebug(KSIRK_LOG) << "You must distribute all your armies";
2323     if (!currentPlayer()->isVirtual() && !currentPlayer()->isAI())
2324     {
2325       KMessageBox::error(nullptr, i18n("You must distribute\nall your armies"), i18n("KsirK"));
2326     }
2327     return false;
2328   }
2329   else
2330   {
2331     m_rightDock->hide();
2332     if (currentPlayer() && currentPlayer()-> isAI() && (!currentPlayer()->isVirtual()))
2333     {
2334       if (!(static_cast<AIPlayer *>(currentPlayer()))-> isRunning()) (static_cast<AIPlayer *>(currentPlayer()))-> start();
2335       m_nextPlayerAction->setEnabled(false);
2336     }
2337     else if (currentPlayer() && !currentPlayer()->isVirtual())
2338     {
2339       m_nextPlayerAction->setEnabled(true);
2340     }
2341     else
2342     {
2343       m_nextPlayerAction->setEnabled(false);
2344     }
2345     return true;
2346   }
2347 }
2348 
2349 /** 
2350   * @return if true next state will be NEWARMIES else it will be WAIT
2351   */
2352 bool KGameWindow::nextPlayerNormal()
2353 {
2354   qCDebug(KSIRK_LOG) << " (current is" << currentPlayer()->name()<<")";
2355   setCurrentPlayerToNext();
2356   distributeArmies();
2357 
2358   QByteArray buffer;
2359   m_automaton->sendMessage(buffer,ShowArmiesToPlace);
2360 
2361   clear();
2362   QByteArray buffer2;
2363   m_automaton->sendMessage(buffer2,StartLocalCurrentAI);
2364   getRightDialog()->close();
2365 
2366   QByteArray buffer3;
2367   QDataStream stream3(&buffer3, QIODevice::WriteOnly);
2368   stream3 << currentPlayer()-> name();
2369   stream3 << (quint32)nbNewArmies(currentPlayer());
2370   qCDebug(KSIRK_LOG) << "sending DisplayRecycleDetails "
2371       << currentPlayer()->name() << nbNewArmies(currentPlayer())
2372       << " at " << __FILE__ << ", line " << __LINE__;
2373   m_automaton->sendMessage(buffer3,DisplayRecycleDetails);
2374   return true;
2375 }
2376 
2377 void KGameWindow::centerOnFight()
2378 {
2379   qCDebug(KSIRK_LOG);
2380 
2381   qreal aj=m_rightDialog->width();    //get the width of the right widget
2382   qreal ay=m_chatDlg->height();      //get the height of the bottom widget
2383 
2384 //Larg
2385   if (m_firstCountry==nullptr || m_secondCountry==nullptr)
2386   {
2387     qCCritical(KSIRK_LOG) << "countries should not be null ("<<(void*)m_firstCountry<<","<<(void*)m_secondCountry<<") at "<<__FILE__<<", line "<<__LINE__;
2388     return;
2389   }
2390   qreal larg=((m_secondCountry->centralPoint().x())-(m_firstCountry->centralPoint().x()));
2391   if (larg<0)
2392   {
2393    larg=-larg;    //si negatif alors on remet en positif
2394   }
2395 //Long
2396   qreal longu=((m_secondCountry->centralPoint().y())-(m_firstCountry->centralPoint().y()));
2397   if (longu<0)
2398   {
2399    longu=-longu;    //si negatif alors on remet en positif
2400   }
2401 //Point NordOuest
2402   qreal minx=m_secondCountry->centralPoint().x();  
2403   qreal miny=m_secondCountry->centralPoint().y();
2404   if (minx>m_firstCountry->centralPoint().x())
2405   {
2406   minx=m_firstCountry->centralPoint().x();
2407   }
2408   if (miny>m_firstCountry->centralPoint().y())
2409   {
2410   miny=m_firstCountry->centralPoint().y();
2411   }
2412 
2413   QSizeF size (larg,longu);   //creation de la size  (2x la largeur entre les deux pays)
2414   QPointF NO (minx,miny);  //creation du point Nord Ouest
2415   QRectF rect(NO,size);    //creation du rect
2416   m_frame->ensureVisible(rect);
2417 
2418 // centering on the middle point
2419   qreal xx=((m_secondCountry->centralPoint().x())+(m_firstCountry->centralPoint().x()))/2;
2420   if (xx<0)
2421   {
2422    xx=-xx;    //si negatif alors on remet en positif
2423   }
2424   qreal yy=((m_secondCountry->centralPoint().y())+(m_firstCountry->centralPoint().y()))/2;
2425   if (yy<0)
2426   {
2427    yy=-yy;    //si negatif alors on remet en positif
2428   }
2429 
2430   QPointF mid (xx,yy);
2431   m_frame->centerOn(mid);      //center on the point
2432 
2433   m_frame->translate(-aj/2,-ay/2);  //translate to center perfectly
2434 //end Benjamin M.
2435 
2436 
2437 }
2438 void KGameWindow::attack(unsigned int nb)
2439 {  
2440   centerOnFight();        //center the view on the fight Benj
2441   
2442   currentPlayer()-> setNbAttack(nb);
2443   /*KMessageParts messageParts;
2444   messageParts << kli18n("Attack with %1 armies: designate the belligerants").untranslatedText()
2445     << QString::number(nb);
2446   broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);*/
2447   /*
2448   showMessage(i18n("To attack, press the mouse button in the attacking country<br>and then <b>drag and drop</b> on its neighbour your want to attack."), 5);
2449   */
2450 }
2451 
2452 void KGameWindow::defense(unsigned int nb)
2453 {
2454   qCDebug(KSIRK_LOG);
2455 
2456   if (!m_firstCountry) // anything left to do?
2457      return;
2458 
2459   m_secondCountry-> owner()-> setNbDefense(nb);
2460   
2461   QPixmap pmA = m_firstCountry-> owner()->getFlag()->image(0);
2462   QPixmap pmD = m_secondCountry-> owner()->getFlag()->image(0);
2463 
2464   KMessageParts messageParts;
2465   messageParts << kli18n("Battle ongoing.").untranslatedText();
2466 //     << kli18n("Battle between <font color=\"red\">%1</font> (").untranslatedText()
2467 //     << m_firstCountry-> name()
2468 //     << pmA
2469 //     << kli18n("%1).untranslatedText() <font color=\"red\">with %2 armies</font> and <font color=\"blue\">%3</font> (")
2470 //     << m_firstCountry->owner()->name()
2471 //     << QString::number(currentPlayer()-> getNbAttack())
2472 //     << m_secondCountry-> name()
2473 //     << pmD
2474 //     << kli18n("%1).untranslatedText() <font color=\"blue\">with %2 armies</font>.")
2475 //     << m_secondCountry->owner()->name()
2476 //     << QString::number(nb);
2477 
2478   broadcastChangeItem(messageParts, ID_STATUS_MSG2, false);
2479 
2480   if (m_firstCountry-> owner() && m_firstCountry-> owner()-> getFlag())
2481   {
2482     if (!m_goalAction->isVisible())
2483       m_goalAction->setVisible(true);
2484     m_goalAction-> setIcon(QIcon(m_firstCountry-> owner()->getFlag()-> image(0)));
2485     m_goalAction-> setIconText(i18n("Goal"));
2486     m_barFlag-> setPixmap(m_firstCountry-> owner()->getFlag()-> image(0));
2487   }
2488   if (m_automaton->isAdmin())
2489   {
2490     QByteArray buffer;
2491     QDataStream stream(&buffer, QIODevice::WriteOnly);
2492     m_automaton->sendMessage(buffer,InitCombatMovement);
2493     m_automaton->state(GameLogic::GameAutomaton::FIGHT_BRING);
2494   }
2495 }
2496 
2497 int KGameWindow::nbMovedArmies()
2498 {
2499   return m_nbMovedArmies;
2500 }
2501 
2502 void KGameWindow::incrNbMovedArmies(unsigned int nb)
2503 {
2504   m_nbMovedArmies += nb;
2505 }
2506 
2507 void KGameWindow::decrNbMovedArmies(unsigned int nb)
2508 {
2509   m_nbMovedArmies -= nb;
2510 }
2511 
2512 bool KGameWindow::invade(unsigned int nb )
2513 {
2514   if (m_firstCountry==nullptr || m_secondCountry==nullptr)
2515   {
2516     qCDebug(KSIRK_LOG) << "invade("<<nb<<") returns " << false;
2517     return false;
2518   }
2519   bool res = initArmiesMovement(nb, m_firstCountry, m_secondCountry);
2520   qCDebug(KSIRK_LOG) << "invade("<<nb<<") returns " << res;
2521   return res;
2522 }
2523 
2524 AnimSprite* KGameWindow::simultaneousAttack(int nb, FightType state)
2525 {
2526   qCDebug(KSIRK_LOG) << nb << state << relativePosInArenaAttack << relativePosInArenaDefense;
2527   AnimSprite* res;
2528 
2529   if (state == Attack)
2530   {
2531     QPointF pointAttaquant(0,0);
2532     QPointF pointDefenseur(0,0);
2533     determinePointArriveeForArena(relativePosInArenaAttack, pointAttaquant,pointDefenseur);
2534 
2535     qCDebug(KSIRK_LOG) << "****point att****" << pointAttaquant;
2536 
2537     qCDebug(KSIRK_LOG) << "****SIMULTANEOUS ATTACK****" << pointAttaquant;
2538     res = initArmiesMultipleCombat(nb, firstCountry(), secondCountry(), pointAttaquant);
2539 
2540     relativePosInArenaAttack++;
2541   }
2542   else // Defense
2543   {
2544     QPointF pointAttaquant(0,0);
2545     QPointF pointDefenseur(0,0);
2546     determinePointArriveeForArena(/*secondCountry(), firstCountry(),*/
2547       relativePosInArenaDefense, pointDefenseur, pointAttaquant);
2548 
2549     qCDebug(KSIRK_LOG) << "****point def****" << pointAttaquant;
2550 
2551     qCDebug(KSIRK_LOG) << "****SIMULTANEOUS DEFENSE****" << pointDefenseur;
2552     res = initArmiesMultipleCombat(nb, secondCountry(), secondCountry(), pointDefenseur);
2553 
2554     relativePosInArenaDefense++;
2555   }
2556   qCDebug(KSIRK_LOG) << (void*)res;
2557   return res;
2558 }
2559 
2560 
2561 bool KGameWindow::retreat(unsigned int nb)
2562 {
2563   bool res;
2564   if (m_nbMovedArmies >= int(nb))
2565   {
2566     res = initArmiesMovement(nb, m_secondCountry, m_firstCountry);
2567   }
2568   else
2569   {
2570     res = false;
2571   }
2572   qCDebug(KSIRK_LOG) << "retreat("<<nb<<") returns " << res;
2573   return res;
2574 }
2575 
2576 void KGameWindow::invasionFinished()
2577 {
2578   qCDebug(KSIRK_LOG);
2579   clearHighlighting();
2580  //KMessageParts messageParts;
2581 
2582   QPixmap pm = currentPlayer()->getFlag()->image(0);
2583   KMessageParts messageParts;
2584   messageParts
2585     << pm 
2586     << kli18n("%1, it is up to you.").untranslatedText() << currentPlayer()->name();
2587   broadcastChangeItem(messageParts, ID_STATUS_MSG2);
2588 }
2589         
2590 void KGameWindow::shiftFinished()
2591 {
2592   clearHighlighting();
2593   QPixmap pm = currentPlayer()->getFlag()->image(0);
2594   KMessageParts messageParts;
2595   messageParts 
2596     << pm 
2597     << kli18n("%1, it is up to you.").untranslatedText() << currentPlayer()->name();
2598   broadcastChangeItem(messageParts, ID_STATUS_MSG2);
2599   slotNextPlayer();
2600 }
2601 
2602 void KGameWindow::cancelAction()
2603 {
2604   qCDebug(KSIRK_LOG) << "KGameWindow::cancelAction";
2605   QByteArray buffer;
2606   QDataStream stream(&buffer, QIODevice::WriteOnly);
2607   stream << "";
2608   m_automaton->sendMessage(buffer,FirstCountry);
2609   QByteArray buffer2;
2610   QDataStream stream2(&buffer2, QIODevice::WriteOnly);
2611   stream2 << "";
2612   m_automaton->sendMessage(buffer2,SecondCountry);
2613 
2614   clearHighlighting();
2615 
2616   KMessageParts messageParts;
2617   QPixmap pm = currentPlayer()->getFlag()->image(0);
2618   messageParts
2619     << pm 
2620     << kli18n("%1, it is up to you.").untranslatedText() << currentPlayer()->name();
2621   broadcastChangeItem(messageParts, ID_STATUS_MSG2);
2622 }
2623 
2624 void KGameWindow::cancelShiftSource()
2625 {
2626   if (m_nbMovedArmies < 0)
2627   {
2628     m_firstCountry-> decrNbArmies(m_nbMovedArmies);
2629     m_secondCountry-> incrNbArmies(m_nbMovedArmies);
2630     m_firstCountry-> createArmiesSprites();
2631     m_secondCountry-> createArmiesSprites();
2632     m_nbMovedArmies = 0;
2633   }
2634   if (m_nbMovedArmies > 0)
2635   {
2636     m_firstCountry-> incrNbArmies(m_nbMovedArmies);
2637     m_secondCountry-> decrNbArmies(m_nbMovedArmies);
2638     m_firstCountry-> createArmiesSprites();
2639     m_secondCountry-> createArmiesSprites();
2640     m_nbMovedArmies = 0;
2641   }
2642 }
2643 
2644 bool KGameWindow::actionNewGame(GameAutomaton::NetworkGameType socket)
2645 {
2646   qCDebug(KSIRK_LOG);
2647   if  ( ( m_automaton->playerList()->count() == 0 ) ||
2648   ( isMyState(GameLogic::GameAutomaton::GAME_OVER)  ) ||
2649         (KMessageBox::warningContinueCancel(this,i18n("Do you really want to end your current game and start a new one?"),i18n("New game confirmation"),KGuiItem(i18nc("@action:button", "Start New Game"))) == KMessageBox::Continue ) )
2650 
2651   {
2652     qCDebug(KSIRK_LOG) << "valid";
2653     m_automaton->setGameStatus(KGame::End);
2654     m_reinitializingGame = true;
2655     m_automaton->removeAllPlayers();
2656     // Bug 308527. Need to remove all goals on new game.
2657     m_automaton->removeAllGoals();
2658     m_automaton->state(GameLogic::GameAutomaton::INIT);
2659     m_automaton->savedState(GameLogic::GameAutomaton::INVALID);
2660     disconnect(m_automaton->messageServer(), &KMessageServer::connectionLost,
2661                m_automaton, &GameAutomaton::slotConnectionToClientBroken);
2662 
2663     m_automaton->disconnect();
2664 
2665     m_newGameSetup->clear();
2666     m_automaton->setupPlayersNumberAndSkin(socket);
2667   }
2668   return false;
2669 }
2670 
2671 void KGameWindow::saveXml(QTextStream& xmlStream)
2672 {
2673   xmlStream << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
2674   xmlStream << "<ksirkSavedGame formatVersion=\"" << SAVE_GAME_FILE_FORMAT_VERSION << "\" >";
2675   xmlStream << "<game skin=\"" << m_automaton->skin() << "\" state=\"" << m_automaton->state() << "\" >";
2676   m_theWorld->saveXml(xmlStream);
2677   xmlStream << "<players nb=\""<<m_automaton->playerList()->count()<<"\">";
2678   PlayersArray::iterator it = m_automaton->playerList()->begin();
2679   PlayersArray::iterator it_end = m_automaton->playerList()->end();
2680   for (; it != it_end; it++)
2681   {
2682     static_cast<Player*>(*it)->saveXml(xmlStream);
2683   }
2684   xmlStream << "</players>";
2685   Player* player = m_automaton->currentPlayer();
2686   if (player)
2687   {
2688     QString name = player->name();
2689     name = name.replace('&',"&amp;");
2690     name = name.replace('<',"&lt;");
2691     name = name.replace('>',"&gt;");
2692     xmlStream << "<currentPlayer name=\"" << name << "\" />";
2693   }
2694   else
2695     xmlStream << "<currentPlayer name=\"\" />";
2696   xmlStream << "<goals>\n";
2697   it = m_automaton->playerList()->begin();
2698   it_end = m_automaton->playerList()->end();
2699   for (; it != it_end; it++)
2700   {
2701     static_cast<Player*>(*it)->goal().saveXml(xmlStream);
2702   }
2703   xmlStream << "</goals>\n";
2704   xmlStream << "</game>";
2705   xmlStream << "</ksirkSavedGame>";
2706 }
2707 
2708 /**
2709   * @brief Accessor to the world
2710   * @return A pointer to the world
2711   */
2712 ONU* KGameWindow::theWorld()
2713 {
2714   return m_theWorld;
2715 }
2716 
2717 /**
2718   * @brief Adds a player
2719   */
2720 Player* KGameWindow::addPlayer(const QString& playerName,
2721       unsigned int nbAvailArmies, 
2722       unsigned int nbCountries, 
2723       const QString& nationName, 
2724       bool isAI,
2725       const QString& password,
2726       unsigned int nbAttack,
2727       unsigned int nbDefense)
2728 {
2729   qCDebug(KSIRK_LOG) << "Adding player (AI: " << isAI << ")";
2730   Player* p = dynamic_cast<Player*>(m_automaton->createPlayer(isAI?2:1,0,false)); 
2731   if (p)
2732   {
2733     if (!isAI)
2734     {
2735       m_chatDlg->setFromPlayer(p);
2736     }
2737     p->setName(playerName);
2738     p->setNation(nationName);
2739     p->setNbCountries(nbCountries);
2740     p->setNbAvailArmies(nbAvailArmies, true);
2741     p->setNbAttack(nbAttack);
2742     p->setNbDefense(nbDefense);
2743     p->setPassword(password);
2744     if (!m_automaton->addPlayer(p))
2745     {
2746       qCDebug(KSIRK_LOG) << p->name() << "NOT added!";
2747       p = nullptr; // freed - weired API
2748     }
2749   }
2750   return p;
2751 }
2752 
2753 QMap< QString, QString > KGameWindow::nationsList()
2754 {
2755   QMap< QString, QString >  res;
2756   if (m_theWorld == nullptr)
2757   {
2758     return res;
2759   }
2760   QList<Nationality*>& nationsList = m_theWorld->getNationalities();
2761   qCDebug(KSIRK_LOG) << "There is " << nationsList.size() << " nations";
2762   QList<Nationality*>::iterator nationsIt = nationsList.begin();
2763   for (; nationsIt != nationsList.end(); nationsIt++ ) 
2764   {
2765     Nationality* nation = *nationsIt;
2766     qCDebug(KSIRK_LOG) << "Nation '" << nation->name() << "' = " << nation;
2767     res.insert(nation->name(),nation->flagFileName());
2768   } 
2769   return res;
2770 }
2771 
2772 /** @return true if the given player is the last one ; false otherwise */
2773 bool KGameWindow::isLastPlayer(const Player& player)
2774 {
2775   if (m_automaton->playerList()->begin() == m_automaton->playerList()->end())
2776   {
2777     qCCritical(KSIRK_LOG) << "No player ; should not be able to call isLastPlayer !";
2778     exit(1);
2779   }
2780   PlayersArray::iterator it = m_automaton->playerList()->end();
2781   //  it--;
2782   Player* lastPlayer = static_cast<Player*>(*it);
2783   return (player == (*lastPlayer));
2784 }
2785 
2786 void KGameWindow::actionRecycling()
2787 {
2788   qCDebug(KSIRK_LOG) << "KGameWindow::actionRecycling";
2789   setCurrentPlayerToFirst();
2790   QByteArray buffer;
2791   QDataStream stream(&buffer, QIODevice::WriteOnly);
2792   m_automaton->sendMessage(buffer,StartLocalCurrentAI);
2793   QByteArray buffer2;
2794   QDataStream stream2(&buffer2, QIODevice::WriteOnly);
2795   stream2 << currentPlayer()->name();
2796   stream2 << (quint32)0;
2797   qCDebug(KSIRK_LOG) << "sending DisplayRecycleDetails "
2798     << currentPlayer()->name() << 0
2799     << " at " << __FILE__ << ", line " << __LINE__;
2800   m_automaton->sendMessage(buffer2,DisplayRecycleDetails);
2801 
2802   QPixmap pm = currentPlayer()->getFlag()->image(0);
2803 }
2804 
2805 void KGameWindow::actionRecyclingFinished()
2806 {
2807   qCDebug(KSIRK_LOG);
2808   getRightDialog()->close();
2809   if (m_automaton->isAdmin())
2810   {
2811     setCurrentPlayerToFirst();
2812     distributeArmies();
2813 
2814     QByteArray buffer;
2815     m_automaton->sendMessage(buffer,ShowArmiesToPlace);
2816 
2817     clear();
2818     QByteArray buffer2;
2819     m_automaton->sendMessage(buffer2,StartLocalCurrentAI);
2820 
2821     QByteArray buffer3;
2822     QDataStream stream3(&buffer3, QIODevice::WriteOnly);
2823     stream3 << currentPlayer()-> name();
2824     stream3 << (quint32)nbNewArmies(currentPlayer());
2825     qCDebug(KSIRK_LOG) << "sending DisplayRecycleDetails "
2826         << currentPlayer()->name() << nbNewArmies(currentPlayer())
2827         << " at " << __FILE__ << ", line " << __LINE__;
2828     m_automaton->sendMessage(buffer3,DisplayRecycleDetails);
2829     m_automaton->state(GameLogic::GameAutomaton::NEWARMIES);
2830   }
2831 }
2832 
2833 void KGameWindow::finishMoves()
2834 {
2835   qCDebug(KSIRK_LOG);
2836   m_animFighters->moveAllToDestinationNow();
2837 }
2838 
2839 void KGameWindow::displayButtonsForState(GameAutomaton::GameState state)
2840 {
2841   QByteArray buffer;
2842   QDataStream stream(&buffer, QIODevice::WriteOnly);
2843   switch (state)
2844   {
2845   case GameLogic::GameAutomaton::WAIT:;
2846     m_automaton->sendMessage(buffer,ClearHighlighting);
2847     break;
2848   case GameLogic::GameAutomaton::WAIT_RECYCLING:;
2849     m_automaton->sendMessage(buffer,StartLocalCurrentAI);
2850     break;
2851   case GameLogic::GameAutomaton::NEWARMIES:;
2852     m_automaton->sendMessage(buffer,StartLocalCurrentAI);
2853     break;
2854   case GameLogic::GameAutomaton::INIT:;
2855     break;
2856   case GameLogic::GameAutomaton::INTERLUDE:;
2857     break;
2858   case GameLogic::GameAutomaton::ATTACK:;
2859     break;
2860   case GameLogic::GameAutomaton::ATTACK2:;
2861     break;
2862   case GameLogic::GameAutomaton::INVADE:;
2863     break;
2864   case GameLogic::GameAutomaton::SHIFT1:;
2865     break;
2866   case GameLogic::GameAutomaton::SHIFT2:;
2867     break;
2868   case GameLogic::GameAutomaton::FIGHT_BRING:;
2869     break;
2870   case GameLogic::GameAutomaton::FIGHT_ANIMATE:;
2871     break;
2872   case GameLogic::GameAutomaton::FIGHT_BRINGBACK:;
2873     break;
2874   case GameLogic::GameAutomaton::WAITDEFENSE:;
2875     break;
2876   case GameLogic::GameAutomaton::EXPLOSION_ANIMATE:;
2877     break;
2878     
2879   default: 
2880     m_automaton->sendMessage(buffer,ClearHighlighting);
2881   }
2882 }
2883 
2884 void KGameWindow::optionsConfigure()
2885 {
2886   //An instance of your dialog could be already created and could be cached, 
2887   //in which case you want to display the cached dialog instead of creating 
2888   //another one 
2889   if ( KsirkConfigurationDialog::showDialog( "settings" ) ) 
2890     return; 
2891  
2892   //KConfigDialog didn't find an instance of this dialog, so lets create it : 
2893   KsirkConfigurationDialog* dialog = new KsirkConfigurationDialog( this, "settings", 
2894                                              KsirkSettings::self() ); 
2895 
2896   connect(dialog, &KsirkConfigurationDialog::armiesNumberShowingChanged,
2897           this, &KGameWindow::slotArmiesNumberChanged);
2898 
2899   dialog->show();
2900 }
2901 
2902 void KGameWindow::explain()
2903 {
2904   KMessageParts message0Parts;
2905   message0Parts << kli18n("<b>KsirK quick Introduction</b>").untranslatedText();
2906   broadcastChangeItem(message0Parts, ID_NO_STATUS_MSG);
2907 
2908   KMessageParts message1Parts;
2909   message1Parts << kli18n("Attacks and moves are issued through drag & drop between neighbour countries.").untranslatedText();
2910   broadcastChangeItem(message1Parts, ID_NO_STATUS_MSG);
2911 
2912   KMessageParts message2Parts;
2913   message2Parts << kli18n("Start a new game or join a network game with the menu or the toolbar...").untranslatedText();
2914   broadcastChangeItem(message2Parts, ID_NO_STATUS_MSG);
2915 
2916   KMessageParts message5Parts;
2917   message5Parts << kli18n("and then let the system guide you through messages and tooltips appearing on buttons when hovering above them. You can disable bubble help in the options window.").untranslatedText();
2918   broadcastChangeItem(message5Parts, ID_NO_STATUS_MSG);
2919 }
2920 
2921 void KGameWindow::showMessage(const QString& message, quint32 delay, MessageShowingType forcing)
2922 {
2923   qCDebug(KSIRK_LOG);
2924   QString lmessage = message + "<br><a href=\"dontshowagain\">"+i18n("Don't show messages anymore") + "</a>";
2925   if(KsirkSettings::helpEnabled() || forcing == ForceShowing)
2926   {
2927     if (m_message == nullptr)
2928     {
2929       qCDebug(KSIRK_LOG) << "Creating KGamePopupItem";
2930       m_message  = new KGamePopupItem();
2931       connect(m_message, &KGamePopupItem::linkActivated, this, &KGameWindow::slotDisableHelp);
2932       m_scene_world->addItem(m_message);
2933       m_message->setSharpness(KGamePopupItem::Soft);
2934       m_message->setZValue(1000);
2935     }
2936     m_message->setMessageTimeout(delay*1000);
2937     m_message->showMessage(lmessage, KGamePopupItem::TopLeft, KGamePopupItem::ReplacePrevious);
2938 
2939 //   m_message->setPos(m_frame-> mapToScene(QPoint(30,30)));
2940   }
2941 }
2942 
2943 
2944 void KGameWindow::firstCountry(GameLogic::Country* country)
2945 {
2946   qCDebug(KSIRK_LOG) << (void*)country;
2947   if (m_firstCountry != nullptr)
2948   {
2949     m_firstCountry->releaseHighlightingLock();
2950     m_firstCountry->clearHighlighting();
2951   }
2952   m_firstCountry = country;
2953   if (country == nullptr)
2954   {
2955     return;
2956   }
2957   qCDebug(KSIRK_LOG) << country->name();
2958   country->highlightAsAttacker();
2959 }
2960 
2961 void KGameWindow::secondCountry(GameLogic::Country* country)
2962 {
2963   if (m_secondCountry != nullptr)
2964   {
2965     m_secondCountry->clearHighlighting();
2966   }
2967   m_secondCountry = country;
2968   if (country == nullptr)
2969   {
2970     return;
2971   }
2972   qCDebug(KSIRK_LOG) << country->name();
2973   country->highlightAsDefender();
2974 }
2975 
2976 
2977 GameLogic::Country* KGameWindow::firstCountry()
2978 {
2979   if (m_currentDisplayedWidget == Arena) {
2980      return m_arena->countryAttack();
2981   }
2982   return m_firstCountry;
2983 }
2984 
2985 
2986 GameLogic::Country* KGameWindow::secondCountry()
2987 {
2988   if (m_currentDisplayedWidget == Arena) {
2989     return m_arena->countryDefense();
2990   }
2991   return m_secondCountry;
2992 }
2993 
2994 
2995 void KGameWindow::showArena()
2996 {
2997   qCDebug(KSIRK_LOG);
2998   if (m_currentDisplayedWidget != Arena)
2999   {
3000     // synchronize the arena countries
3001     m_currentDisplayedWidget = Arena;
3002     m_arena->initFightArena(m_firstCountry,m_secondCountry,m_backGnd_arena);
3003   }
3004   qCDebug(KSIRK_LOG) << "before setCurrentIndex";
3005   m_centralWidget->setCurrentIndex(ARENA_INDEX);
3006 }
3007 
3008 
3009 void KGameWindow::showMap()
3010 {
3011   qCDebug(KSIRK_LOG);
3012   m_centralWidget->setCurrentIndex(MAP_INDEX);
3013   m_currentDisplayedWidget = Map;
3014   statusBar()->show();
3015   m_zoomInAction->setEnabled(true);
3016   m_zoomOutAction->setEnabled(true);
3017 }
3018 
3019 void KGameWindow::showMainMenu()
3020 {
3021   qCDebug(KSIRK_LOG);
3022   m_centralWidget->setCurrentIndex(MAINMENU_INDEX);
3023   m_currentDisplayedWidget = MainMenu;
3024 }
3025 
3026 
3027 KGameWindow::WidgetType KGameWindow::currentWidgetType()
3028 {
3029   return m_currentDisplayedWidget;
3030 }
3031 
3032 
3033 QGraphicsView* KGameWindow::currentWidget()
3034 {
3035   switch (currentWidgetType())
3036   {
3037     case Arena:
3038       return dynamic_cast <QGraphicsView*>(arena());
3039       break;
3040     case MainMenu:
3041       return nullptr;
3042       break;
3043     case Map:
3044       return dynamic_cast <QGraphicsView*>(frame());
3045       break;
3046     default:
3047       return nullptr;
3048   }
3049   return nullptr;
3050 }
3051 
3052 
3053 BackGnd* KGameWindow::backGnd() {
3054   if (currentWidgetType() == Arena) {
3055     return backGndArena();
3056   } else {
3057     return backGndWorld();
3058   }
3059 }
3060 
3061 void KGameWindow::slideInvade(GameLogic::Country * attack, GameLogic::Country * defender, InvasionSlider::InvasionType invasionType)
3062 {
3063   if (m_wSlide != nullptr)
3064   {
3065     m_wSlide->hide();
3066     delete m_wSlide;
3067   }
3068   m_wSlide = new InvasionSlider(this,attack,defender,invasionType);
3069   m_wSlide->show();
3070 }
3071 
3072 bool KGameWindow::isArena()
3073 {
3074   return m_useArena;
3075 }
3076 
3077 void KGameWindow::reduceChat()
3078 {
3079   qCDebug(KSIRK_LOG);
3080   m_chatIsReduced = true;
3081 
3082   m_lastWidthChat = m_bottomDock->width();
3083 
3084   // reduce the chat
3085   QPixmap upChatReducePix(QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + "/Images/upArrow.png"));
3086   m_reduceChatButton->setIcon(upChatReducePix);
3087   m_chatDlg->hide();
3088   m_titleChatMsg->show();
3089 }
3090 
3091 void KGameWindow::unreduceChat()
3092 {
3093   qCDebug(KSIRK_LOG);
3094   m_chatIsReduced = false;
3095 
3096   // restore the chat
3097   QPixmap downChatReducePix(QStandardPaths::locate(QStandardPaths::AppDataLocation, m_automaton->skin() + "/Images/downArrow.png"));
3098   m_reduceChatButton->setIcon(downChatReducePix);
3099   m_chatDlg->show();
3100   m_titleChatMsg->hide();
3101   m_bottomDock->setMaximumSize(16777215,16777215);
3102   m_bottomDock->resize(m_lastWidthChat,38+m_chatDlg->height());
3103 }
3104 
3105 void KGameWindow::setNextPlayerActionEnabled(bool value)
3106 {
3107   qCDebug(KSIRK_LOG) << value;
3108   m_nextPlayerAction->setEnabled(value);
3109 }
3110 
3111 void KGameWindow::setSaveGameActionEnabled(bool value)
3112 {
3113   qCDebug(KSIRK_LOG) << value;
3114   m_saveGameAction->setEnabled(value);
3115 }
3116 
3117 void KGameWindow::setContextualHelpActionEnabled(GameLogic::GameAutomaton::GameState gameState, bool isPlayerAI)
3118 {
3119   qCDebug(KSIRK_LOG) << isPlayerAI << gameState;
3120   bool enabled = (gameState == GameLogic::GameAutomaton::WAIT || gameState == GameLogic::GameAutomaton::NEWARMIES || gameState == GameLogic::GameAutomaton::INTERLUDE) &&
3121                  !isPlayerAI &&
3122                  KsirkSettings::helpEnabled();
3123   m_contextualHelpAction->setEnabled(enabled);
3124 }
3125 
3126 void KGameWindow::setupPopupMessage()
3127 {
3128   if (m_message == nullptr)
3129   {
3130     qCDebug(KSIRK_LOG);
3131     m_message  = new KGamePopupItem();
3132     connect(m_message, &KGamePopupItem::linkActivated, this, &KGameWindow::slotDisableHelp);
3133     m_scene_world->addItem(m_message);
3134     m_message->setSharpness(KGamePopupItem::Soft);
3135     QColor color = QColor(102,102,255);
3136     m_message->setBackgroundBrush(color);
3137     m_message->setZValue(1000);
3138   }
3139 }
3140 
3141 bool KGameWindow::newGameDialog(const QString& skin, GameAutomaton::NetworkGameType netGameType)
3142 {
3143   qCDebug(KSIRK_LOG) << "state is" << m_automaton->stateName();
3144   m_automaton->setGameStatus( KGame::Pause );
3145   m_stateBeforeNewGame = m_automaton->state();
3146   m_automaton->state(GameAutomaton::STARTING_GAME);
3147   m_rightDock->hide();
3148   statusBar()->hide();
3149   m_zoomInAction->setEnabled(false);
3150   m_zoomOutAction->setEnabled(false);
3151   m_nextPlayerAction->setEnabled(false);
3152   m_goalAction->setVisible(false);;
3153   m_newGameDialog->init(skin, netGameType);
3154   m_stackWidgetBeforeNewGame = m_centralWidget->currentIndex();
3155   m_centralWidget->setCurrentIndex(NEWGAME_INDEX);
3156   return false;
3157 }
3158 
3159 #if HAVE_JABBER_SUPPORT
3160 /* Set presence (usually called by dialog widget). */
3161 void KGameWindow::setPresence ( const XMPP::Status &status )
3162 {
3163   qCDebug(KSIRK_LOG) << "Status: " << status.show () << ", Reason: " << status.status ();
3164   
3165   // fetch input status
3166   XMPP::Status newStatus = status;
3167   
3168   // TODO: Check if Caps is enabled
3169   // Send entity capabilities
3170   if( m_jabberClient )
3171   {
3172     newStatus.setCapsNode( m_jabberClient->capsNode() );
3173     newStatus.setCapsVersion( m_jabberClient->capsVersion() );
3174     newStatus.setCapsExt( m_jabberClient->capsExt() );
3175   }
3176   
3177   // make sure the status gets the correct priority
3178   newStatus.setPriority ( 5 );
3179   
3180 /*  XMPP::Jid jid ( this->contactId() );
3181   XMPP::Resource newResource ( resource (), newStatus );
3182   
3183   // update our resource in the resource pool
3184   resourcePool()->addResource ( jid, newResource );
3185   
3186   // make sure that we only consider our own resource locally
3187   resourcePool()->lockToResource ( jid, newResource );*/
3188   
3189   /*
3190   * Unless we are in the connecting status, send a presence packet to the server
3191   */
3192   if(status.show () != QString("connecting") )
3193   {
3194     /*
3195     * Make sure we are actually connected before sending out a packet.
3196     */
3197     if (true/*isConnected()*/)
3198     {
3199       qCDebug(KSIRK_LOG) << "Sending new presence to the server.";
3200       
3201       XMPP::JT_Presence * task = new XMPP::JT_Presence ( m_jabberClient->rootTask ());
3202       
3203       task->pres ( newStatus );
3204       task->go ( true );
3205     }
3206     else
3207     {
3208       qCDebug(KSIRK_LOG) << "We were not connected, presence update aborted.";
3209     }
3210   }
3211   
3212 }
3213 
3214 void KGameWindow::askForJabberGames()
3215 {
3216   if (m_jabberClient && m_jabberClient->isConnected())
3217   {
3218     XMPP::Message message(QString(m_groupchatRoom+'@'+m_groupchatHost));
3219     message.setType("groupchat");
3220     message.setId(QUuid::createUuid().toString().remove('{').remove('}').remove('-'));
3221     QString body("Who propose online KsirK games here?");
3222     message.setBody(body);
3223     qCDebug(KSIRK_LOG) << "Sending message: <<" << body << ">> to" << (m_groupchatRoom+'@'+m_groupchatHost);
3224     m_jabberClient->sendMessage(message);
3225   }
3226 }
3227 
3228 void KGameWindow::sendGameInfoToJabber()
3229 {
3230   qCDebug(KSIRK_LOG);
3231   if (m_jabberClient
3232     && m_jabberClient->isConnected()
3233     && m_automaton->startingGame())
3234   {
3235     qCDebug(KSIRK_LOG) << "Sending 'I'm starting a game with ...'";
3236     XMPP::Message message(QString(m_groupchatRoom+'@'+m_groupchatHost));
3237     message.setType("groupchat");
3238     message.setId(QUuid::createUuid().toString().remove('{').remove('}').remove('-'));
3239     QString body;
3240     QTextStream qts(&body);
3241     qts <<"I'm starting a game with skin '" << m_automaton->skin() << "' and '" << m_automaton->nbPlayers() << "' players";
3242     message.setBody(body);
3243     qCDebug(KSIRK_LOG) << "Sending message: <<" << body << ">> to" << (m_groupchatRoom+'@'+m_groupchatHost);
3244     m_jabberClient->sendMessage(message);
3245   }
3246 }
3247 #endif
3248 
3249 void KGameWindow::joinNetworkGame()
3250 {
3251   qCDebug(KSIRK_LOG);
3252   /// @TODO show the network connect screen
3253   m_centralWidget->setCurrentIndex(TCPCONNECT_INDEX);
3254 }
3255 
3256 void KGameWindow::updateNewGameSummary()
3257 {
3258   qCDebug(KSIRK_LOG);
3259   m_newGameSummaryWidget->show(this);
3260 }
3261 
3262 void KGameWindow::showNewGameSummary()
3263 {
3264   qCDebug(KSIRK_LOG);
3265   m_centralWidget->setCurrentIndex(NEWGAMESUMMARY_INDEX);
3266 }
3267 
3268 } // closing namespace Ksirk
3269 
3270 #include "moc_kgamewin.cpp"