initial commit, lordsawar source, slightly modified
[lordsawar] / src / NextTurnNetworked.cpp
1 // Copyright (C) 2003, 2004, 2005 Ulf Lorenz
2 // Copyright (C) 2007, 2008 Ben Asselstine
3 // Copyright (C) 2007, 2008 Ole Laursen
4 //
5 //  This program is free software; you can redistribute it and/or modify
6 //  it under the terms of the GNU General Public License as published by
7 //  the Free Software Foundation; either version 3 of the License, or
8 //  (at your option) any later version.
9 //
10 //  This program is distributed in the hope that it will be useful,
11 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 //  GNU Library General Public License for more details.
14 //
15 //  You should have received a copy of the GNU General Public License
16 //  along with this program; if not, write to the Free Software
17 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
18 //  02110-1301, USA.
19
20 #include "NextTurnNetworked.h"
21
22 #include "playerlist.h"
23 #include "citylist.h"
24 #include "ruinlist.h"
25 #include "stacklist.h"
26 #include "armysetlist.h"
27 #include "hero.h"
28 #include "vectoredunitlist.h"
29 #include "FogMap.h"
30 #include "history.h"
31 #include "QuestsManager.h"
32 #include "network_player.h"
33 #include "game-server.h"
34 #include "game-client.h"
35 #include "GameScenarioOptions.h"
36
37 #include "path.h"
38
39 using namespace std;
40 #define debug(x) {cerr<<__FILE__<<": "<<__LINE__<<": "<<x<<flush<<endl;}
41 //#define debug(x)
42
43 NextTurnNetworked::NextTurnNetworked(bool turnmode, bool random_turns)
44     :NextTurn(turnmode, random_turns)
45 {
46   Playerlist* plist = Playerlist::getInstance();
47   for (Playerlist::iterator i = plist->begin(); i != plist->end(); ++i) {
48     Player *p = *i;
49     p->ending_turn.connect(sigc::mem_fun(this, &NextTurn::endTurn));
50   }
51 }
52
53 NextTurnNetworked::~NextTurnNetworked()
54 {
55 }
56
57 void NextTurnNetworked::start()
58 {
59     //We need the playerlist a lot, so maintain a copy of it.
60     Playerlist* plist = Playerlist::getInstance();
61
62     //set first player as active if no active player exists
63     if (!plist->getActiveplayer())
64         nextPlayer();
65         
66     if (plist->getActiveplayer()->isDead())
67       nextPlayer();
68
69     if (plist->getActiveplayer()->isDead())
70       return;
71
72     if (plist->getActiveplayer()->getType() != Player::NETWORKED)
73       {
74         while (!d_stop)
75           {
76             supdating.emit();
77
78             startTurn();
79
80             // inform everyone about the next turn 
81             snextTurn.emit(plist->getActiveplayer());
82
83             if (plist->getNoOfPlayers() <= 2)
84               {
85                 if (plist->checkPlayers()) //end of game detected
86                   return;
87               }
88
89             splayerStart.emit(plist->getActiveplayer());
90
91             // let the player do his or her duties...
92             bool continue_loop = plist->getActiveplayer()->startTurn();
93             if (!continue_loop)
94               return;
95
96             //Now do some cleanup at the end of the turn.
97             finishTurn();
98
99             //...and initiate the next one.
100             nextPlayer();
101
102
103             //if it is the first player's turn now, a new round has started
104             if (Playerlist::getInstance()->getActiveplayer() == 
105                 Playerlist::getInstance()->getFirstLiving())
106               {
107                 //if (GameServer::getInstance()->isListening() == true)
108                   {
109                     if (plist->checkPlayers() == true)
110                       {
111                         if (plist->getNoOfPlayers() <= 1)
112                           break;
113                         if (plist->getActiveplayer()->isDead())
114                           nextPlayer();
115                       }
116                     finishRound();
117                     snextRound.emit();
118                     if (GameServer::getInstance()->isListening() == false)
119                       GameClient::getInstance()->sendRoundOver();
120                   }
121                 //both client and server exit this loop at the end of the round
122                 break;
123               }
124             if (Playerlist::getInstance()->getActiveplayer()->getType() == Player::NETWORKED)
125               break;
126           }
127       }
128     if (d_stop == true)
129       {
130         Player *active = Playerlist::getInstance()->getActiveplayer();
131         if (active->getType() == Player::NETWORKED &&
132             Playerlist::getInstance()->getNeutral() != active)
133           {
134             NetworkPlayer *player = dynamic_cast<NetworkPlayer*>(active);
135             if (player->isConnected() == false)
136               snextPlayerUnavailable.emit(active);
137           }
138       }
139 }
140
141 void NextTurnNetworked::endTurn()
142 {
143   // Finish off the player and transfers the control to the start function
144   // again.
145   finishTurn();
146   nextPlayer();
147
148   if (Playerlist::getActiveplayer() == Playerlist::getInstance()->getFirstLiving())
149     {
150       //if (GameServer::getInstance()->isListening() == true)
151         //{
152           finishRound();
153           snextRound.emit();
154           if (GameServer::getInstance()->isListening() == false)
155             GameClient::getInstance()->sendRoundOver();
156         //}
157       return;
158     }
159
160   start();
161 }
162
163 void NextTurnNetworked::startTurn()
164 {
165   //this function is called before a player starts his turn. Some
166   //items you could imagine to be placed here: healing/building
167   //units, check for joining heroes...
168
169   //a shortcut
170   Player* p = Playerlist::getActiveplayer();
171
172   //here we check to see if the player is about to start a new turn
173   //we do this check to see if we're re-sitting down again in the game lobby
174   //we want to prevent offering the player another hero, etc.
175   if (p->hasAlreadyInitializedTurn() && p->hasAlreadyEndedTurn() == false)
176     return;
177   p->initTurn();
178
179   //calculate upkeep and income
180   p->calculateUpkeep();
181   p->calculateIncome();
182
183   //if turnmode is set, create/heal armies at player's turn
184   if (d_turnmode)
185     {
186
187       //if (p->getType() != Player::NETWORKED)
188
189       //collect taxes
190       Citylist::getInstance()->collectTaxes(p);
191
192       guint32 num_cities = Citylist::getInstance()->countCities(p);
193       p->getStacklist()->collectTaxes(p, num_cities);
194
195       //vector armies (needs to preceed city's next turn)
196       VectoredUnitlist::getInstance()->nextTurn(p);
197
198       //pay upkeep for existing stacks
199       p->getStacklist()->payUpkeep(p);
200
201       //reset moves, and heal stacks
202       p->getStacklist()->nextTurn();
203
204       //build new armies
205       Citylist::getInstance()->nextTurn(p);
206
207     }
208   p->calculateUpkeep();
209
210   QuestsManager::getInstance()->nextTurn(p);
211 }
212
213 void NextTurnNetworked::finishTurn()
214 {
215   //Put everything that has to be done before the next player starts
216   //his turn here. E.g. one could clear some caches.
217   Player *p = Playerlist::getActiveplayer();
218   p->getFogMap()->smooth();
219   p->endTurn();
220 }
221
222 void NextTurnNetworked::finishRound()
223 {
224   Playerlist *plist = Playerlist::getInstance();
225   //Put everything that has to be done when a new round starts in here.
226   //E.g. increase the round number in GameScenario. (this is done with
227   //the snextRound signal, but useful for an example).
228
229   if (!d_turnmode)
230     {
231       //do this for all players at once
232
233       for (Playerlist::iterator it = plist->begin(); it != plist->end(); it++)
234         {
235           if ((*it)->isDead())
236             continue;
237
238           //collect monies from cities
239           Citylist::getInstance()->collectTaxes(*it);
240
241           guint32 num_cities = Citylist::getInstance()->countCities(*it);
242           (*it)->getStacklist()->collectTaxes((*it), num_cities);
243
244           //vector armies (needs to preceed city's next turn)
245           VectoredUnitlist::getInstance()->nextTurn(*it);
246
247           //pay for existing armies
248           (*it)->getStacklist()->payUpkeep(*it);
249
250           //reset, and heal armies
251           (*it)->getStacklist()->nextTurn();
252
253           //produce new armies
254           Citylist::getInstance()->nextTurn(*it);
255
256         }
257     }
258
259   // heal the stacks in the ruins
260   Ruinlist* rl = Ruinlist::getInstance();
261   for (Ruinlist::iterator it = rl->begin(); it != rl->end(); it++)
262     {
263       Stack* keeper = (*it)->getOccupant();
264       if (keeper)
265         keeper->nextTurn();
266     }
267
268   if (d_random_turns)
269     {
270       plist->randomizeOrder();
271       nextPlayer();
272     }
273
274 }